Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Iflux to firenado #4

Merged
merged 6 commits into from
Jun 13, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ develop-eggs
lib
lib64

# Sphinx doc
_build

# Installer logs
pip-log.txt

Expand Down
6 changes: 6 additions & 0 deletions docs/guide.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
User's guide
============

.. toctree::

guide/intro
8 changes: 8 additions & 0 deletions docs/guide/intro.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Introduction
------------

Firenado is a Python web framework that extends `Tornado <http://www.tornadoweb.org>`_ adding new
features such as but not limited to application loose couple components, server side session layer,
yaml based configuration files.

WORK IN PROGRESS
8 changes: 5 additions & 3 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
contain the root `toctree` directive.


|Firenado Framework|
====================
Firenado Framework
==================

Firenado is a Python web framework that extends `Tornado <http://www.tornadoweb.org>`_ adding new
features such as but not limited to application loose couple components, server side session layer,
Expand All @@ -17,11 +17,13 @@ Contents:
.. toctree::
:maxdepth: 2


guide

Indices and tables
==================



* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`
Expand Down
32 changes: 23 additions & 9 deletions firenado/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,26 +40,40 @@

LIB_CONFIG_FILE = os.path.join(ROOT, 'conf', FIRENADO_CONFIG_FILE)

# Application file
APP_CONFIG_ROOT_PATH = os.path.join(os.getcwd())
# If FIRENADO_CURRENT_APP_PATH is not set than return current directory conf dir
APP_CONFIG_PATH = os.getenv('FIRENADO_CURRENT_APP_CONFIG_PATH',
os.path.join(APP_CONFIG_ROOT_PATH, 'conf'))
APP_CONFIG_FILE = os.path.join(APP_CONFIG_PATH, FIRENADO_CONFIG_FILE)

HAS_LIB_CONFIG_FILE = False
HAS_APP_CONFIG_FILE = False

if os.path.isfile(LIB_CONFIG_FILE):
HAS_LIB_CONFIG_FILE = True
stack.append(LIB_CONFIG_FILE)

if os.path.isfile(APP_CONFIG_FILE):
if APP_CONFIG_FILE != LIB_CONFIG_FILE:
HAS_APP_CONFIG_FILE = True
stack.append(APP_CONFIG_FILE)

# Setting firenado's default variables

# Application default configuration
application = {}
app = {}
# Key to to be used on on the session context to store and retrieve the current
# logged user
application['current_user_key'] = '__FIRENADO_CURRENT_USER_KEY__'
application['data'] = {}
application['data']['sources'] = []
application['python_path'] = None
application['port'] = 8888
application['login'] = {}
application['login']['urls'] = {}
application['login']['urls']['default'] = '/login'
app['current_user_key'] = '__FIRENADO_CURRENT_USER_KEY__'
app['data'] = {}
app['data']['sources'] = []
app['python_path'] = None
app['port'] = 8888
app['login'] = {}
app['login']['urls'] = {}
app['login']['urls']['default'] = '/login'
app['is_on_dir'] = False

# Data default configuration
data = {}
Expand Down
134 changes: 131 additions & 3 deletions firenado/core/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,14 @@

from __future__ import (absolute_import, division,
print_function, with_statement)

import inspect
import os
from tornado.escape import json_encode
import tornado.web


class TornadoApplication(tornado.web.Application):
"""
Firenado basic Tornado application.
"""Firenado basic Tornado application.
"""

def __init__(self, handlers=None, default_host="", transforms=None,
Expand All @@ -35,3 +36,130 @@ def __init__(self, handlers=None, default_host="", transforms=None,

tornado.web.Application.__init__(self, composed_handlers, default_host,
transforms, **settings)


class TornadoComponent(object):
"""Firenado applications are organized in components. A component could be
the proper application or something that can be distributed as an add-on or
a plugin.
"""

def __init__(self, name, application, config={}):
self.name = name
self.application = application
self.config = config
self.plugins = dict()

def get_handlers(self):
"""Return handlers being added by the component to the application.
"""
return []

def get_component_path(self):
"""Return the component path.
"""
return os.path.dirname(inspect.getfile(self.__class__))

def get_template_path(self):
"""Return the path that holds the component's templates.
"""
return os.path.join(os.path.dirname(
inspect.getfile(self.__class__)), 'templates')


class TornadoHandler(tornado.web.RequestHandler):
""" Base request handler to be used on a Firenado application.
It provides session and handles component paths.
"""

def __init__(self, application, request, **kwargs):
self.component = None
self.__template_variables = dict()
super(TornadoHandler, self).__init__(application, request, **kwargs)

def initialize(self, component):
self.component = component

def add_variable_to_template(self, name, variable):
""" Add a variable to a dict that will be added to the template during
the render or render_string execution.
"""
self.__template_variables[name] = variable

def render_string(self, template_name, **kwargs):
ignore_component = False
application_component = None
for key in ('ignore_component', 'component',):
if key in kwargs:
if key is 'ignore_component':
ignore_component = kwargs[key]
if key is 'component':
pass
kwargs['user_agent'] = self.user_agent if hasattr(
self, 'user_agent') else None
kwargs['credential'] = self.credential if hasattr(
self, 'credential') else None
for name, variable in self.__template_variables.iteritems():
kwargs[name] = variable
if self.ui:
return super(TornadoHandler, self).render_string(
template_name, **kwargs)
else:
# TODO: After a redirect I'm still hitting here.
# Need to figure out what is going on.
self._finished = False
return None

def write_error(self, status_code, **kwargs):
error_stack = {'code': status_code}

exc_info = None
for key in kwargs:
if key == 'exc_info':
exc_info = kwargs[key]
error = exc_info[1]

if type(error) == JSONError:
error_stack.update(error.data)
response = dict(data=None, error=error_stack)
self.write(response)
else:
raise error

def get_firenado_template_path(self):
"""Override to customize the firenado template path for each handler.

By default, we use the ``firenado_template_path`` application setting.
Return None to load templates relative to the calling file.
"""
return self.application.settings.get('firenado_template_path')

def get_template_path(self):
"""Override to customize template path for each handler.

By default, we use the ``template_path`` application setting.
Return None to load templates relative to the calling file.
"""
if self.component is None:
# This is the default behaviour provided by Tornado.
# No components on the request no fancy template path.
return super(TornadoHandler, self).get_template_path()
else:
return self.component.get_template_path()


#TODO: This is iFlux migration leftover. Need to figure out we should keep
# that.
class JSONError(tornado.web.HTTPError):

data = {}

def __init__(self, status_code, log_message=None, *args, **kwargs):
self.data.update(log_message)
if not isinstance(log_message, basestring):
json_log_message = self.data
json_log_message['code'] = status_code
json_log_message = json_encode(json_log_message)
super(JSONError, self).__init__(
status_code, json_log_message, *args, **kwargs)

7 changes: 4 additions & 3 deletions firenado/core/management/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
print_function, with_statement)

import firenado.conf
from firenado.util.argparse_util import ArgumentParserException
from firenado.util.argparse_util import FirenadoArgumentError
from firenado.util.argparse_util import FirenadoArgumentParser
import os
import sys
Expand Down Expand Up @@ -48,7 +48,7 @@ def run_from_command_line():
show_command_line_usage(parser)
else:
run_command(namespace.command, sys.argv[command_index-1:])
except ArgumentParserException:
except FirenadoArgumentError:
show_command_line_usage(parser, True)


Expand Down Expand Up @@ -147,7 +147,7 @@ def run_tasks(self, args):
namespace = cmd_parser.parse_args(args)
for task in self.tasks:
task.run(namespace)
except ArgumentParserException as exception:
except FirenadoArgumentException as exception:
command_help = ""
for task in self.tasks:
if task.get_error_message(cmd_parser, exception):
Expand Down Expand Up @@ -184,3 +184,4 @@ def run(self, namespace=None):
"""
Task implementation is done here.
"""

2 changes: 1 addition & 1 deletion firenado/core/management/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

ManagementCommand(
'Firenado', 'app', 'Application related commands', '',
tasks.CreateProjectTask)
tasks.ValidateAppCommandsTask)
ManagementCommand(
'Firenado', 'project',
'Project related commands', '', tasks.ValidateProjectCommandsTask)
Expand Down
47 changes: 43 additions & 4 deletions firenado/core/management/tasks/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,39 @@
import firenado.conf
from firenado.core.management import ManagementTask
from firenado.util import file as _file
from firenado.util.argparse_util import FirenadoArgumentError

import os
import sys
from tornado import template

class ValidateProjectCommandsTask(ManagementTask):
class ValidateAppCommandsTask(ManagementTask):
"""Validate application related commands
"""
Validates project related commands
def run(self, namespace):
print "buuu"
if namespace.app_command == 'start':
task = StartAppTask(namespace)

def add_arguments(self, parser):
parser.add_argument(
'app_command', type=str,
choices=['start'], help="The ")

class ValidateProjectCommandsTask(ManagementTask):
"""Validate project related commands
"""
def run(self, namespace):
if namespace.project_command == 'init':
task = CreateProjectTask()
task.add_arguments(namespace)
task = CreateProjectTask(namespace)
task.add_arguments(self.parser)
try:
self.parser.parse_args()
except FirenadoArgumentError as exception:
print exception.message

def add_arguments(self, parser):
self.parser = parser
parser.add_argument(
'project_command', type=str,
choices=['init'], help="The project module")
Expand All @@ -45,6 +63,7 @@ def get_error_message(self, parser, exception):
help_message = loader.load("init_command_help.txt").generate()
return help_message


class CreateProjectTask(ManagementTask):
"""
Creates a new project from scratch
Expand Down Expand Up @@ -96,3 +115,23 @@ def add_arguments(self, parser):
task.
"""
parser.add_argument('module', help="The project module")

def get_error_message(self, parser, exception):
return exception.message



class StartAppTask(ManagementTask):
""" Task that starts an Firenado Tornado Application based
on the it's project configuration
"""
def run(self, namespace):
import tornado.ioloop
import tornado.httpserver
# TODO: Resolve module if doesnt exists
if firenado.conf.app['python_path']:
sys.path.append(firenado.conf.app['python_path'])
http_server = tornado.httpserver.HTTPServer(
firenado.core.TornadoApplication())
http_server.listen(firenado.conf.app['port'])
tornado.ioloop.IOLoop.instance().start()
2 changes: 1 addition & 1 deletion firenado/core/management/templates/init/firenado.yaml.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
application:
app:
port: 8888
data:
sources:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Firenado Framework

Usage: project init <project_name>
7 changes: 4 additions & 3 deletions firenado/util/argparse_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@
from gettext import gettext as _


class ArgumentParserException(Exception):
""" Class to be used IfluxArgumentParser when an error occur.
class FirenadoArgumentError(Exception):
""" An error thrown while parsing arguments with FirenadoArgumentParser.
"""
pass

Expand All @@ -33,4 +33,5 @@ class FirenadoArgumentParser(argparse.ArgumentParser):
def error(self, message):
args = {'prog': self.prog, 'message': message}
message = _('%(prog)s: error: %(message)s\n') % args
raise ArgumentParserException(message)
raise FirenadoArgumentError(message)