Skip to content

Commit

Permalink
Merge pull request #302 from candango/develop
Browse files Browse the repository at this point in the history
Merging develop to master.
  • Loading branch information
piraz committed Mar 5, 2020
2 parents 5cf97bc + 061e932 commit cc6cbfe
Show file tree
Hide file tree
Showing 45 changed files with 385 additions and 477 deletions.
4 changes: 3 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@
language: python
python:
- "2.7"
- "3.4"
- "3.5"
- "3.6"
- "3.7"
- "3.8"
install:
- "pip install -r requirements/basic.txt"
- "pip install -r requirements/all.txt"
- "pip install -r requirements/tests.txt"
script:
- "PYTHONPATH=$PYTHONPATH:. python tests/runtests.py"
- ./scripts/run_behave.sh
1 change: 1 addition & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
include LICENSE
include README.md
include requirements/all.txt
include requirements/basic.txt
include requirements/pexpect.txt
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.1.8
releases/v0.1.7.8
releases/v0.1.7.7
releases/v0.1.7.6
Expand Down
41 changes: 41 additions & 0 deletions docs/releases/v0.1.8.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
What's new in Firenado 0.1.8
=============================

Mar 04, 2020
------------

We are pleased to announce the release of Firenado 0.1.8.

We still support python 2.7 in the main development contrary to the announce
from 0.1.7.8 but we started to relax tests against 2.7 and prepare the code
base for a python 3.x only.

Firenado gave birth to Cartola and we added this project to the basic
dependency.

This version fixes definitely the process launcher shutdown making easier to
spam and teardown Firenado application in a test and that's the reason we still
keep with python 2.7.

A new json session encoder were added to the available list of session encoders
making it easier to share session data between applications that don't have
pikle encoding/serialization.

Here are the highlights:

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

* Add json session encoder to the project. `#295 <https://github.com/candango/firenado/issues/295>`_
* Clean sys.path and set PYTHONPATH before launch a process. . `#299 <https://github.com/candango/firenado/issues/299>`_

Bug Fixes
~~~~~~~~~
* Process launcher shutdown doesn't work. `#290 <https://github.com/candango/firenado/issues/290>`_

Refactory
~~~~~~~~~
* Use pymobiledetect instead of util.browser. `#292 <https://github.com/candango/firenado/issues/292>`_
* Use cartola instead of util.sysexits. `#293 <https://github.com/candango/firenado/issues/293>`_
* Use cartola instead of util.file. `#294 <https://github.com/candango/firenado/issues/294>`_
* Use cartola instead of local security package. `#296 <https://github.com/candango/firenado/issues/296>`_
2 changes: 1 addition & 1 deletion examples/feed/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
feedgen==0.4.0
feedgen==0.9.0
pytz==2016.6.1
1 change: 1 addition & 0 deletions examples/testapp/conf/firenado.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ session:
# Scan interval by default is 2 minutes = 120 seconds
# scan_interval: 120
# Redis session handler configuration
encoder: json
data:
source: session
# File session handler related configuration
Expand Down
4 changes: 4 additions & 0 deletions examples/testapp/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import firenado.conf
from firenado import security, service, tornadogen, tornadoweb
from firenado.components.toolbox.pagination import Paginator
import hashlib
from tornado import gen
import logging

Expand Down Expand Up @@ -112,6 +113,9 @@ def post(self):
errors['fail'] = "Invalid login"
else:
user = self.user_service.by_username(username)
# Shhhhh!!!! this is a secret.
user['pass'] = hashlib.sha256(
"_".join(user['pass']).encode('ascii')).hexdigest()
self.session.set("user", json_encode(user))
self.redirect(self.get_rooted_path("private"))

Expand Down
6 changes: 2 additions & 4 deletions examples/testapp/services.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env python
#
# Copyright 2015-2017 Flavio Garcia
# Copyright 2015-2020 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,9 +14,9 @@
# See the License for the specific language governing permissions and
# limitations under the License.

from firenado import service
from .models import UserBase
import datetime
from firenado import service


def password_digest(pass_phrase):
Expand Down Expand Up @@ -73,5 +73,3 @@ def by_username(self, username):
if username == "test":
user = {'usename': "test", 'pass': "testpass"}
return user


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, 1, 7, 8)
__version__ = (0, 1, 8, 1)
__licence__ = "Apache License V2.0"


Expand Down
5 changes: 3 additions & 2 deletions firenado/conf/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# -*- coding: UTF-8 -*-
#
# Copyright 2015-2019 Flavio Garcia
# Copyright 2015-2020 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 @@ -21,6 +21,7 @@
import logging
import os
import sys
import tempfile

# Setting root path
ROOT = None
Expand Down Expand Up @@ -80,7 +81,7 @@

# Tmp path variable
# TODO: Should I care about windows?
TMP_SYS_PATH = "/tmp"
TMP_SYS_PATH = tempfile.gettempdir()
TMP_APP_PATH = TMP_SYS_PATH

# Setting firenado's default variables
Expand Down
2 changes: 2 additions & 0 deletions firenado/conf/firenado.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ session:
- name: redis
class: firenado.session.RedisSessionHandler
encoders:
- name: json
class: firenado.session.JsonSessionEncoder
- name: pickle
class: firenado.session.PickeSessionEncoder
id_generators:
Expand Down
17 changes: 13 additions & 4 deletions firenado/config.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# -*- coding: UTF-8 -*-
#
# Copyright 2015-2019 Flavio Garcia
# Copyright 2015-2020 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,8 +14,10 @@
# See the License for the specific language governing permissions and
# limitations under the License.

from cartola import sysexits
import yaml
import logging
import os


def get_app_defaults():
Expand Down Expand Up @@ -73,6 +75,7 @@ def log_level_from_string(str_level):
'WARNING': logging.WARNING,
'INFO': logging.INFO,
'DEBUG': logging.DEBUG,
'NOTSET': logging.NOTSET,
}
try:
return levels[str_level.upper()]
Expand Down Expand Up @@ -202,7 +205,7 @@ def process_app_config(config, config_data):
config.is_multi_app = True
process_apps_config_session(config, config_data['apps'])
if 'app' in config_data:
from .util import sysexits

logger = logging.getLogger(__name__)
logger.critical("Firenado is running in multi application mode. "
"The app section is only allowed in simple "
Expand All @@ -216,8 +219,6 @@ def process_app_config(config, config_data):

# TODO: This is being used for the multi app configuration
def process_apps_config_session(config, apps_config):
from .util import sysexits
import os
logger = logging.getLogger(__name__)

class AppConf:
Expand Down Expand Up @@ -442,3 +443,11 @@ def process_session_config_section(config, session_config):
config.session['callback_time'] = session_config['callback_time']
if 'purge_limit' in session_config:
config.session['purge_limit'] = session_config['purge_limit']
if 'encoder' in session_config:
if session_config['encoder'] in config.session['encoders']:
config.session['encoder'] = session_config['encoder']
else:
logger = logging.getLogger(__name__)
logger.critical("The session encoder \"{}\" is not defined."
"".format(session_config['encoder']))
sysexits.exit_fatal(sysexits.EX_CONFIG)
30 changes: 25 additions & 5 deletions firenado/launcher.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# -*- coding: UTF-8 -*-
#
# Copyright 2015-2019 Flavio Garcia
# Copyright 2015-2020 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,6 +14,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.

from cartola import sysexits
import firenado.conf
import logging
import os
Expand All @@ -38,6 +39,9 @@ class FirenadoLauncher(object):

def __init__(self, **settings):
self.app = settings.get("app", None)
self.path = settings.get("path", None)
if self.path is not None:
sys.path.append(self.path)
if self.app:
os.environ["CURRENT_APP"] = self.app
if os.environ.get("CURRENT_APP"):
Expand All @@ -47,6 +51,23 @@ def __init__(self, **settings):
self.port = settings.get("port", None)
self.socket = settings.get("socket", None)

# Fixing and cleaning PYTHONPATH and sys.path
# This is useful so we can run a process launcher with the same
# PYTHONPATH from the parent process
real_pythonpaths = []
if os.environ['PYTHONPATH'] is not None:
current_pythonpaths = os.environ['PYTHONPATH'].split(":")
for path in current_pythonpaths:
if path.strip() != "":
if path.strip() not in real_pythonpaths:
real_pythonpaths.append(path.strip())
for path in sys.path:
if path.strip() != "":
if path.strip() not in real_pythonpaths:
real_pythonpaths.append(path.strip())
sys.path = real_pythonpaths
os.environ['PYTHONPATH'] = ":".join(real_pythonpaths)

def load(self):
return None

Expand Down Expand Up @@ -128,12 +149,12 @@ def send(self, line):
logger.info("Sending line {}".format(line))
self.process.sendline(line)

@gen.coroutine
def shutdown(self):
logger.warning("Shutting down process launcher.")
self.send("^C")
yield self.process.expect("^C", async_=True)
self.process.terminate(force=True)

def is_alive(self):
return self.process.isalive()

class TornadoLauncher(FirenadoLauncher):

Expand Down Expand Up @@ -209,7 +230,6 @@ def launch(self):
tornado.process.fork_processes(num_processes, max_restarts)
tornado.ioloop.IOLoop.current().start()
else:
from .util import sysexits
logger.critical("Firenado unable to start.")
sysexits.exit_fatal(sysexits.EX_SOFTWARE)

Expand Down
32 changes: 17 additions & 15 deletions firenado/management/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,14 @@
# See the License for the specific language governing permissions and
# limitations under the License.

from cartola import fs
import firenado.conf
from firenado.management import ManagementTask
from firenado.util import argparse_util
import logging
import sys

import os
from six import iteritems

import firenado.conf
from firenado.management import ManagementTask
from firenado.util import file as _file, argparse_util
import sys

logger = logging.getLogger(__name__)

Expand All @@ -37,7 +36,7 @@ def run(self, namespace):
module = namespace.module
component = module.replace(".", " ").title().replace(" ", "")
project_name = module.replace(".", "_").lower()
project_directory = _file.create_module(module, os.getcwd())
project_directory = fs.create_module(module, os.getcwd())
#TODO: Check if project exists
#TODO: If doesn't exists create project
#TODO: If exists throw an error
Expand All @@ -47,24 +46,24 @@ def run(self, namespace):
project_init_content = loader.load("app.py.txt").generate(
project_name=project_name, module=module, component=component)
# Generating application firenado component and handlers
_file.write(os.path.join(project_directory, "__init__.py"), "")
_file.write(os.path.join(project_directory, "app.py"),
fs.write(os.path.join(project_directory, "__init__.py"), "")
fs.write(os.path.join(project_directory, "app.py"),
project_init_content.decode(sys.stdout.encoding))
handlers_file_name = os.path.join(project_directory, "handlers.py")
_file.touch(handlers_file_name)
fs.touch(handlers_file_name)
project_handlers_content = loader.load("handlers.py.txt").generate(
handlers=["Index"])
_file.write(handlers_file_name,
fs.write(handlers_file_name,
project_handlers_content.decode(sys.stdout.encoding))
# Generating configuration
project_conf_directory = os.path.join(project_directory, "conf")
os.mkdir(project_conf_directory)
project_conf_file = os.path.join(project_conf_directory,
"firenado.yml")
_file.touch(project_conf_file)
fs.touch(project_conf_file)
project_init_content = loader.load("firenado.yml.txt").generate(
app_name=project_name, module=module, component=component)
_file.write(project_conf_file,
fs.write(project_conf_file,
project_init_content.decode(sys.stdout.encoding))
else:
#TODO: This thing has to go. The parameter validation should be
Expand Down Expand Up @@ -114,6 +113,7 @@ def add_arguments(self, parser):
parser.add_argument("-a", "--addresses", default=None)
parser.add_argument("-A", "--app", default=None)
parser.add_argument("-d", "--dir", default=None)
parser.add_argument("-p", "--path", default=None)
parser.add_argument("-P", "--port", type=int)
parser.add_argument("-s", "--socket", default=None)

Expand All @@ -128,6 +128,8 @@ def run(self, namespace):
parameters['app'] = namespace.app
if namespace.dir is not None:
parameters['dir'] = namespace.dir
if namespace.path is not None:
parameters['path'] = namespace.path
if namespace.socket is None:
if namespace.addresses is not None:
parameters['addresses'] = namespace.addresses.split(",")
Expand All @@ -150,14 +152,14 @@ def add_arguments(self, parser):
parser.add_argument("size", nargs='?', default=64, type=int)

def run(self, namespace):
from firenado.util import random_string
from cartola import security
size = namespace.size
if size > 1000000:
logger.error("The size {} has reached this command "
"limit.".format(size))
sys.exit(1)
logger.debug("Displaying a random string with size {}".format(size))
print(random_string(size))
print(security.random_string(size))
sys.exit(0)


Expand Down

0 comments on commit cc6cbfe

Please sign in to comment.