From de5549e43cc9e07292323d01b5ad62972058eae4 Mon Sep 17 00:00:00 2001 From: Christoph Stahl Date: Mon, 29 May 2017 14:55:11 +0200 Subject: [PATCH] Version 0.1.1 Default values are now shown in HTML-Form --- README.rst | 77 ++++++++++++++++++++++++++++++++++++++++ setup.py | 2 +- warped/actions.py | 1 + warped/samples/hooked.py | 2 +- warped/static/js/app.js | 14 ++++++-- 5 files changed, 92 insertions(+), 4 deletions(-) create mode 100644 README.rst diff --git a/README.rst b/README.rst new file mode 100644 index 0000000..2d0328b --- /dev/null +++ b/README.rst @@ -0,0 +1,77 @@ +WARPED - a Webbased frontend for ARgparser in Python +==================================================== + +``warped`` can be used to execute single Python file and Python modules. +It captures calls to the ``argparse`` module of Python and renders a web +GUI based on the options and arguments defined. It also displays the +output of the program inside the web GUI and allows you to stop, pause +and resume the program, as well as downloading the output. + +Install +------- + +Either get a stable version from PyPI, or install the current version +from git + +:: + + # Installation from PyPI + pip install warped + + # Installation from git + pip install git+https://git.k-fortytwo.de/christofsteel/warped/ + +Usage +----- + +:: + + warped [-h] [--port PORT] [--host HOST] [--module] file + + a Webbased frontend for ARgparse in Python + + positional arguments: + file File to run + + optional arguments: + -h, --help show this help message and exit + --port PORT, -p PORT The port to listen on (default 5000) + --host HOST The host to bind to (default 0.0.0.0) + --module, -m If set, loads a module instead of a file + +Sample +------ + +To test the capabilities of ``warped`` an example module was included. +You can run it like this: + +:: + + warped -m warped.samples.hooked + +Since ``warped`` also makes use of the argparse module, ``warped`` +itself can be //warped//. + +:: + + warped -m warped.hook + +How does it work? +----------------- + +When ``warped`` is executed, it starts a flask webserver. The javascript +of the website reads the ``/arguments`` resource of the server, where +the configuration of the argparser returned. In a seperate process the +given program is executed using the ``runpy`` library, redirecting +``sys.stdin`` and ``sys.stdout`` to a ``multiprocessing.Queue``, which +can be read by the warp process to display it via the web GUI. + +Additionally, ``warped`` adds an entry for ``argparse`` in the +``sys.modules`` list. Python looks first looks at this list, everytime a +module is imported, to avoid importing a module multiple times. This +custom ``argparse`` module behaves similar to the original ``argparse`` +module. In fact with the exception of the +``ArgumentParser.parse_args()`` method, it works exactly like the +original. Once the program calls the ``parse_args()`` method, it blocks +and waits for user interaction via the web GUI. Once the user submits +the data, the process continues. diff --git a/setup.py b/setup.py index 0aacb41..2c24e32 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,7 @@ from setuptools import setup, find_packages setup( name='warped', - version='0.1.0', + version='0.1.1', packages=find_packages(), url='https://git.k-fortytwo.de/christofsteel/warp', download_url = 'https://git.k-fortytwo.de/christofsteel/warped/archive/0.1.0.tar.gz', diff --git a/warped/actions.py b/warped/actions.py index 8ac0df5..8eee943 100644 --- a/warped/actions.py +++ b/warped/actions.py @@ -43,6 +43,7 @@ class Action(): internal_dict['dest'] = self.dest internal_dict['desc'] = self.desc internal_dict['checked'] = self.on_none if self.on_none is True or self.on_none is False else None + internal_dict['default'] = self.on_none if type(self.on_none) == str else None internal_dict['optional'] = self.optional internal_dict['is_const'] = self.const is not None internal_dict['type'] = self.type_function.__name__ diff --git a/warped/samples/hooked.py b/warped/samples/hooked.py index e0af362..4e55eb2 100644 --- a/warped/samples/hooked.py +++ b/warped/samples/hooked.py @@ -21,7 +21,7 @@ def main(): group3 = group2.add_mutually_exclusive_group() group3.add_argument('--three') group3.add_argument('--four') - bla.add_argument('--test', '-t', help="Blubb") + bla.add_argument('--test', '-t', help="Blubb", default="Blabla") bla.add_argument('--bla', action="store_true", default=True) bla.add_argument('--blubb', action="store_true") bla.add_argument('-f', action="append") diff --git a/warped/static/js/app.js b/warped/static/js/app.js index d729e6b..41a20c8 100644 --- a/warped/static/js/app.js +++ b/warped/static/js/app.js @@ -120,7 +120,10 @@ function createInputAction(action) { function disableAction(action) { return function () { console.log("disable"); - thisli = $('#action-' + action['uuid']); + var thisli = $('#action-' + action['uuid']); + var input = $('#action-' + action['uuid'] + ' input'); + thisli.attr('old_val', input.val()) + $('#action-' + action['uuid'] + ' input').val(action["default"]); thisli.prop('disabled', true).addClass('disabled'); delbutton = $('#action-' + action['uuid' + "button"]); delbutton.prop('disabled', true).addClass('disabled'); @@ -134,7 +137,13 @@ function disableAction(action) { function enableAction(action) { return function() { console.log("enable"); - thisli = $('#action-' + action['uuid']); + var thisli = $('#action-' + action['uuid']); + var oldval = thisli.attr('old_val'); + if (oldval !== undefined) { + var input = $('#action-' + action['uuid'] + ' input'); + thisli.oldval = input.val() + $('#action-' + action['uuid'] + ' input').val(oldval); + } thisli.prop('disabled', false).removeClass('disabled'); delbutton = $('#action-' + action['uuid' + "button"]); delbutton.prop('disabled', false).removeClass('disabled'); @@ -181,6 +190,7 @@ function createAction(action) { if(action.optional === true) { li.prop('disabled', true).addClass('disabled'); input.prop('disabled', true).addClass('disabled'); + input.val(action["default"]); input.find('input').prop('disabled', true).addClass('disabled'); input.find('.addbutton').prop('disabled', true).addClass('disabled'); input.find('.rembutton').prop('disabled', true).addClass('disabled');