Skip to content

Commit

Permalink
Merge branch 'development'
Browse files Browse the repository at this point in the history
  • Loading branch information
hkage committed Mar 14, 2017
2 parents 9451d5d + 82d454d commit 12d3f8b
Show file tree
Hide file tree
Showing 39 changed files with 1,420 additions and 70 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,7 @@ dist
# Vagrant
.vagrant
.bash_history

.idea

.tox
8 changes: 8 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
language: python
python:
- "2.7"
- "3.3"
- "3.4"
- "3.5"
install: "pip install -r requirements_dev.txt"
script: py.test
9 changes: 8 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
Changelog
===

0.2.0 (2016-07-xx)
Development
---

0.2.0 (2017-03-14)
---
* #2: Changed the boilerplate to a Cookiecutter template
* Added tox file for testing
* Added .editorconfig
* Added Sphinx documentation
* Added bumpversion support
* Added docker-compose file
* Fixed Vagrant setup

0.1.1 (2016-01-11)
---
Expand Down
2 changes: 2 additions & 0 deletions CONTRIBUTORS
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Dectinc <[email protected]>
Henning Kage <[email protected]>
22 changes: 14 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,26 @@
Tornado Cookiecutter template
===

[![Build Status](https://travis-ci.org/hkage/cookiecutter-tornado.svg?branch=development)](https://travis-ci.org/hkage/cookiecutter-tornado)

This is my cookiecutter template to build a simple, fast and rock solid website based upon
the Tornado framework. There are quite many Tornado template projects out there,
but I wanted to start something from scratch, that fits my needs and evolves out
of years of experiences (positive and negative alike) with other Python based webframeworks like Turbogears and Django.
of years of experiences (positive and negative alike) with other Python based webframeworks
like Turbogears and Django.

Of course this template is not designed for larger data structures. The main
focus is on scalability, fast data access and small library dependencies.

Features
---
* Configurable as a Cookiecutter template
* pytest and tox for testing
* Vagrant and Docker support
* Basic [HTML5 Boilerplate](https://html5boilerplate.com/)
* SASS for CSS generation
* (Optional) pytest
* (Optional) tox
* (Optional) [Bumpversion](https://github.com/peritus/bumpversion) for updating version information
* (Optional) Docker support
* (Optional) Vagrant support

Installation
---
Expand All @@ -30,6 +35,7 @@ Initialize the project with cookiecutter and answer some questions for the newly

Configuration
---
...

Testing
---
Expand All @@ -44,7 +50,7 @@ To start the final application, just run the following fabric command:

$ fab devserver

This will tell Tornado to start the applicaton with the default port 8888. If
This will tell Tornado to start the application with the default port 8888. If
you want to use another port, just type:

$ fab devserver:port=8000
Expand All @@ -66,9 +72,9 @@ You can now access your application via `http://localhost:8000`
Docker
---

To run the application within Docker, you need to build and then run the image:
Install docker and docker compose in the latest version. Then start the tornado
project with docker-compose:

$ sudo docker build --tag=tornado-app --rm=true .
$ sudo docker run -p 8000:8000 -t -i tornado-app:latest
$ docker-compose up

You can now access your application via `http://localhost:8000`
5 changes: 5 additions & 0 deletions cookiecutter.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,14 @@
"project_slug": "{{ cookiecutter.project_name.lower()|replace(' ', '_')|replace('-', '_') }}",
"author_name": "Your name",
"email": "Your e-mail",
"github_username": "yourname",
"repo_name": "tornado-project",
"description": "A short description of the project.",
"version": "0.1.0",
"use_pytest": "y",
"use_tox": "y",
"use_docker": "y",
"use_vagrant": "y",
"use_bumpversion": "y",
"open_source_license": ["MIT", "BSD", "GPLv3", "Apache Software License 2.0", "Not open source"]
}
61 changes: 57 additions & 4 deletions hooks/post_gen_project.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,66 @@
"""Post generation script"""

import os
import string
import random


PROJECT_DIRECTORY = os.path.realpath(os.path.curdir)


if '{{ cookiecutter.use_docker }}'.lower() == 'n':
os.remove(os.path.join(PROJECT_DIRECTORY, 'Dockerfile'))
def generate_random_string(length=25,
allowed_chars=string.ascii_letters + string.digits):
"""
Generate a random string.
if '{{ cookiecutter.use_vagrant }}'.lower() == 'n':
os.remove(os.path.join(PROJECT_DIRECTORY, 'Vagrantfile'))
:param length: The length of the desired string
:type length: int
:param allowed_chars: The set of allowed characters
:type allowed_chars: str
:returns: Random string
:rtype: str
"""
return ''.join(random.choice(allowed_chars) for i in range(length))


def remove_file(filepath):
"""
Remove a file with the given path.
:param str filepath: Path of the file.
"""
os.remove(os.path.join(PROJECT_DIRECTORY, filepath))


def set_cookie_secret(project_directory):
"""
Open the settings and generate a secure cookie secret.
:param str project_directory: Path of the project directory.
"""
project_settings_file = os.path.join(project_directory, 'settings.py')
with open(project_settings_file) as f:
file_ = f.read()
file_ = file_.replace('!!CHANGEME!!', generate_random_string())
with open(project_settings_file, 'w') as f:
f.write(file_)


if __name__ == '__main__':
if '{{ cookiecutter.use_docker }}'.lower() in ('n', 'no'):
remove_file('Dockerfile')

if '{{ cookiecutter.use_vagrant }}'.lower() in ('n', 'no'):
remove_file('Vagrantfile')

if '{{ cookiecutter.use_bumpversion }}'.lower() in ('n', 'no'):
remove_file('.bumpversion.cfg')

if '{{ cookiecutter.use_tox }}'.lower() in ('n', 'no'):
remove_file('tox.ini')

if '{{ cookiecutter.use_pytest }}'.lower() in ('n', 'no'):
remove_file('pytest.ini')

# Replace the cookie secret
set_cookie_secret(PROJECT_DIRECTORY)
8 changes: 8 additions & 0 deletions hooks/pre_gen_project.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# -*- coding: utf-8 -*-

"""Pre generation script"""

import os


PROJECT_DIRECTORY = os.path.realpath(os.path.curdir)
2 changes: 2 additions & 0 deletions pytest.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[pytest]
testpaths = tests/
5 changes: 5 additions & 0 deletions requirements_dev.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
bumpversion==0.5.3
cookiecutter>=1.5.0
pytest==3.0.5
pytest-cookies==0.2.0
tox==2.5.0
11 changes: 11 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[bumpversion]
current_version = 0.1.1
commit = True
tag = True

[metadata]
description-file = README.md

[bumpversion:file:setup.py]
search = version='{current_version}'
replace = version='{new_version}'
30 changes: 30 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# !/usr/bin/env python

from distutils.core import setup

setup(
name='cookiecutter-tornado',
packages=[],
version='0.1.1',
description='Cookiecutter template for Tornado based projects',
author='Henning Kage',
author_email='[email protected]',
url='https://github.com/hkage/cookiecutter-tornado',
keywords=['cookiecutter', 'template', 'tornado', ],
classifiers=[
'Development Status :: 4 - Beta',
'Environment :: Console',
'Intended Audience :: Developers',
'Natural Language :: English',
'License :: OSI Approved :: BSD License',
'Programming Language :: Python',
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: Implementation :: CPython',
'Programming Language :: Python :: Implementation :: PyPy',
'Topic :: Software Development',
],
)
104 changes: 104 additions & 0 deletions tests/test_bake_project.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
"""Tests for the cookiecutter template."""

from contextlib import contextmanager

from cookiecutter.utils import rmtree
import pytest


@contextmanager
def bake_in_temp_dir(cookies, *args, **kwargs):
result = cookies.bake(*args, **kwargs)
try:
yield result
finally:
rmtree(str(result.project))


def test_bake_project_with_defaults(cookies):
with bake_in_temp_dir(cookies) as result:
assert result.exit_code == 0
assert result.exception is None
assert result.project.isdir()
found_toplevel_files = [f.basename for f in result.project.listdir()]
assert 'setup.py' in found_toplevel_files
assert 'tox.ini' in found_toplevel_files
assert 'Dockerfile' in found_toplevel_files
assert 'tests' in found_toplevel_files


@pytest.mark.parametrize('with_docker_support, expected_result', [
('y', True),
('yes', True),
('YES', True),
('n', False),
('no', False),
('NO', False),
])
def test_docker_support(cookies, with_docker_support, expected_result):
with bake_in_temp_dir(cookies, extra_context={'use_docker': with_docker_support}) as result:
found_toplevel_files = [f.basename for f in result.project.listdir()]
assert ('Dockerfile' in found_toplevel_files) == expected_result


@pytest.mark.parametrize('with_vagrant_support, expected_result', [
('y', True),
('yes', True),
('YES', True),
('n', False),
('no', False),
('NO', False),
])
def test_vagrant_support(cookies, with_vagrant_support, expected_result):
with bake_in_temp_dir(cookies, extra_context={'use_vagrant': with_vagrant_support}) as result:
found_toplevel_files = [f.basename for f in result.project.listdir()]
assert ('Vagrantfile' in found_toplevel_files) == expected_result


@pytest.mark.parametrize('with_bumpversion_support, expected_result', [
('y', True),
('yes', True),
('YES', True),
('n', False),
('no', False),
('NO', False),
])
def test_bumpversion_support(cookies, with_bumpversion_support, expected_result):
with bake_in_temp_dir(cookies, extra_context={'use_bumpversion': with_bumpversion_support}) as result:
found_toplevel_files = [f.basename for f in result.project.listdir()]
assert ('.bumpversion.cfg' in found_toplevel_files) == expected_result


@pytest.mark.parametrize('with_pytest_support, expected_result', [
('y', True),
('yes', True),
('YES', True),
('n', False),
('no', False),
('NO', False),
])
def test_pytest_support(cookies, with_pytest_support, expected_result):
with bake_in_temp_dir(cookies, extra_context={'use_pytest': with_pytest_support}) as result:
found_toplevel_files = [f.basename for f in result.project.listdir()]
assert ('pytest.ini' in found_toplevel_files) == expected_result


@pytest.mark.parametrize('with_tox_support, expected_result', [
('y', True),
('yes', True),
('YES', True),
('n', False),
('no', False),
('NO', False),
])
def test_tox_support(cookies, with_tox_support, expected_result):
with bake_in_temp_dir(cookies, extra_context={'use_tox': with_tox_support}) as result:
found_toplevel_files = [f.basename for f in result.project.listdir()]
assert ('tox.ini' in found_toplevel_files) == expected_result


def test_cookie_secret_has_been_generated(cookies):
with bake_in_temp_dir(cookies) as result:
settings_file = result.project.join('settings.py')
settings_lines = settings_file.readlines(cr=False)
assert '!!CHANGEME!!' not in settings_lines
17 changes: 17 additions & 0 deletions tox.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[tox]
envlist = py27, py33, py34, py35, docs
skipsdist = true

[testenv:docs]
basepython=python
changedir=docs
deps=sphinx
commands=
sphinx-build -b html -d {envtmpdir}/doctrees . {envtmpdir}/html

[testenv]
whitelist_externals = bash
deps =
-rrequirements_dev.txt
commands =
py.test
7 changes: 7 additions & 0 deletions {{cookiecutter.project_slug}}/.bumpversion.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[bumpversion]
current_version = {{ cookiecutter.version }}
commit = True
tag = True
tag_name = {new_version}

[bumpversion:file:{{ cookiecutter.project_slug }}/version.py]
13 changes: 13 additions & 0 deletions {{cookiecutter.project_slug}}/AUTHORS.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
=======
Credits
=======

Development Lead
----------------

* {{ cookiecutter.author_name }} <{{ cookiecutter.email }}>

Contributors
------------

None yet. Why not be the first?
Loading

0 comments on commit 12d3f8b

Please sign in to comment.