From 73116554b1d4e4faf9add7acd24e6dc4047d8f00 Mon Sep 17 00:00:00 2001 From: juacrumar Date: Sun, 12 Jun 2022 13:08:34 +0200 Subject: [PATCH 1/2] isolating components --- setup.py | 23 ++++++++++++++--------- src/pybliotecario/pybliotecario.py | 5 ++++- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/setup.py b/setup.py index a4c80b1..65f8a87 100644 --- a/setup.py +++ b/setup.py @@ -14,6 +14,19 @@ # Remove it from the list of argument, nobody should know sys.argv.remove("--with_name") +target_dependencies = { + "facebook": ["flask", "requests_toolbelt"], + "stonks": ["yahoo-fin", "pandas"], + "arxiv": ["arxiv"], + "weather": ["pyowm"], + "wiki": ["wikipedia"], + "github": ["pygithub"], + "twitter": ["tweepy"], +} + +# Create a special target for full +target_dependencies["full"] = set().union(*target_dependencies.values()) + # Readup the readme README = (pathlib.Path(__file__).parent / "readme.md").read_text() setup( @@ -32,17 +45,9 @@ "numpy", "requests", "regex", - "arxiv", - "pyowm", "psutil", - "wikipedia", - "pygithub", - "tweepy" ], - extras_require={ - "facebook": ["flask", "requests_toolbelt"], - "stonks": ["yahoo-fin", "pandas"], - }, + extras_require=target_dependencies, entry_points={ "console_scripts": [ "{0} = pybliotecario.pybliotecario:main".format(pybliotecario_name), diff --git a/src/pybliotecario/pybliotecario.py b/src/pybliotecario/pybliotecario.py index 8b9f41c..cc064a4 100755 --- a/src/pybliotecario/pybliotecario.py +++ b/src/pybliotecario/pybliotecario.py @@ -116,7 +116,10 @@ def main(cmdline_arg=None, tele_api=None, config=None): if chat_id is not None: config.set("DEFAULT", "chat_id", chat_id) - on_cmdline.run_command(args, tele_api, config) + try: + on_cmdline.run_command(args, tele_api, config) + except ModuleNotFoundError as e: + logger.error("In order to use this option you need to install the module '%s'", e.name) if args.daemon: logger.info("Activating main loop") From e971e650d4dd033c4b7b116e7c5c07057ca58f6f Mon Sep 17 00:00:00 2001 From: juacrumar Date: Sun, 12 Jun 2022 13:30:15 +0200 Subject: [PATCH 2/2] make sure the the failures are gracious --- setup.py | 3 +- src/pybliotecario/backend/backend_test.py | 4 +- src/pybliotecario/components/arxiv_mod.py | 5 +- src/pybliotecario/components/dnd.py | 3 +- src/pybliotecario/components/system.py | 3 +- src/pybliotecario/components/twitter.py | 3 +- src/pybliotecario/components/wiki.py | 7 +-- src/pybliotecario/on_cmd_message.py | 69 ++++++++++++----------- 8 files changed, 49 insertions(+), 48 deletions(-) diff --git a/setup.py b/setup.py index 65f8a87..f91880a 100644 --- a/setup.py +++ b/setup.py @@ -22,6 +22,7 @@ "wiki": ["wikipedia"], "github": ["pygithub"], "twitter": ["tweepy"], + "tests": ["numpy"] } # Create a special target for full @@ -42,9 +43,7 @@ package_dir={"": "src"}, packages=find_packages("src"), install_requires=[ - "numpy", "requests", - "regex", "psutil", ], extras_require=target_dependencies, diff --git a/src/pybliotecario/backend/backend_test.py b/src/pybliotecario/backend/backend_test.py index 83c0cb0..6904c0c 100644 --- a/src/pybliotecario/backend/backend_test.py +++ b/src/pybliotecario/backend/backend_test.py @@ -5,7 +5,6 @@ import pathlib from datetime import datetime -import numpy as np from pybliotecario.backend.telegram_util import TelegramMessage @@ -20,6 +19,9 @@ class TestMessage(TelegramMessage): def _create_fake_msg(text): + """Create fake messages for testing""" + import numpy as np + ret = { "update_id": np.random.randint(1000), "message": { diff --git a/src/pybliotecario/components/arxiv_mod.py b/src/pybliotecario/components/arxiv_mod.py index 43996b4..927e8ba 100644 --- a/src/pybliotecario/components/arxiv_mod.py +++ b/src/pybliotecario/components/arxiv_mod.py @@ -42,9 +42,8 @@ def query_recent(category): results = arxiv.Search( query=category, max_results=75, sort_by=arxiv.SortCriterion.LastUpdatedDate ).results() - indx = -1 elements = [] - for i, element in enumerate(results): + for _, element in enumerate(results): time_s = element.updated if not is_today(time_s): break @@ -149,7 +148,7 @@ class Arxiv(Component): help_text = """ > Arxiv module /arxiv arxiv_id: sends information about the given id - /arxiv_get arxiv_id: sends the PDF for the given id """ + /arxiv_get arxiv_id: sends the PDF for the given id""" def __init__(self, telegram_object, configuration=None, **kwargs): super().__init__(telegram_object, configuration=configuration, **kwargs) diff --git a/src/pybliotecario/components/dnd.py b/src/pybliotecario/components/dnd.py index b07dbfa..16290e1 100644 --- a/src/pybliotecario/components/dnd.py +++ b/src/pybliotecario/components/dnd.py @@ -87,8 +87,7 @@ def roll_dice(text): class DnD(Component): help_text = """ > DnD module - /r, /roll dice [text]: roll a dice in the format NdM+Mod - """ + /r, /roll dice [text]: roll a dice in the format NdM+Mod""" section_name = "DnD" default_roll = "1d20" diff --git a/src/pybliotecario/components/system.py b/src/pybliotecario/components/system.py index 133cb34..ceae79d 100644 --- a/src/pybliotecario/components/system.py +++ b/src/pybliotecario/components/system.py @@ -23,8 +23,7 @@ def run_command(command): class System(Component): help_text = """ > System component - /system uptime: returns the uptime of the computer in which the bot lives - """ + /system uptime: returns the uptime of the computer in which the bot lives""" def __init__(self, telegram_object, **kwargs): super().__init__(telegram_object, **kwargs) diff --git a/src/pybliotecario/components/twitter.py b/src/pybliotecario/components/twitter.py index 741dd37..2c7ae87 100644 --- a/src/pybliotecario/components/twitter.py +++ b/src/pybliotecario/components/twitter.py @@ -86,8 +86,7 @@ class TwitterComponent(Component): > Twitter module /twitter_tl [@user] [N=20]: send the last N tweets from the TL [of user @user] /twitter_mentions [N=5]: send the last N mentions - /twitter_tweet : send a tweet - """ + /twitter_tweet : send a tweet""" def __init__(self, telegram_object, configuration=None, **kwargs): super().__init__(telegram_object, configuration=configuration, **kwargs) diff --git a/src/pybliotecario/components/wiki.py b/src/pybliotecario/components/wiki.py index 7648f2a..7307972 100644 --- a/src/pybliotecario/components/wiki.py +++ b/src/pybliotecario/components/wiki.py @@ -4,12 +4,12 @@ # TODO use the selected language -import regex +import re import wikipedia from pybliotecario.components.component_core import Component # log = logging.getLogger(__name__) -GET_N = regex.compile(r"^\d+") +GET_N = re.compile(r"^\d+") MAX_SIZE = 4000 WIKI_NAME = "WIKIPEDIA" DEFAULT_LANGUAGE = "EN" @@ -22,8 +22,7 @@ class WikiComponent(Component): help_text = """ > Wikipedia module /wiki term: search for term in wikipedia, return the summary - /wiki_full N term: read the full article and return N times the defined summary_size - """ + /wiki_full N term: read the full article and return N times the defined summary_size""" def __init__(self, telegram_object, configuration=None, **kwargs): super().__init__(telegram_object, configuration=configuration, **kwargs) diff --git a/src/pybliotecario/on_cmd_message.py b/src/pybliotecario/on_cmd_message.py index 04135e0..ce4972c 100644 --- a/src/pybliotecario/on_cmd_message.py +++ b/src/pybliotecario/on_cmd_message.py @@ -6,9 +6,6 @@ This is a design choice as this way it is not necessary to have all dependencies if you want to run only some submodules of the pybliotecario. """ - -import subprocess as sp -import os import logging import importlib @@ -33,12 +30,15 @@ def send_help(tele_api, chat_id): ("wiki", "WikiComponent"), ("system", "System"), ("stocks", "Stocks"), - ("twitter", "TwitterComponent") + ("twitter", "TwitterComponent"), ] full_help = [] for module, cls in components: - Actor = import_component(module, cls) - full_help.append(Actor.help_msg()) + try: + Actor = import_component(module, cls) + full_help.append(Actor.help_msg()) + except ModuleNotFoundError: + pass tele_api.send_message("\n".join(full_help), chat_id) return None @@ -50,32 +50,37 @@ def act_on_telegram_command(tele_api, message_obj, config): tg_command = message_obj.command chat_id = config["DEFAULT"]["chat_id"] - if tg_command == "ip": - from pybliotecario.components.ip_lookup import IpLookup as Actor - elif tg_command.lower() in ("is_pid_alive", "kill_pid"): - from pybliotecario.components.pid import ControllerPID as Actor - elif tg_command in ("arxiv_query", "arxiv", "arxivget", "arxiv_get"): - from pybliotecario.components.arxiv_mod import Arxiv as Actor - elif tg_command == "script": - from pybliotecario.components.scripts import Script as Actor - elif tg_command in ("r", "roll"): - from pybliotecario.components.dnd import DnD as Actor - elif tg_command in ("reaction_save", "reaction", "reaction_list"): - from pybliotecario.components.reactions import Reactions as Actor - elif tg_command[:4] == "wiki": - from pybliotecario.components.wiki import WikiComponent as Actor - elif tg_command == "system": - from pybliotecario.components.system import System as Actor - elif tg_command == "stock_price": - from pybliotecario.components.stocks import Stocks as Actor - elif tg_command.startswith("twitter_"): - from pybliotecario.components.twitter import TwitterComponent as Actor - - elif tg_command == "help": - return send_help(tele_api, chat_id) - else: - log.info("No actor declared for this command: {0}".format(tg_command)) - return None + try: + if tg_command == "ip": + from pybliotecario.components.ip_lookup import IpLookup as Actor + elif tg_command.lower() in ("is_pid_alive", "kill_pid"): + from pybliotecario.components.pid import ControllerPID as Actor + elif tg_command in ("arxiv_query", "arxiv", "arxivget", "arxiv_get"): + from pybliotecario.components.arxiv_mod import Arxiv as Actor + elif tg_command == "script": + from pybliotecario.components.scripts import Script as Actor + elif tg_command in ("r", "roll"): + from pybliotecario.components.dnd import DnD as Actor + elif tg_command in ("reaction_save", "reaction", "reaction_list"): + from pybliotecario.components.reactions import Reactions as Actor + elif tg_command[:4] == "wiki": + from pybliotecario.components.wiki import WikiComponent as Actor + elif tg_command == "system": + from pybliotecario.components.system import System as Actor + elif tg_command == "stock_price": + from pybliotecario.components.stocks import Stocks as Actor + elif tg_command.startswith("twitter_"): + from pybliotecario.components.twitter import TwitterComponent as Actor + + elif tg_command == "help": + return send_help(tele_api, chat_id) + else: + log.info("No actor declared for this command: {0}".format(tg_command)) + return None + + except ModuleNotFoundError as e: + log.error(f"The component {tg_command} raised the following error: {e}") + return tele_api.send_message(f"Dependencies for {tg_command} are missing", chat_id) actor_instance = Actor( tele_api,