mirror of
https://github.com/onionshare/onionshare.git
synced 2025-06-25 06:50:25 -04:00
bundling required python dependencies, to make it easier on Tails users
This commit is contained in:
parent
18fd65acd7
commit
8ffa569094
224 changed files with 52588 additions and 0 deletions
316
lib/werkzeug/script.py
Normal file
316
lib/werkzeug/script.py
Normal file
|
@ -0,0 +1,316 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
r'''
|
||||
werkzeug.script
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
.. admonition:: Deprecated Functionality
|
||||
|
||||
``werkzeug.script`` is deprecated without replacement functionality.
|
||||
Python's command line support improved greatly with :mod:`argparse`
|
||||
and a bunch of alternative modules.
|
||||
|
||||
Most of the time you have recurring tasks while writing an application
|
||||
such as starting up an interactive python interpreter with some prefilled
|
||||
imports, starting the development server, initializing the database or
|
||||
something similar.
|
||||
|
||||
For that purpose werkzeug provides the `werkzeug.script` module which
|
||||
helps you writing such scripts.
|
||||
|
||||
|
||||
Basic Usage
|
||||
-----------
|
||||
|
||||
The following snippet is roughly the same in every werkzeug script::
|
||||
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
from werkzeug import script
|
||||
|
||||
# actions go here
|
||||
|
||||
if __name__ == '__main__':
|
||||
script.run()
|
||||
|
||||
Starting this script now does nothing because no actions are defined.
|
||||
An action is a function in the same module starting with ``"action_"``
|
||||
which takes a number of arguments where every argument has a default. The
|
||||
type of the default value specifies the type of the argument.
|
||||
|
||||
Arguments can then be passed by position or using ``--name=value`` from
|
||||
the shell.
|
||||
|
||||
Because a runserver and shell command is pretty common there are two
|
||||
factory functions that create such commands::
|
||||
|
||||
def make_app():
|
||||
from yourapplication import YourApplication
|
||||
return YourApplication(...)
|
||||
|
||||
action_runserver = script.make_runserver(make_app, use_reloader=True)
|
||||
action_shell = script.make_shell(lambda: {'app': make_app()})
|
||||
|
||||
|
||||
Using The Scripts
|
||||
-----------------
|
||||
|
||||
The script from above can be used like this from the shell now:
|
||||
|
||||
.. sourcecode:: text
|
||||
|
||||
$ ./manage.py --help
|
||||
$ ./manage.py runserver localhost 8080 --debugger --no-reloader
|
||||
$ ./manage.py runserver -p 4000
|
||||
$ ./manage.py shell
|
||||
|
||||
As you can see it's possible to pass parameters as positional arguments
|
||||
or as named parameters, pretty much like Python function calls.
|
||||
|
||||
|
||||
:copyright: (c) 2013 by the Werkzeug Team, see AUTHORS for more details.
|
||||
:license: BSD, see LICENSE for more details.
|
||||
'''
|
||||
from __future__ import print_function
|
||||
|
||||
import sys
|
||||
import inspect
|
||||
import getopt
|
||||
from os.path import basename
|
||||
from werkzeug._compat import iteritems
|
||||
|
||||
|
||||
argument_types = {
|
||||
bool: 'boolean',
|
||||
str: 'string',
|
||||
int: 'integer',
|
||||
float: 'float'
|
||||
}
|
||||
|
||||
|
||||
converters = {
|
||||
'boolean': lambda x: x.lower() in ('1', 'true', 'yes', 'on'),
|
||||
'string': str,
|
||||
'integer': int,
|
||||
'float': float
|
||||
}
|
||||
|
||||
|
||||
def run(namespace=None, action_prefix='action_', args=None):
|
||||
"""Run the script. Participating actions are looked up in the caller's
|
||||
namespace if no namespace is given, otherwise in the dict provided.
|
||||
Only items that start with action_prefix are processed as actions. If
|
||||
you want to use all items in the namespace provided as actions set
|
||||
action_prefix to an empty string.
|
||||
|
||||
:param namespace: An optional dict where the functions are looked up in.
|
||||
By default the local namespace of the caller is used.
|
||||
:param action_prefix: The prefix for the functions. Everything else
|
||||
is ignored.
|
||||
:param args: the arguments for the function. If not specified
|
||||
:data:`sys.argv` without the first argument is used.
|
||||
"""
|
||||
if namespace is None:
|
||||
namespace = sys._getframe(1).f_locals
|
||||
actions = find_actions(namespace, action_prefix)
|
||||
|
||||
if args is None:
|
||||
args = sys.argv[1:]
|
||||
if not args or args[0] in ('-h', '--help'):
|
||||
return print_usage(actions)
|
||||
elif args[0] not in actions:
|
||||
fail('Unknown action \'%s\'' % args[0])
|
||||
|
||||
arguments = {}
|
||||
types = {}
|
||||
key_to_arg = {}
|
||||
long_options = []
|
||||
formatstring = ''
|
||||
func, doc, arg_def = actions[args.pop(0)]
|
||||
for idx, (arg, shortcut, default, option_type) in enumerate(arg_def):
|
||||
real_arg = arg.replace('-', '_')
|
||||
if shortcut:
|
||||
formatstring += shortcut
|
||||
if not isinstance(default, bool):
|
||||
formatstring += ':'
|
||||
key_to_arg['-' + shortcut] = real_arg
|
||||
long_options.append(isinstance(default, bool) and arg or arg + '=')
|
||||
key_to_arg['--' + arg] = real_arg
|
||||
key_to_arg[idx] = real_arg
|
||||
types[real_arg] = option_type
|
||||
arguments[real_arg] = default
|
||||
|
||||
try:
|
||||
optlist, posargs = getopt.gnu_getopt(args, formatstring, long_options)
|
||||
except getopt.GetoptError as e:
|
||||
fail(str(e))
|
||||
|
||||
specified_arguments = set()
|
||||
for key, value in enumerate(posargs):
|
||||
try:
|
||||
arg = key_to_arg[key]
|
||||
except IndexError:
|
||||
fail('Too many parameters')
|
||||
specified_arguments.add(arg)
|
||||
try:
|
||||
arguments[arg] = converters[types[arg]](value)
|
||||
except ValueError:
|
||||
fail('Invalid value for argument %s (%s): %s' % (key, arg, value))
|
||||
|
||||
for key, value in optlist:
|
||||
arg = key_to_arg[key]
|
||||
if arg in specified_arguments:
|
||||
fail('Argument \'%s\' is specified twice' % arg)
|
||||
if types[arg] == 'boolean':
|
||||
if arg.startswith('no_'):
|
||||
value = 'no'
|
||||
else:
|
||||
value = 'yes'
|
||||
try:
|
||||
arguments[arg] = converters[types[arg]](value)
|
||||
except ValueError:
|
||||
fail('Invalid value for \'%s\': %s' % (key, value))
|
||||
|
||||
newargs = {}
|
||||
for k, v in iteritems(arguments):
|
||||
newargs[k.startswith('no_') and k[3:] or k] = v
|
||||
arguments = newargs
|
||||
return func(**arguments)
|
||||
|
||||
|
||||
def fail(message, code=-1):
|
||||
"""Fail with an error."""
|
||||
print('Error: %s' % message, file=sys.stderr)
|
||||
sys.exit(code)
|
||||
|
||||
|
||||
def find_actions(namespace, action_prefix):
|
||||
"""Find all the actions in the namespace."""
|
||||
actions = {}
|
||||
for key, value in iteritems(namespace):
|
||||
if key.startswith(action_prefix):
|
||||
actions[key[len(action_prefix):]] = analyse_action(value)
|
||||
return actions
|
||||
|
||||
|
||||
def print_usage(actions):
|
||||
"""Print the usage information. (Help screen)"""
|
||||
actions = actions.items()
|
||||
actions.sort()
|
||||
print('usage: %s <action> [<options>]' % basename(sys.argv[0]))
|
||||
print(' %s --help' % basename(sys.argv[0]))
|
||||
print()
|
||||
print('actions:')
|
||||
for name, (func, doc, arguments) in actions:
|
||||
print(' %s:' % name)
|
||||
for line in doc.splitlines():
|
||||
print(' %s' % line)
|
||||
if arguments:
|
||||
print()
|
||||
for arg, shortcut, default, argtype in arguments:
|
||||
if isinstance(default, bool):
|
||||
print(' %s' % (
|
||||
(shortcut and '-%s, ' % shortcut or '') + '--' + arg
|
||||
))
|
||||
else:
|
||||
print(' %-30s%-10s%s' % (
|
||||
(shortcut and '-%s, ' % shortcut or '') + '--' + arg,
|
||||
argtype, default
|
||||
))
|
||||
print()
|
||||
|
||||
|
||||
def analyse_action(func):
|
||||
"""Analyse a function."""
|
||||
description = inspect.getdoc(func) or 'undocumented action'
|
||||
arguments = []
|
||||
args, varargs, kwargs, defaults = inspect.getargspec(func)
|
||||
if varargs or kwargs:
|
||||
raise TypeError('variable length arguments for action not allowed.')
|
||||
if len(args) != len(defaults or ()):
|
||||
raise TypeError('not all arguments have proper definitions')
|
||||
|
||||
for idx, (arg, definition) in enumerate(zip(args, defaults or ())):
|
||||
if arg.startswith('_'):
|
||||
raise TypeError('arguments may not start with an underscore')
|
||||
if not isinstance(definition, tuple):
|
||||
shortcut = None
|
||||
default = definition
|
||||
else:
|
||||
shortcut, default = definition
|
||||
argument_type = argument_types[type(default)]
|
||||
if isinstance(default, bool) and default is True:
|
||||
arg = 'no-' + arg
|
||||
arguments.append((arg.replace('_', '-'), shortcut,
|
||||
default, argument_type))
|
||||
return func, description, arguments
|
||||
|
||||
|
||||
def make_shell(init_func=None, banner=None, use_ipython=True):
|
||||
"""Returns an action callback that spawns a new interactive
|
||||
python shell.
|
||||
|
||||
:param init_func: an optional initialization function that is
|
||||
called before the shell is started. The return
|
||||
value of this function is the initial namespace.
|
||||
:param banner: the banner that is displayed before the shell. If
|
||||
not specified a generic banner is used instead.
|
||||
:param use_ipython: if set to `True` ipython is used if available.
|
||||
"""
|
||||
if banner is None:
|
||||
banner = 'Interactive Werkzeug Shell'
|
||||
if init_func is None:
|
||||
init_func = dict
|
||||
def action(ipython=use_ipython):
|
||||
"""Start a new interactive python session."""
|
||||
namespace = init_func()
|
||||
if ipython:
|
||||
try:
|
||||
try:
|
||||
from IPython.frontend.terminal.embed import InteractiveShellEmbed
|
||||
sh = InteractiveShellEmbed(banner1=banner)
|
||||
except ImportError:
|
||||
from IPython.Shell import IPShellEmbed
|
||||
sh = IPShellEmbed(banner=banner)
|
||||
except ImportError:
|
||||
pass
|
||||
else:
|
||||
sh(global_ns={}, local_ns=namespace)
|
||||
return
|
||||
from code import interact
|
||||
interact(banner, local=namespace)
|
||||
return action
|
||||
|
||||
|
||||
def make_runserver(app_factory, hostname='localhost', port=5000,
|
||||
use_reloader=False, use_debugger=False, use_evalex=True,
|
||||
threaded=False, processes=1, static_files=None,
|
||||
extra_files=None, ssl_context=None):
|
||||
"""Returns an action callback that spawns a new development server.
|
||||
|
||||
.. versionadded:: 0.5
|
||||
`static_files` and `extra_files` was added.
|
||||
|
||||
..versionadded:: 0.6.1
|
||||
`ssl_context` was added.
|
||||
|
||||
:param app_factory: a function that returns a new WSGI application.
|
||||
:param hostname: the default hostname the server should listen on.
|
||||
:param port: the default port of the server.
|
||||
:param use_reloader: the default setting for the reloader.
|
||||
:param use_evalex: the default setting for the evalex flag of the debugger.
|
||||
:param threaded: the default threading setting.
|
||||
:param processes: the default number of processes to start.
|
||||
:param static_files: optional dict of static files.
|
||||
:param extra_files: optional list of extra files to track for reloading.
|
||||
:param ssl_context: optional SSL context for running server in HTTPS mode.
|
||||
"""
|
||||
def action(hostname=('h', hostname), port=('p', port),
|
||||
reloader=use_reloader, debugger=use_debugger,
|
||||
evalex=use_evalex, threaded=threaded, processes=processes):
|
||||
"""Start a new development server."""
|
||||
from werkzeug.serving import run_simple
|
||||
app = app_factory()
|
||||
run_simple(hostname, port, app, reloader, debugger, evalex,
|
||||
extra_files, 1, threaded, processes,
|
||||
static_files=static_files, ssl_context=ssl_context)
|
||||
return action
|
Loading…
Add table
Add a link
Reference in a new issue