Skip to content

Commit

Permalink
Add tests, fix bugs
Browse files Browse the repository at this point in the history
  • Loading branch information
akheron committed Aug 20, 2010
1 parent 975630e commit a6bc970
Show file tree
Hide file tree
Showing 18 changed files with 872 additions and 22 deletions.
48 changes: 48 additions & 0 deletions run-tests.py
@@ -0,0 +1,48 @@
import sys
from optparse import OptionParser

try:
from coverage import coverage
except ImportError:
coverage = None

parser = OptionParser()
parser.add_option('-v', '--verbose', action='store_true',
help='Be more verbose')
if coverage:
parser.add_option('-c', '--coverage', action='store_true',
help='Measure code coverage')

options, args = parser.parse_args()
if args:
parser.print_help()
sys.exit(2)

if coverage and options.coverage:
cov = coverage()
cov.start()

# Import the Stango code down here to make coverage count the importing, too
import stango.tests
result = stango.tests.run(options.verbose)

if result.wasSuccessful() and options.coverage:
exclude = [
'stango.tests',
'stango.autoreload',
]

def include_module(name):
# exclude test code and stango.autoreload which is not testable
for prefix in ['stango.tests', 'stango.autoreload']:
if name.startswith(prefix):
return False
return name.startswith('stango')

cov.stop()
modules = [
module for name, module in sys.modules.items()
if include_module(name)
]
cov.report(modules, file=sys.stdout)
cov.erase()
16 changes: 12 additions & 4 deletions stango/__init__.py
Expand Up @@ -4,12 +4,15 @@
from stango.context import Context
from stango.files import Files

STANGO_TEMPLATE_DIR = os.path.join(os.path.dirname(__file__), 'templates')

class Manager(object):
HOOK_NAMES = ['post_render_hook']

def __init__(self):
self.index_file = None
self.files = Files()
self.template_dirs = [STANGO_TEMPLATE_DIR]

# By default, all hooks return the data unmodified
default_hook = lambda context, data: data
Expand Down Expand Up @@ -42,15 +45,15 @@ def view(self, filespec, generating=False, serving=False):
elif isinstance(view_result, (bytes, bytearray)):
byte_result = view_result
else:
raise ValueError('The result of view %r for file %s is not a str, bytes or bytearray instance' % (view, filespec.realpath))
raise ValueError('The result of view %r for path %r is not a str, bytes or bytearray instance' % (filespec.view.__name__, filespec.path))

result = self.hooks['post_render_hook'](context, byte_result)
if not isinstance(result, (bytes, bytearray)):
raise ValueError('The result of %s is not a bytes or bytearray instance for %s' % (hook, filespec.realpath))
raise ValueError('The result of post_render_hook is not a bytes or bytearray instance for %s' % filespec.realpath)

return result

def serve(self, host, port):
def serve(self, host, port, run_server=True, verbose=False):
from stango.http import StangoHTTPServer

if port < 0 or port > 65535:
Expand All @@ -59,7 +62,12 @@ def serve(self, host, port):
self.complete_files()

httpd = StangoHTTPServer((host, port), self)
httpd.serve_forever()
httpd.verbose = verbose

if run_server:
httpd.serve_forever()
else:
return httpd

def generate(self, outdir):
self.complete_files()
Expand Down
11 changes: 1 addition & 10 deletions stango/context.py
@@ -1,7 +1,3 @@
import os

STANGO_TEMPLATE_DIR = os.path.join(os.path.dirname(__file__), 'templates')

def dict_merge(*args):
result = {}
for d in args:
Expand All @@ -18,11 +14,6 @@ def __init__(self, manager, filespec):
self.generating = False
self.serving = False

self.template_dirs = [
'templates',
STANGO_TEMPLATE_DIR,
]

def render_template(self, template_name, **kwargs):
builtin_template_args = {
'generating': self.generating,
Expand All @@ -38,7 +29,7 @@ def render_template(self, template_name, **kwargs):
# Create the Jinja environment once and save it to the
# manager instance
from jinja2 import Environment, FileSystemLoader
loader = FileSystemLoader(self.template_dirs)
loader = FileSystemLoader(self.manager.template_dirs)
env = Environment(loader=loader)
self.jinja_env = self.manager._jinja_env = env

Expand Down
2 changes: 1 addition & 1 deletion stango/files.py
Expand Up @@ -26,7 +26,7 @@ def __new__(cls, path, view, kwargs={}, realpath=None):
return super(Filespec, cls).__new__(cls, path, view, kwargs, realpath)

def isdir(self):
return not self.realpath or self.realpath.endswith('/')
return not self.path or self.path.endswith('/')

def complete(self, index_file):
assert index_file is not None
Expand Down
4 changes: 4 additions & 0 deletions stango/http.py
Expand Up @@ -29,6 +29,10 @@ def do_GET(self):
else:
self.start_response(404)

def log_message(self, *args, **kwargs):
if self.server.verbose:
super(StangoRequestHandler, self).log_message(*args, **kwargs)


class StangoHTTPServer(HTTPServer):
def __init__(self, server_address, manager):
Expand Down
13 changes: 6 additions & 7 deletions stango/main.py
Expand Up @@ -6,26 +6,24 @@

def quickstart():
conf_code = '''\
import stango
from stango.files import Files
import views
index_file = 'index.html'
files = stango.files(
files = Files(
('', views.hello, { 'message': 'Hello, World!', 'link': 'greeting.html' }),
('greeting.html', views.hello, { 'message': 'Greetings, World!', 'link': 'index.html' }),
)
'''

views_code = '''\
from stango.shortcuts import render_template
def hello(message, link):
return render_template('hello.html', message=message, link=link)
def hello(context, message, link):
return context.render_template('hello.html', message=message, link=link)
'''

hello_template = '''\
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<!DOCTYPE html>
<html>
<head>
<title>{{ message }}</title>
Expand Down Expand Up @@ -128,6 +126,7 @@ def run():
manager = Manager()
manager.files = config['files']
manager.index_file = config['index_file']
manager.template_dirs.insert(0, 'templates')

if config['post_render_hook']:
manager.add_hook('post_render_hook', config['post_render_hook'])
Expand Down
65 changes: 65 additions & 0 deletions stango/tests/__init__.py
@@ -0,0 +1,65 @@
from datetime import datetime
import os
import shutil
import sys
import unittest

class StangoTestCase(unittest.TestCase):
def setup(self):
pass

def teardown(self):
pass

def eq(self, a, b):
return self.assertEqual(a, b)

def assert_raises(self, exc_class, func, *args, **kwargs):
'''Like assertRaises() but returns the exception'''
try:
func(*args, **kwargs)
except exc_class as exc:
return exc
else:
raise AssertionError('%s was not raised' % exc_class.__name__)

def tempdir(self):
path = os.path.join('tmp', self.id())
if os.path.exists(path):
shutil.rmtree(path)
os.makedirs(path)
return path


# Don't override these in test code

def setUp(self):
dirpath = os.path.dirname(__file__)
self.template_path = os.path.join(dirpath, 'templates')
self.data_path = os.path.relpath(os.path.join(dirpath, 'data'))
self.setup()

def tearDown(self):
self.teardown()


def make_suite(cls):
return unittest.TestLoader().loadTestsFromTestCase(cls)


def suite():
from stango.tests import \
test_files, test_generate, test_main, test_manager, test_serve, \
test_views
suite = unittest.TestSuite()
suite.addTest(test_files.suite())
suite.addTest(test_generate.suite())
suite.addTest(test_main.suite())
suite.addTest(test_manager.suite())
suite.addTest(test_serve.suite())
suite.addTest(test_views.suite())
return suite


def run(verbose=False):
return unittest.TextTestRunner(verbosity=(2 if verbose else 1)).run(suite())
1 change: 1 addition & 0 deletions stango/tests/data/static/file.txt
@@ -0,0 +1 @@
This is a test file
1 change: 1 addition & 0 deletions stango/tests/data/static/other.txt
@@ -0,0 +1 @@
This is also a test file
Binary file added stango/tests/data/test.tar
Binary file not shown.
1 change: 1 addition & 0 deletions stango/tests/templates/value.txt
@@ -0,0 +1 @@
value is: {{ value }}

0 comments on commit a6bc970

Please sign in to comment.