mirror of
https://github.com/Tygs/0bin.git
synced 2023-08-10 21:13:00 +03:00
Added options to the server script
This commit is contained in:
parent
36216fe118
commit
15b203eb11
428
libs/clize.py
Normal file
428
libs/clize.py
Normal file
@ -0,0 +1,428 @@
|
|||||||
|
from __future__ import print_function
|
||||||
|
from functools import wraps, partial
|
||||||
|
from collections import namedtuple
|
||||||
|
import re
|
||||||
|
from textwrap import TextWrapper
|
||||||
|
from traceback import print_exc
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
import inspect
|
||||||
|
from gettext import gettext as _, ngettext as _n
|
||||||
|
|
||||||
|
class ArgumentError(TypeError):
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return str(self.args[0] + '\n'
|
||||||
|
+ help(self.args[2], self.args[1],
|
||||||
|
just_do_usage=True, do_print=False))
|
||||||
|
|
||||||
|
Option = namedtuple(
|
||||||
|
'Option',
|
||||||
|
(
|
||||||
|
'source',
|
||||||
|
'names',
|
||||||
|
'default',
|
||||||
|
'type',
|
||||||
|
'help',
|
||||||
|
'optional',
|
||||||
|
'positional',
|
||||||
|
'takes_argument',
|
||||||
|
'catchall',
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
def make_flag(
|
||||||
|
source,
|
||||||
|
names,
|
||||||
|
default=False,
|
||||||
|
type=bool,
|
||||||
|
help='',
|
||||||
|
takes_argument=0,
|
||||||
|
):
|
||||||
|
return Option(
|
||||||
|
source, names, default, type, help,
|
||||||
|
optional=True, positional=False,
|
||||||
|
takes_argument=takes_argument, catchall=False
|
||||||
|
)
|
||||||
|
|
||||||
|
Command = namedtuple(
|
||||||
|
'Command',
|
||||||
|
(
|
||||||
|
'description',
|
||||||
|
'footnotes',
|
||||||
|
'posargs',
|
||||||
|
'options'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
argdesc = re.compile('^(\w+): (.*)$', re.DOTALL)
|
||||||
|
|
||||||
|
def read_arguments(fn, alias, force_positional, require_excess, coerce):
|
||||||
|
argspec = inspect.getargspec(fn)
|
||||||
|
|
||||||
|
doc = inspect.getdoc(fn)
|
||||||
|
description = []
|
||||||
|
footnotes = []
|
||||||
|
opts_help = {}
|
||||||
|
|
||||||
|
if doc:
|
||||||
|
for paragraph in doc.split('\n\n'):
|
||||||
|
m = argdesc.match(paragraph)
|
||||||
|
|
||||||
|
if m:
|
||||||
|
optname, desc = m.groups()
|
||||||
|
opts_help[optname] = desc
|
||||||
|
else:
|
||||||
|
if opts_help:
|
||||||
|
footnotes.append(paragraph)
|
||||||
|
else:
|
||||||
|
description.append(paragraph)
|
||||||
|
|
||||||
|
posargs = []
|
||||||
|
options = []
|
||||||
|
|
||||||
|
for i, argname in enumerate(argspec.args):
|
||||||
|
try:
|
||||||
|
default = argspec.defaults[-len(argspec.args) + i]
|
||||||
|
except (IndexError, TypeError):
|
||||||
|
default = None
|
||||||
|
optional = False
|
||||||
|
type_ = str
|
||||||
|
else:
|
||||||
|
optional = True
|
||||||
|
type_ = type(default)
|
||||||
|
|
||||||
|
type_ = coerce.get(argname, type_)
|
||||||
|
|
||||||
|
positional = not optional
|
||||||
|
if argname in force_positional:
|
||||||
|
positional = True
|
||||||
|
|
||||||
|
if positional and options and options[-1].optional:
|
||||||
|
optional = True
|
||||||
|
|
||||||
|
option = Option(
|
||||||
|
source=argname,
|
||||||
|
names=(argname.replace('_', '-'),) + alias.get(argname, ()),
|
||||||
|
default=default,
|
||||||
|
type=type_,
|
||||||
|
help=opts_help.get(argname, ''),
|
||||||
|
optional=optional,
|
||||||
|
positional=positional,
|
||||||
|
takes_argument=int(optional and type_ != bool),
|
||||||
|
catchall=False,
|
||||||
|
)
|
||||||
|
if positional:
|
||||||
|
posargs.append(option)
|
||||||
|
else:
|
||||||
|
options.append(option)
|
||||||
|
|
||||||
|
if argspec.varargs:
|
||||||
|
posargs.append(
|
||||||
|
Option(
|
||||||
|
source=argspec.varargs,
|
||||||
|
names=(argspec.varargs.replace('_', '-'),),
|
||||||
|
default=None,
|
||||||
|
type=str,
|
||||||
|
help=opts_help.get(argspec.varargs, ''),
|
||||||
|
optional=bool(not require_excess or posargs and posargs[-1].optional),
|
||||||
|
positional=True,
|
||||||
|
takes_argument=False,
|
||||||
|
catchall=True,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
return Command(
|
||||||
|
description=tuple(description), footnotes=tuple(footnotes),
|
||||||
|
posargs=posargs, options=options)
|
||||||
|
|
||||||
|
def get_arg_name(arg):
|
||||||
|
name = arg.names[0] + (arg.catchall and '...' or '')
|
||||||
|
return (arg.optional and '[' + name + ']'
|
||||||
|
or name)
|
||||||
|
|
||||||
|
def get_option_names(option):
|
||||||
|
shorts = []
|
||||||
|
longs = []
|
||||||
|
|
||||||
|
for name in option.names:
|
||||||
|
if option.positional:
|
||||||
|
longs.append(name)
|
||||||
|
elif len(name) == 1:
|
||||||
|
shorts.append('-' + name)
|
||||||
|
else:
|
||||||
|
longs.append('--' + name)
|
||||||
|
|
||||||
|
if ((not option.positional and option.type != bool)
|
||||||
|
or (option.positional and option.type != str)):
|
||||||
|
longs[-1] += '=' + option.type.__name__.upper()
|
||||||
|
|
||||||
|
if option.positional and option.catchall:
|
||||||
|
longs[-1] += '...'
|
||||||
|
|
||||||
|
return ', '.join(shorts + longs)
|
||||||
|
|
||||||
|
def get_terminal_width():
|
||||||
|
return 70 #fair terminal dice roll
|
||||||
|
|
||||||
|
def print_arguments(arguments, width=None):
|
||||||
|
if width == None:
|
||||||
|
width = 0
|
||||||
|
for arg in arguments:
|
||||||
|
width = max(width, len(get_option_names(arg)))
|
||||||
|
|
||||||
|
help_wrapper = TextWrapper(
|
||||||
|
width=get_terminal_width(),
|
||||||
|
initial_indent=' ' * (width + 5),
|
||||||
|
subsequent_indent=' ' * (width + 5),
|
||||||
|
)
|
||||||
|
|
||||||
|
return ('\n'.join(
|
||||||
|
' ' * 2 + '{0:<{width}} {1}'.format(
|
||||||
|
get_option_names(arg),
|
||||||
|
arg.help and help_wrapper.fill(
|
||||||
|
arg.help +
|
||||||
|
(arg.default not in (None, False)
|
||||||
|
and _('(default: {0!r})').format(arg.default)
|
||||||
|
or '')
|
||||||
|
)[width + 4:]
|
||||||
|
or '',
|
||||||
|
width=width,
|
||||||
|
) for arg in arguments))
|
||||||
|
|
||||||
|
def help(name, command, just_do_usage=False, do_print=True, **kwargs):
|
||||||
|
ret = ""
|
||||||
|
ret += (_('Usage: {0}{1} {2}').format(
|
||||||
|
name,
|
||||||
|
command.options and _(' [OPTIONS]') or '',
|
||||||
|
' '.join(get_arg_name(arg) for arg in command.posargs),
|
||||||
|
))
|
||||||
|
|
||||||
|
if just_do_usage:
|
||||||
|
if do_print:
|
||||||
|
print(ret)
|
||||||
|
return ret
|
||||||
|
|
||||||
|
tw = TextWrapper(
|
||||||
|
width=get_terminal_width()
|
||||||
|
)
|
||||||
|
|
||||||
|
ret += '\n\n'.join(
|
||||||
|
tw.fill(p) for p in ('',) + command.description) + '\n'
|
||||||
|
if command.posargs:
|
||||||
|
ret += '\n' + _('Positional arguments:') + '\n'
|
||||||
|
ret += print_arguments(command.posargs) + '\n'
|
||||||
|
if command.options:
|
||||||
|
ret += '\n' + _('Options:') + '\n'
|
||||||
|
ret += print_arguments(command.options) + '\n'
|
||||||
|
if command.footnotes:
|
||||||
|
ret += '\n' + '\n\n'.join(tw.fill(p) for p in command.footnotes)
|
||||||
|
ret += '\n'
|
||||||
|
|
||||||
|
if do_print:
|
||||||
|
print(ret)
|
||||||
|
|
||||||
|
return ret
|
||||||
|
|
||||||
|
def get_option(name, list):
|
||||||
|
for option in list:
|
||||||
|
if name in option.names:
|
||||||
|
return option
|
||||||
|
raise KeyError
|
||||||
|
|
||||||
|
def coerce_option(val, option, key, command, name):
|
||||||
|
try:
|
||||||
|
return option.type(val)
|
||||||
|
except ValueError:
|
||||||
|
key = (len(key) == 1 and '-' + key) or ('--' + key)
|
||||||
|
raise ArgumentError(_("{0} needs an argument of type {1}")
|
||||||
|
.format(key, option.type.__name__.upper()),
|
||||||
|
name, command
|
||||||
|
)
|
||||||
|
|
||||||
|
def set_arg_value(val, option, key, params, name, command):
|
||||||
|
if callable(option.source):
|
||||||
|
return option.source(name=name, command=command,
|
||||||
|
val=val, params=params)
|
||||||
|
else:
|
||||||
|
params[option.source] = coerce_option(
|
||||||
|
val, option, key, name, command)
|
||||||
|
|
||||||
|
def get_following_arguments(i, option, input, key, command, name):
|
||||||
|
if i + option.takes_argument >= len(input):
|
||||||
|
raise ArgumentError(
|
||||||
|
_n("--{0} needs an argument.",
|
||||||
|
"--{0} needs {1} arguments.",
|
||||||
|
option.takes_argument)
|
||||||
|
.format(key, option.takes_argument),
|
||||||
|
command, name
|
||||||
|
)
|
||||||
|
|
||||||
|
if option.catchall:
|
||||||
|
val_ = input[i+1:]
|
||||||
|
else:
|
||||||
|
val_ = input[
|
||||||
|
i+1:i+option.takes_argument+1]
|
||||||
|
|
||||||
|
return len(val_), ' '.join(val_)
|
||||||
|
|
||||||
|
def clize(
|
||||||
|
fn=None,
|
||||||
|
alias={},
|
||||||
|
help_names=('help', 'h'),
|
||||||
|
force_positional=(),
|
||||||
|
coerce={},
|
||||||
|
require_excess=False,
|
||||||
|
extra=(),
|
||||||
|
):
|
||||||
|
def _wrapperer(fn):
|
||||||
|
command = read_arguments(
|
||||||
|
fn,
|
||||||
|
alias, force_positional,
|
||||||
|
require_excess, coerce,
|
||||||
|
)
|
||||||
|
|
||||||
|
if help_names:
|
||||||
|
help_option = make_flag(
|
||||||
|
source=help,
|
||||||
|
names=help_names,
|
||||||
|
help=_("Show this help"),
|
||||||
|
)
|
||||||
|
command.options.append(help_option)
|
||||||
|
|
||||||
|
command.options.extend(extra)
|
||||||
|
|
||||||
|
@wraps(fn)
|
||||||
|
def _getopts(*input):
|
||||||
|
name = input[0]
|
||||||
|
input = input[1:]
|
||||||
|
|
||||||
|
kwargs = {}
|
||||||
|
args = []
|
||||||
|
|
||||||
|
skip_next = 0
|
||||||
|
for i, arg in enumerate(input):
|
||||||
|
if skip_next:
|
||||||
|
skip_next -= 1
|
||||||
|
continue
|
||||||
|
|
||||||
|
if arg.startswith('--'):
|
||||||
|
if len(arg) == 2:
|
||||||
|
args.extend(input[i+1:])
|
||||||
|
break
|
||||||
|
|
||||||
|
keyarg = arg[2:].split('=', 1)
|
||||||
|
try:
|
||||||
|
option = get_option(keyarg[0], command.options)
|
||||||
|
except KeyError:
|
||||||
|
raise ArgumentError(
|
||||||
|
_("Unrecognized option {0}").format(arg),
|
||||||
|
command,
|
||||||
|
name
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
if option.takes_argument or option.catchall:
|
||||||
|
try:
|
||||||
|
key, val = keyarg
|
||||||
|
except ValueError:
|
||||||
|
key = keyarg[0]
|
||||||
|
|
||||||
|
skip_next, val = get_following_arguments(
|
||||||
|
i, option, input, key, command, name
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
key = keyarg[0]
|
||||||
|
val = True
|
||||||
|
if set_arg_value(
|
||||||
|
val, option, key,
|
||||||
|
kwargs,
|
||||||
|
name, command
|
||||||
|
):
|
||||||
|
return
|
||||||
|
elif arg.startswith('-'):
|
||||||
|
skip_next_ = 0
|
||||||
|
for j, c in enumerate(arg[1:]):
|
||||||
|
if skip_next_:
|
||||||
|
skip_next_ -= 1
|
||||||
|
continue
|
||||||
|
|
||||||
|
try:
|
||||||
|
option = get_option(c, command.options)
|
||||||
|
except KeyError:
|
||||||
|
raise ArgumentError(_("Unknown option -{0}.").format(c),
|
||||||
|
command, name)
|
||||||
|
else:
|
||||||
|
if option.takes_argument:
|
||||||
|
if len(arg) > 2+j:
|
||||||
|
if option.type == int:
|
||||||
|
val = ""
|
||||||
|
for k in range(2+j, len(arg)):
|
||||||
|
if k == 2+j and arg[k] == '-':
|
||||||
|
val += '-'
|
||||||
|
elif '0' <= arg[k] and arg[k] <= '9':
|
||||||
|
val += arg[k]
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
val = arg[2+j:]
|
||||||
|
skip_next_ = len(val)
|
||||||
|
else:
|
||||||
|
skip_next, val = get_following_arguments(
|
||||||
|
i, option, input, option.source, command, name
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
val = True
|
||||||
|
|
||||||
|
if set_arg_value(
|
||||||
|
val, option, c,
|
||||||
|
kwargs,
|
||||||
|
name, command
|
||||||
|
):
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
args.append(arg)
|
||||||
|
|
||||||
|
for i, option in enumerate(command.posargs):
|
||||||
|
if i >= len(args):
|
||||||
|
if option.optional:
|
||||||
|
if not option.catchall:
|
||||||
|
args.append(option.default)
|
||||||
|
else:
|
||||||
|
raise ArgumentError(_("Not enough arguments."), command, name)
|
||||||
|
if not option.catchall:
|
||||||
|
args[i] = option.type(args[i])
|
||||||
|
|
||||||
|
|
||||||
|
if len(args) != len(command.posargs):
|
||||||
|
if (not command.posargs
|
||||||
|
or not command.posargs[-1].catchall):
|
||||||
|
raise ArgumentError(_("Too many arguments."), command, name)
|
||||||
|
|
||||||
|
for option in command.options:
|
||||||
|
if not callable(option.source):
|
||||||
|
kwargs.setdefault(option.source, option.default)
|
||||||
|
|
||||||
|
fn_args = inspect.getargspec(fn).args
|
||||||
|
for i, key in enumerate(fn_args):
|
||||||
|
if key in kwargs:
|
||||||
|
args.insert(i, kwargs[key])
|
||||||
|
|
||||||
|
return fn(*args)
|
||||||
|
return _getopts
|
||||||
|
|
||||||
|
if fn == None:
|
||||||
|
return _wrapperer
|
||||||
|
else:
|
||||||
|
return _wrapperer(fn)
|
||||||
|
|
||||||
|
def run(fn, args=None):
|
||||||
|
if args == None:
|
||||||
|
args = sys.argv
|
||||||
|
|
||||||
|
import os.path
|
||||||
|
try:
|
||||||
|
fn(*sys.argv)
|
||||||
|
except ArgumentError as e:
|
||||||
|
print(os.path.basename(args[0]) + ': ' + str(e),
|
||||||
|
file=sys.stderr)
|
@ -16,11 +16,10 @@ DEBUG = True
|
|||||||
# default in projectdirectory/static/content/
|
# default in projectdirectory/static/content/
|
||||||
# use "/" even under Windows
|
# use "/" even under Windows
|
||||||
PASTE_FILES_ROOT = os.path.join(STATIC_FILES_ROOT, 'content')
|
PASTE_FILES_ROOT = os.path.join(STATIC_FILES_ROOT, 'content')
|
||||||
# Port and host the embeded python server should be using in prod and in dev
|
|
||||||
PROD_HOST = "0.0.0.0"
|
# Port and host the embeded python server should be using
|
||||||
PROD_PORT= "80"
|
HOST = "127.0.0.1"
|
||||||
DEV_HOST = "127.0.0.1"
|
PORT= "8000"
|
||||||
DEV_PORT= "8000"
|
|
||||||
|
|
||||||
# User and group the server should run as. Set to None if it should be the
|
# User and group the server should run as. Set to None if it should be the
|
||||||
# current user
|
# current user
|
||||||
|
@ -9,14 +9,5 @@ import sys
|
|||||||
|
|
||||||
import settings
|
import settings
|
||||||
from paste import Paste
|
from paste import Paste
|
||||||
|
from utils import drop_privileges
|
||||||
|
|
||||||
|
|
||||||
def setup_path():
|
|
||||||
"""
|
|
||||||
Add the project dir in the python path to the site to run with the
|
|
||||||
source code beeing just copied/pasted and not installed.
|
|
||||||
|
|
||||||
Add fallback on embeded libs to path.
|
|
||||||
"""
|
|
||||||
sys.path.insert(0, os.path.dirname(settings.ROOT_DIR))
|
|
||||||
sys.path.append(os.path.join(settings.ROOT_DIR, 'libs'))
|
|
32
src/utils.py
Normal file
32
src/utils.py
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import time
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
import settings
|
||||||
|
import glob
|
||||||
|
import tempfile
|
||||||
|
|
||||||
|
|
||||||
|
try:
|
||||||
|
from privilege import drop_privileges_permanently, coerce_user, coerce_group
|
||||||
|
except (AttributeError):
|
||||||
|
pass # privilege does't work on several plateform
|
||||||
|
|
||||||
|
|
||||||
|
def drop_privileges():
|
||||||
|
time.sleep(5)
|
||||||
|
if settings.USER:
|
||||||
|
settings.GROUP = settings.GROUP or settings.USER
|
||||||
|
try:
|
||||||
|
user = coerce_user(settings.USER)
|
||||||
|
group = coerce_group(settings.GROUP)
|
||||||
|
|
||||||
|
lock_files = glob.glob(os.path.join(tempfile.gettempdir(),
|
||||||
|
'bottle.*.lock'))
|
||||||
|
for lock_file in lock_files:
|
||||||
|
os.chown(lock_file, user, group)
|
||||||
|
|
||||||
|
drop_privileges_permanently(settings.USER, settings.GROUP, ())
|
||||||
|
except Exception:
|
||||||
|
print "Failed to drop privileges. Running with current user."
|
66
start.py
Normal file → Executable file
66
start.py
Normal file → Executable file
@ -9,35 +9,30 @@ import sys
|
|||||||
import os
|
import os
|
||||||
import hashlib
|
import hashlib
|
||||||
import thread
|
import thread
|
||||||
import time
|
|
||||||
import tempfile
|
|
||||||
import glob
|
|
||||||
import math
|
import math
|
||||||
|
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
|
|
||||||
from src import settings, setup_path, Paste
|
import settings
|
||||||
|
sys.path.insert(0, os.path.dirname(settings.ROOT_DIR))
|
||||||
setup_path()
|
sys.path.append(os.path.join(settings.ROOT_DIR, 'libs'))
|
||||||
|
|
||||||
try:
|
|
||||||
from privilege import drop_privileges_permanently, coerce_user, coerce_group
|
|
||||||
except AttributeError:
|
|
||||||
pass # privilege does't work on several plateform
|
|
||||||
|
|
||||||
|
import bottle
|
||||||
from bottle import (Bottle, route, run, abort,
|
from bottle import (Bottle, route, run, abort,
|
||||||
static_file, debug, view, request)
|
static_file, debug, view, request)
|
||||||
|
|
||||||
|
import clize
|
||||||
|
|
||||||
|
from src import settings, Paste, drop_privileges
|
||||||
|
|
||||||
|
|
||||||
app = Bottle()
|
app = Bottle()
|
||||||
|
|
||||||
import settings
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/')
|
@app.route('/')
|
||||||
@view('home')
|
@view('home')
|
||||||
def index():
|
def index():
|
||||||
max_size_kb = int(math.ceil(settings.MAX_SIZE/1024.0))
|
max_size_kb = int(math.ceil(settings.MAX_SIZE / 1024.0))
|
||||||
return {'max_size': settings.MAX_SIZE, 'max_size_kb': max_size_kb}
|
return {'max_size': settings.MAX_SIZE, 'max_size_kb': max_size_kb}
|
||||||
|
|
||||||
|
|
||||||
@ -97,38 +92,25 @@ def display_paste(paste_id):
|
|||||||
return {'paste': paste, 'keep_alive': keep_alive}
|
return {'paste': paste, 'keep_alive': keep_alive}
|
||||||
|
|
||||||
|
|
||||||
@app.route('/static/<filename:path>')
|
@clize.clize
|
||||||
def server_static(filename):
|
def runserver(host=settings.HOST, port=settings.PORT, debug=settings.DEBUG,
|
||||||
|
serve_static=settings.DEBUG):
|
||||||
|
|
||||||
|
if serve_static:
|
||||||
|
@app.route('/static/<filename:path>')
|
||||||
|
def server_static(filename):
|
||||||
return static_file(filename, root=settings.STATIC_FILES_ROOT)
|
return static_file(filename, root=settings.STATIC_FILES_ROOT)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
|
|
||||||
def drop_privileges():
|
|
||||||
time.sleep(5)
|
|
||||||
if settings.USER:
|
|
||||||
settings.GROUP = settings.GROUP or settings.USER
|
|
||||||
try:
|
|
||||||
user = coerce_user(settings.USER)
|
|
||||||
group = coerce_group(settings.GROUP)
|
|
||||||
|
|
||||||
lock_files = glob.glob(os.path.join(tempfile.gettempdir(),
|
|
||||||
'bottle.*.lock'))
|
|
||||||
for lock_file in lock_files:
|
|
||||||
os.chown(lock_file, user, group)
|
|
||||||
|
|
||||||
drop_privileges_permanently(settings.USER, settings.GROUP, ())
|
|
||||||
except Exception:
|
|
||||||
print "Failed to drop privileges. Running with current user."
|
|
||||||
|
|
||||||
thread.start_new_thread(drop_privileges, ())
|
thread.start_new_thread(drop_privileges, ())
|
||||||
|
|
||||||
if settings.DEBUG:
|
if debug:
|
||||||
debug(True)
|
bottle.debug(True)
|
||||||
run(app, host=settings.DEV_HOST, port=settings.DEV_PORT,
|
run(app, host=host, port=port, reloader=True, server="cherrypy")
|
||||||
reloader=True, server="cherrypy")
|
|
||||||
else:
|
else:
|
||||||
run(app, host=settings.PROD_HOST,
|
run(app, host=host, port=port, server="cherrypy")
|
||||||
port=settings.PROD_PORT, server="cherrypy")
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
clize.run(runserver)
|
||||||
|
|
||||||
|
|
||||||
|
@ -79,10 +79,12 @@
|
|||||||
<small>Edgar Allan Poe</small>
|
<small>Edgar Allan Poe</small>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
|
|
||||||
|
<!--
|
||||||
<h4 id="pixels-total" >
|
<h4 id="pixels-total" >
|
||||||
<p>ø</p>
|
<p>ø</p>
|
||||||
<strong>41,017,923,819</strong> pastes øbinned
|
<strong>41,017,923,819</strong> pastes øbinned
|
||||||
</h4>
|
</h4>
|
||||||
|
-->
|
||||||
|
|
||||||
</br>
|
</br>
|
||||||
<p class="greetings span12">
|
<p class="greetings span12">
|
||||||
|
Loading…
Reference in New Issue
Block a user