Initial commit
commit
a3c69c2771
|
@ -0,0 +1,5 @@
|
||||||
|
/dist/
|
||||||
|
*.egg-info/
|
||||||
|
__pycache__/
|
||||||
|
*.py[co]
|
||||||
|
*.ini
|
|
@ -0,0 +1,43 @@
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
import gunicorn.app.base
|
||||||
|
import os
|
||||||
|
import webob.static
|
||||||
|
import logging
|
||||||
|
|
||||||
|
|
||||||
|
config = os.path.join(os.path.dirname(__file__), 'development.ini')
|
||||||
|
|
||||||
|
|
||||||
|
class DebugApplication(object):
|
||||||
|
|
||||||
|
def __init__(self, app, staticpath='.'):
|
||||||
|
self.app = app
|
||||||
|
self.static = webob.static.DirectoryApp(os.path.realpath(staticpath))
|
||||||
|
|
||||||
|
def __call__(self, environ, start_response):
|
||||||
|
if os.path.exists(environ['PATH_INFO'].lstrip('/')):
|
||||||
|
return self.static(environ, start_response)
|
||||||
|
else:
|
||||||
|
return self.app(environ, start_response)
|
||||||
|
|
||||||
|
|
||||||
|
class Server(gunicorn.app.base.BaseApplication):
|
||||||
|
|
||||||
|
def load_config(self):
|
||||||
|
self.cfg.set('bind', '[::]:8080')
|
||||||
|
self.cfg.set('reload', True)
|
||||||
|
self.cfg.set('workers', 1)
|
||||||
|
self.cfg.set('threads', 1)
|
||||||
|
self.cfg.set('accesslog', '-')
|
||||||
|
self.cfg.set('timeout', 9001)
|
||||||
|
|
||||||
|
def load(self):
|
||||||
|
import rouse.web
|
||||||
|
app = rouse.web.Application.create(config)
|
||||||
|
return DebugApplication(app)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
logging.basicConfig(level=logging.DEBUG)
|
||||||
|
logging.getLogger('sqlalchemy.engine.base.Engine').propagate = False
|
||||||
|
Server().run()
|
|
@ -0,0 +1,16 @@
|
||||||
|
from setuptools import find_packages, setup
|
||||||
|
|
||||||
|
setup(
|
||||||
|
name='Rouse',
|
||||||
|
version='0.1',
|
||||||
|
description='Wake-on-LAN sender with convenient browser user interface',
|
||||||
|
author='Dustin C. Hatch',
|
||||||
|
author_email='dustin@hatch.name',
|
||||||
|
url='',
|
||||||
|
license='GPL-3',
|
||||||
|
packages=find_packages('src'),
|
||||||
|
package_dir={'': 'src'},
|
||||||
|
install_requires=[
|
||||||
|
'Milla>=0.3',
|
||||||
|
],
|
||||||
|
)
|
|
@ -0,0 +1,92 @@
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
from milla.dispatch import routing
|
||||||
|
import functools
|
||||||
|
import jinja2
|
||||||
|
import json
|
||||||
|
import milla.util
|
||||||
|
import os
|
||||||
|
|
||||||
|
|
||||||
|
class SmartJSONEncoder(json.JSONEncoder):
|
||||||
|
|
||||||
|
def default(self, obj): # pylint: disable=method-hidden
|
||||||
|
if hasattr(obj, 'to_json'):
|
||||||
|
return obj.to_json()
|
||||||
|
super(SmartJSONEncoder, self).default(obj)
|
||||||
|
|
||||||
|
|
||||||
|
class VariedResponse(milla.Response):
|
||||||
|
|
||||||
|
TMPL_LOADER = jinja2.PackageLoader(__name__)
|
||||||
|
|
||||||
|
def __init__(self, request, *args, **kwargs):
|
||||||
|
super(VariedResponse, self).__init__(*args, **kwargs)
|
||||||
|
self.request = request
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def for_request(cls, request):
|
||||||
|
return functools.partial(cls, request)
|
||||||
|
|
||||||
|
def set_payload(self, template, context=None):
|
||||||
|
if not self.vary:
|
||||||
|
self.vary = ['Accept']
|
||||||
|
elif 'accept' not in (v.lower() for v in self.vary):
|
||||||
|
self.vary += 'Accept',
|
||||||
|
if context is None:
|
||||||
|
context = {}
|
||||||
|
if template is None or self.request.want == 'json':
|
||||||
|
self.content_type = str('application/json')
|
||||||
|
json.dump(context, self.body_file, cls=SmartJSONEncoder)
|
||||||
|
else:
|
||||||
|
if self.request.want == 'xhtml':
|
||||||
|
self.content_type = str('application/xhtml+xml')
|
||||||
|
self.render(template, context)
|
||||||
|
|
||||||
|
def render(self, template, context=None):
|
||||||
|
if context is None:
|
||||||
|
context = {}
|
||||||
|
env = jinja2.Environment(loader=self.TMPL_LOADER)
|
||||||
|
env.globals.update(
|
||||||
|
url=self.request.create_href,
|
||||||
|
static=self.request.static_resource,
|
||||||
|
)
|
||||||
|
if hasattr(self.request, 'user'):
|
||||||
|
env.globals['user'] = self.request.user
|
||||||
|
self.text = env.get_template(template).render(**context)
|
||||||
|
|
||||||
|
|
||||||
|
class Application(milla.Application):
|
||||||
|
|
||||||
|
def __init__(self, config=None): # pylint: disable=super-init-not-called
|
||||||
|
self.config = {}
|
||||||
|
if config and os.path.exists(config):
|
||||||
|
self.config.update(milla.util.read_config(config))
|
||||||
|
self.config['milla.favicon'] = False
|
||||||
|
|
||||||
|
self.setup_routes()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def create(cls, config):
|
||||||
|
app = cls(config)
|
||||||
|
return app
|
||||||
|
|
||||||
|
def setup_routes(self):
|
||||||
|
self.dispatcher = r = routing.Router()
|
||||||
|
|
||||||
|
def make_request(self, environ):
|
||||||
|
request = super(Application, self).make_request(environ)
|
||||||
|
default_format = VariedResponse.default_content_type
|
||||||
|
offers = [
|
||||||
|
'application/json',
|
||||||
|
'application/xhtml+xml',
|
||||||
|
'text/html',
|
||||||
|
]
|
||||||
|
want_fmt = request.accept.best_match(offers, default_format)
|
||||||
|
if want_fmt == 'application/json':
|
||||||
|
request.want = 'json'
|
||||||
|
elif want_fmt == 'text/html':
|
||||||
|
request.want = 'html'
|
||||||
|
else:
|
||||||
|
request.want = 'xhtml'
|
||||||
|
request.ResponseClass = VariedResponse.for_request(request)
|
||||||
|
return request
|
Loading…
Reference in New Issue