From a5c9039fee9f6b69f4b45afa2a31c00c123a34bb Mon Sep 17 00:00:00 2001 From: "Phyks (Lucas Verney)" Date: Fri, 7 Oct 2016 04:29:33 +0200 Subject: [PATCH] Add conversation mode script Start to tackle #4. --- README.md | 25 +++++ cozyweboob/__init__.py | 2 + .../capabilities}/CapDocument.py | 0 .../capabilities}/__init__.py | 0 .../capabilities}/base.py | 0 cozyweboob.py => cozyweboob/cozyweboob.py | 2 +- {tools => cozyweboob/tools}/__init__.py | 0 {tools => cozyweboob/tools}/env.py | 0 {tools => cozyweboob/tools}/jsonwriter.py | 0 {tools => cozyweboob/tools}/progress.py | 0 {tools => cozyweboob/tools}/weboob_tools.py | 0 server.py | 21 ++-- stdin_conversation.py | 95 +++++++++++++++++++ 13 files changed, 137 insertions(+), 8 deletions(-) create mode 100644 cozyweboob/__init__.py rename {capabilities => cozyweboob/capabilities}/CapDocument.py (100%) rename {capabilities => cozyweboob/capabilities}/__init__.py (100%) rename {capabilities => cozyweboob/capabilities}/base.py (100%) rename cozyweboob.py => cozyweboob/cozyweboob.py (98%) rename {tools => cozyweboob/tools}/__init__.py (100%) rename {tools => cozyweboob/tools}/env.py (100%) rename {tools => cozyweboob/tools}/jsonwriter.py (100%) rename {tools => cozyweboob/tools}/progress.py (100%) rename {tools => cozyweboob/tools}/weboob_tools.py (100%) create mode 100755 stdin_conversation.py diff --git a/README.md b/README.md index e70b960..a759252 100644 --- a/README.md +++ b/README.md @@ -51,6 +51,31 @@ Note: You can specify the host and port to listen on using the `COZYWEBOOB_HOST` and `COZYWEBOOB_PORT` environment variables. +## Conversation script + +There is another command-line script available if you would rather communicate +with it in a conversation manner, using `stdin` and `stdout` (typically to +integrate it with Node modules using +[Python-shell](https://github.com/extrabacon/python-shell)). To run it, use: +```bash +./stdin_conversation.py +``` + +Then, you can write on `stdin` and fetch the responses from `stdout`. +Available commands are: +* `GET /list` to list all available modules. +* `GET /fetch JSON_PARAMS` where `JSON_PARAMS` is an input JSON for module + parameters. +* `exit` to quit the script and end the conversation. + +JSON responses are the same one as from the HTTP server script. It is +basically the same script without HTTP encapsulation. + +_Note_: To simplify the script, note that it only supports single line +commands. Then, your `JSON_PARAMS` should be the same single `stdin` line as +the `GET /fetch` part. + + ## Notes concerning all the available scripts Using `COZYWEBOOB_ENV=debug`, you can enable debug features for all of these diff --git a/cozyweboob/__init__.py b/cozyweboob/__init__.py new file mode 100644 index 0000000..680f889 --- /dev/null +++ b/cozyweboob/__init__.py @@ -0,0 +1,2 @@ +from .cozyweboob import WeboobProxy, main_fetch, main +__all__ = ["WeboobProxy", "main_fetch", "main"] diff --git a/capabilities/CapDocument.py b/cozyweboob/capabilities/CapDocument.py similarity index 100% rename from capabilities/CapDocument.py rename to cozyweboob/capabilities/CapDocument.py diff --git a/capabilities/__init__.py b/cozyweboob/capabilities/__init__.py similarity index 100% rename from capabilities/__init__.py rename to cozyweboob/capabilities/__init__.py diff --git a/capabilities/base.py b/cozyweboob/capabilities/base.py similarity index 100% rename from capabilities/base.py rename to cozyweboob/capabilities/base.py diff --git a/cozyweboob.py b/cozyweboob/cozyweboob.py similarity index 98% rename from cozyweboob.py rename to cozyweboob/cozyweboob.py index c5a3cb4..9fe1a32 100755 --- a/cozyweboob.py +++ b/cozyweboob/cozyweboob.py @@ -27,7 +27,7 @@ import tools.weboob_tools as weboob_tools # Dynamically load capabilities conversion modules # Dynamic loading is required to be able to call them programatically. -CAPABILITIES_CONVERSION_MODULES = importlib.import_module("capabilities") +CAPABILITIES_CONVERSION_MODULES = importlib.import_module("cozyweboob.capabilities") # Module specific logger logger = logging.getLogger(__name__) diff --git a/tools/__init__.py b/cozyweboob/tools/__init__.py similarity index 100% rename from tools/__init__.py rename to cozyweboob/tools/__init__.py diff --git a/tools/env.py b/cozyweboob/tools/env.py similarity index 100% rename from tools/env.py rename to cozyweboob/tools/env.py diff --git a/tools/jsonwriter.py b/cozyweboob/tools/jsonwriter.py similarity index 100% rename from tools/jsonwriter.py rename to cozyweboob/tools/jsonwriter.py diff --git a/tools/progress.py b/cozyweboob/tools/progress.py similarity index 100% rename from tools/progress.py rename to cozyweboob/tools/progress.py diff --git a/tools/weboob_tools.py b/cozyweboob/tools/weboob_tools.py similarity index 100% rename from tools/weboob_tools.py rename to cozyweboob/tools/weboob_tools.py diff --git a/server.py b/server.py index ac59dd0..1b840b4 100755 --- a/server.py +++ b/server.py @@ -9,17 +9,17 @@ from bottle import post, request, response, route, run from cozyweboob import main as cozyweboob from cozyweboob import WeboobProxy -from tools.env import is_in_debug_mode -from tools.jsonwriter import pretty_json +from cozyweboob.tools.env import is_in_debug_mode +from cozyweboob.tools.jsonwriter import pretty_json # Module specific logger logger = logging.getLogger(__name__) -@post("/") -def index(): +@post("/fetch") +def fetch_view(): """ - Main view, fetch from weboob modules. + Fetch from weboob modules. """ params = request.forms.get("params") response.content_type = "application/json" @@ -36,9 +36,9 @@ def list_view(): return pretty_json(proxy.list_modules()) -def main(): +def init(): """ - Main function + Init function """ # Debug only: Set logging level and format if is_in_debug_mode(): @@ -52,6 +52,13 @@ def main(): proxy = WeboobProxy() proxy.install_modules() logger.info("Starting server.") + + +def main(): + """ + Main function + """ + init() # Get host to listen on HOST = os.environ.get("COZYWEBOOB_HOST", "localhost") PORT = os.environ.get("COZYWEBOOB_PORT", 8080) diff --git a/stdin_conversation.py b/stdin_conversation.py new file mode 100755 index 0000000..335cbd9 --- /dev/null +++ b/stdin_conversation.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python2 +""" +Wrapper around weboob to be called from mode, in a conversation way, similar to +the +[Python-shell](https://github.com/Birch-san/python-shell/blob/9d8641dc1e55e808ba82d029f9920413ab63206f/test/python/conversation.py) +conversation example. +""" +import logging +import sys + +from cozyweboob import main as cozyweboob +from cozyweboob import WeboobProxy +from cozyweboob.tools.env import is_in_debug_mode +from cozyweboob.tools.jsonwriter import pretty_json + +# Module specific logger +logger = logging.getLogger(__name__) + + +def fetch_view(params): + """ + Fetch from weboob modules. + """ + return pretty_json(cozyweboob(params)) + + +def list_view(): + """ + List all available weboob modules and their configuration options. + """ + proxy = WeboobProxy() + return pretty_json(proxy.list_modules()) + + +def process_query(query): + """ + Process input query on the command-line. + + Args: + query: The query received on stdin. + Returns: + - A JSON response if a valid query is received. + - False if should exit. + - None if invalid query is received. + """ + query = query.strip() + if query == "GET /list": + # List modules view + logger.info("Calling /list view.") + return list_view() + elif query.startswith("GET /fetch"): + # Fetch modules view + logger.info("Calling /list view.") + params = query.split()[2] + return fetch_view(params) + elif query == "exit": + # Exit command + logger.info("Exiting.") + return False + else: + # Invalid query + logger.error("Invalid query, exiting: %s" % query) + return + + +def main(): + """ + Main function + """ + # Debug only: Set logging level and format + if is_in_debug_mode(): + logging.basicConfig( + format='%(levelname)s: %(message)s', + level=logging.INFO + ) + # Ensure all modules are installed and up to date before starting the + # server + logger.info("Ensuring all modules are installed and up to date.") + proxy = WeboobProxy() + proxy.install_modules() + logger.info("Starting server.") + while True: + line = sys.stdin.readline() + if not line: + break + response = process_query(line) + if response: + print(response) + else: + break + sys.stdout.flush() + + +if __name__ == "__main__": + main()