Initial commit

master
Dustin 2015-12-31 21:16:07 -06:00
commit a3c69c2771
5 changed files with 156 additions and 0 deletions

5
.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
/dist/
*.egg-info/
__pycache__/
*.py[co]
*.ini

43
debug.py Normal file
View File

@ -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()

16
setup.py Normal file
View File

@ -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
src/rouse/__init__.py Normal file
View File

92
src/rouse/web/__init__.py Normal file
View File

@ -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