Skip to content

Commit

Permalink
Merge pull request #348 from candango/develop
Browse files Browse the repository at this point in the history
Merging develop to master.
  • Loading branch information
piraz committed Mar 14, 2021
2 parents 2711d61 + 9f4e944 commit d0df29d
Show file tree
Hide file tree
Showing 12 changed files with 136 additions and 164 deletions.
4 changes: 1 addition & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
# https://travis-ci.org/candango/firenado
language: python
python:
- "2.7"
- "3.5"
- "3.6"
- "3.7"
- "3.8"
- "3.9"
install:
- "pip install -r requirements/basic.txt"
- "pip install -r requirements/all.txt"
- "pip install -r requirements/tests.txt"
- ./scripts/install_tornado.sh
script:
- "PYTHONPATH=$PYTHONPATH:. python tests/runtests.py"
- ./scripts/run_behave.sh
2 changes: 0 additions & 2 deletions MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ include requirements/pexpect.txt
include requirements/redis.txt
include requirements/schedule.txt
include requirements/sqlalchemy.txt
include requirements/tornado_legacy.txt
include requirements/tornado_new.txt
include firenado/conf/*.yml
include firenado/management/templates/*/*.txt
include firenado/components/*/conf/*.yaml.example
Expand Down
2 changes: 1 addition & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
# The short X.Y version.
version = '0.2'
# The full version, including alpha/beta/rc tags.
release = '0.2.6'
release = '0.2.7'

# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
Expand Down
1 change: 1 addition & 0 deletions docs/releases.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ Release notes
.. toctree::
:maxdepth: 2

releases/v0.2.7
releases/v0.2.6
releases/v0.2.5
releases/v0.2.4
Expand Down
31 changes: 31 additions & 0 deletions docs/releases/v0.2.7.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
What's new in Firenado 0.2.7
============================

Mar 14, 2021
------------

We are pleased to announce the release of Firenado 0.2.7.

Upgraded to Tornado 6.1. Python 2.7 and 3.5 are no longer supported.

Significant refactory to unify TornadoHandler and TornadoWebSocketHandler
logic.


Here are the highlights:

Bug Fixes
~~~~~~~~~

* Launcher won't launch on Windows with python 3.9. `#339 <https://github.com/candango/firenado/issues/339>`_

New Features
~~~~~~~~~~~~

* Upgrade tornado to 6.1. `#344 <https://github.com/candango/firenado/issues/344>`_
* Remove Python 2.7 and 3.5 from the support list. `#343 <https://github.com/candango/firenado/issues/343>`_

Refactory
~~~~~~~~~

* Unify TornadoHandler and TornadoWebSocketHandler logic. `#342 <https://github.com/candango/firenado/issues/342>`_
8 changes: 4 additions & 4 deletions examples/chatdemows/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env python
#
# Copyright 2015-2016 Flavio Garcia
# Copyright 2015-2021 Flavio Garcia
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
Expand All @@ -14,14 +14,14 @@
# See the License for the specific language governing permissions and
# limitations under the License.

import chatdemows.handlers
from . import handlers
import firenado.tornadoweb


class ChatdemoWsComponent(firenado.tornadoweb.TornadoComponent):

def get_handlers(self):
return [
(r'/', chatdemows.handlers.MainHandler),
(r"/chatsocket", chatdemows.handlers.ChatSocketHandler),
(r'/', handlers.MainHandler),
(r"/chatsocket", handlers.ChatSocketHandler),
]
2 changes: 1 addition & 1 deletion firenado/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
from __future__ import (absolute_import, division, print_function,
with_statement)
__author__ = "Flavio Garcia <piraz@candango.org>"
__version__ = (0, 2, 6)
__version__ = (0, 2, 7)
__licence__ = "Apache License V2.0"


Expand Down
233 changes: 95 additions & 138 deletions firenado/tornadoweb.py
Original file line number Diff line number Diff line change
Expand Up @@ -323,24 +323,13 @@ def shutdown(self):
pass


class TornadoHandler(tornado.web.RequestHandler):
""" Base request handler to be used on a Firenado application.
It provides session and handles component paths.
class SessionHandler:
""" Set the stage for a handler with session. The session per-se will be
managed by the ComponentHandler that extends SessionHandler.
"""
def __init__(self, application, request, **kwargs):
self.component = None
self.session = 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 __init__(self):
self.session = None

def authenticated(self):
""" Returns if the current user is authenticated. If the current user
Expand All @@ -350,13 +339,24 @@ def authenticated(self):
"""
return self.current_user is not None

def is_mobile(self):
from mobiledetect import MobileDetect
if 'User-Agent' in self.request.headers:
return MobileDetect(
useragent=self.request.headers['User-Agent']
).is_mobile()
return False

class ComponentHandler(SessionHandler):
""" This mixing will define a handler with components and session.
ComponentHandler is the base of what a Firenado handler should be and it
will be used to unify TornadoHandler and TornadoWebSocketHandler logic.
Other functionalities will be implemented in TemplateHandler that assumes
the handler being applied to is also a ComponentHandler.
"""

def __init__(self, **kwargs):
self.component = None
SessionHandler.__init__(self)

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

def get_data_connected(self):
return self.application

def write_error(self, status_code: int, **kwargs: Any) -> None:
"""
Expand Down Expand Up @@ -428,46 +428,43 @@ def before_request(self):
"""
pass


class TemplateHandler:
""" Deals with all aspects related to templates. The mixin will assume
it was applied to a ComponentHandler so we can resolve and deal with
templates defined in the same component or other components from the
application.
"""

def __init__(self):
self.__template_variables = dict()

@property
def template_variables(self):
return self.__template_variables

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 == 'ignore_component':
ignore_component = kwargs[key]
if key == '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 iteritems(self.__template_variables):
for name, variable in iteritems(self.template_variables):
kwargs[name] = variable
if self.ui:
return super(TornadoHandler, self).render_string(
return super(TemplateHandler, 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 get_data_connected(self):
return self.application

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_rooted_path(self, path):
from .util.url_util import rooted_path
root = firenado.conf.app['url_root_path']
return rooted_path(root, path)

def get_template_path(self):
"""Override to customize template path for each handler.
Expand All @@ -481,6 +478,14 @@ def get_template_path(self):
else:
return self.component.get_template_path()

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 create_template_loader(self, template_path):
"""Returns a new template loader for the given path.
Expand All @@ -499,6 +504,47 @@ def create_template_loader(self, template_path):
template_path, component=self.component, **kwargs)


class WebUtilHandler:
""" Holds everything else related to web utilities.
"""

def is_mobile(self):
from mobiledetect import MobileDetect
if 'User-Agent' in self.request.headers:
return MobileDetect(
useragent=self.request.headers['User-Agent']
).is_mobile()
return False

def get_rooted_path(self, path):
from .util.url_util import rooted_path
root = firenado.conf.app['url_root_path']
return rooted_path(root, path)


class TornadoHandler(ComponentHandler, TemplateHandler, WebUtilHandler,
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):
ComponentHandler.__init__(self, **kwargs)
TemplateHandler.__init__(self)
tornado.web.RequestHandler.__init__(self, application, request,
**kwargs)


class TornadoWebSocketHandler(ComponentHandler, TemplateHandler,
WebUtilHandler,
tornado.websocket.WebSocketHandler):

def __init__(self, application, request, **kwargs):
ComponentHandler.__init__(self, **kwargs)
TemplateHandler.__init__(self)
tornado.websocket.WebSocketHandler.__init__(
self, application, request, **kwargs)


class FirenadoComponentLoader(Loader):
""" A template loader that loads from a single root directory.
"""
Expand Down Expand Up @@ -530,92 +576,3 @@ def resolve_path(self, name, parent_path=None):

return super(FirenadoComponentLoader,
self).resolve_path(name_resolved, parent_path)


# TODO: We need to create a class to avoid those methods repeated here.
class TornadoWebSocketHandler(tornado.websocket.WebSocketHandler):

def __init__(self, application, request, **kwargs):
self.component = None
self.__template_variables = dict()
super(TornadoWebSocketHandler, 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

@session.read
def prepare(self):
self.component.before_handler(self)

@session.write
def on_finish(self):
self.component.after_handler(self)

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 == 'ignore_component':
ignore_component = kwargs[key]
if key == '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 iteritems(self.__template_variables):
kwargs[name] = variable
if self.ui:
return super(TornadoWebSocketHandler, 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 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(TornadoWebSocketHandler, self).get_template_path()
else:
return self.component.get_template_path()

def create_template_loader(self, template_path):
"""Returns a new template loader for the given path.
May be overridden by subclasses. By default returns a
directory-based loader on the given path, using the
``autoescape`` application setting. If a ``template_loader``
application setting is supplied, uses that instead.
"""
settings = self.application.settings
kwargs = {}
if 'autoescape' in settings:
# autoescape=None means "no escaping", so we have to be sure
# to only pass this kwarg if the user asked for it.
kwargs['autoescape'] = settings['autoescape']
return FirenadoComponentLoader(
template_path, component=self.component, **kwargs)

0 comments on commit d0df29d

Please sign in to comment.