class ViewsTestCase(StangoTestCase): def setup(self): self.tmp = self.tempdir() self.manager = Stango() def test_static_file(self): # stango.files.files_from_dir uses the stango.views.static_file view strip = self.data_path.count('/') + 2 path = os.path.join(self.data_path, 'static') self.manager.files += files_from_dir('foo', path, strip=strip) self.manager.generate(self.tmp) self.eq(filelist(self.tmp), [ 'foo/file.txt', 'foo/other.txt', ]) with open(os.path.join(self.tmp, 'foo/file.txt')) as fobj: self.eq(fobj.read(), 'This is a test file\n') with open(os.path.join(self.tmp, 'foo/other.txt')) as fobj: self.eq(fobj.read(), 'This is also a test file\n') def test_file_from_tar(self): # stango.files.files_from_dir uses the stango.views.file_from_tar view tar = os.path.join(self.data_path, 'test.tar') self.manager.files += files_from_tar('foo', tar) self.manager.generate(self.tmp) self.eq(filelist(self.tmp), [ 'foo/static/file.txt', 'foo/static/other.txt', ]) with open(os.path.join(self.tmp, 'foo/static/file.txt')) as fobj: self.eq(fobj.read(), 'This is a test file\n') with open(os.path.join(self.tmp, 'foo/static/other.txt')) as fobj: self.eq(fobj.read(), 'This is also a test file\n')
class StangoTestCase(StangoTestCase): def setup(self): self.manager = Stango() def test_manager_defaults(self): self.eq(self.manager.files, Files()) self.eq(self.manager.index_file, None) def test_add_hook(self): def hook(context, data): pass self.manager.add_hook('post_render_hook', hook) self.eq(self.manager.hooks, {'post_render_hook': hook}) def test_add_hook_invalid_name(self): def hook(context, data): pass exc = self.assert_raises(ValueError, self.manager.add_hook, 'nonexistent_hook', hook) self.eq(str(exc), 'nonexistent_hook is not a valid hook name') def test_add_noncallable_hook(self): exc = self.assert_raises(TypeError, self.manager.add_hook, 'post_render_hook', 5) self.eq(str(exc), 'hook_func must be callable')
class ServerTestCase(StangoTestCase): def setup(self): self.manager = Stango() self.manager.index_file = 'index.html' def serve(func): @functools.wraps(func) def wrapper(self): gen = func(self) httpd = next(gen) httpd.allow_reuse_address = True server_thread = Thread(target=httpd.serve_forever) server_thread.start() try: self.assert_raises(StopIteration, gen.send, None) finally: httpd.shutdown() server_thread.join() httpd.socket.close() return wrapper @serve def test_simple(self): self.manager.files = Files( ('', view_value('foobar')), ) yield self.manager.make_server('127.0.0.1', 8080) data = urlopen('http://127.0.0.1:8080/') self.eq(data.read(), b'foobar') self.eq(data.info()['Content-Type'], 'text/html') @serve def test_real_path(self): self.manager.files = Files( ('', view_value('bazbuzz')), ) yield self.manager.make_server('127.0.0.1', 8080) data = urlopen('http://127.0.0.1:8080/index.html') self.eq(data.read(), b'bazbuzz') self.eq(data.info()['Content-Type'], 'text/html') @serve def test_404(self): self.manager.files = Files( ('', view_value('foobar')), ) yield self.manager.make_server('127.0.0.1', 8080) url = 'http://127.0.0.1:8080/nonexistent' exc = self.assert_raises(HTTPError, urlopen, url) self.eq(exc.code, 404)
class ServerTestCase(StangoTestCase): def setup(self): self.manager = Stango() self.manager.index_file = 'index.html' def serve(func): @functools.wraps(func) def wrapper(self): gen = func(self) httpd = next(gen) httpd.allow_reuse_address = True server_thread = Thread(target=httpd.serve_forever) server_thread.start() try: self.assert_raises(StopIteration, gen.send, None) finally: httpd.shutdown() server_thread.join() httpd.socket.close() return wrapper @serve def test_simple(self): self.manager.files = Files(('', view_value('foobar')), ) yield self.manager.make_server('127.0.0.1', 8080) data = urlopen('http://127.0.0.1:8080/') self.eq(data.read(), b'foobar') self.eq(data.info()['Content-Type'], 'text/html') @serve def test_real_path(self): self.manager.files = Files(('', view_value('bazbuzz')), ) yield self.manager.make_server('127.0.0.1', 8080) data = urlopen('http://127.0.0.1:8080/index.html') self.eq(data.read(), b'bazbuzz') self.eq(data.info()['Content-Type'], 'text/html') @serve def test_404(self): self.manager.files = Files(('', view_value('foobar')), ) yield self.manager.make_server('127.0.0.1', 8080) url = 'http://127.0.0.1:8080/nonexistent' exc = self.assert_raises(HTTPError, urlopen, url) self.eq(exc.code, 404)
class ViewsTestCase(StangoTestCase): def setup(self): self.tmp = self.tempdir() self.manager = Stango() def test_static_file(self): # stango.files.files_from_dir uses the stango.views.static_file view strip = self.data_path.count('/') + 2 path = os.path.join(self.data_path, 'static') self.manager.files += files_from_dir('foo', path, strip=strip) self.manager.generate(self.tmp) self.eq( filelist(self.tmp), [ 'foo/file.txt', 'foo/other.txt', ] ) with open(os.path.join(self.tmp, 'foo/file.txt')) as fobj: self.eq(fobj.read(), 'This is a test file\n') with open(os.path.join(self.tmp, 'foo/other.txt')) as fobj: self.eq(fobj.read(), 'This is also a test file\n') def test_file_from_tar(self): # stango.files.files_from_dir uses the stango.views.file_from_tar view tar = os.path.join(self.data_path, 'test.tar') self.manager.files += files_from_tar('foo', tar) self.manager.generate(self.tmp) self.eq( filelist(self.tmp), [ 'foo/static/file.txt', 'foo/static/other.txt', ] ) with open(os.path.join(self.tmp, 'foo/static/file.txt')) as fobj: self.eq(fobj.read(), 'This is a test file\n') with open(os.path.join(self.tmp, 'foo/static/other.txt')) as fobj: self.eq(fobj.read(), 'This is also a test file\n')
def setup(self): self.tmp = self.tempdir() self.manager = Stango()
def setup(self): self.tmp = self.tempdir() self.manager = Stango() self.manager.index_file = 'index.html'
class GenerateTestCase(StangoTestCase): def setup(self): self.tmp = self.tempdir() self.manager = Stango() self.manager.index_file = 'index.html' def test_generate_simple(self): self.manager.files += [ ('', view_value('foobar')), ('barfile.txt', view_value('barfoo')), ] self.manager.generate(self.tmp) self.eq(sorted(os.listdir(self.tmp)), ['barfile.txt', 'index.html']) with open(os.path.join(self.tmp, 'index.html')) as fobj: self.eq(fobj.read(), 'foobar') with open(os.path.join(self.tmp, 'barfile.txt')) as fobj: self.eq(fobj.read(), 'barfoo') def test_generate_dest_is_non_dir(self): self.manager.files = Files( ('', dummy_view), ) dest_path = os.path.join(self.tmp, 'dest.txt') with open(dest_path, 'w') as fobj: fobj.write('foo') exc = self.assert_raises(ValueError, self.manager.generate, dest_path) self.eq(str(exc), "'%s' is not a directory" % dest_path) # Check the file wasn't modified self.eq(os.listdir(self.tmp), ['dest.txt']) with open(os.path.join(self.tmp, 'dest.txt'), 'r') as fobj: self.eq(fobj.read(), 'foo') def test_generate_outdir_exists(self): # Create a file and a directory to outdir with open(os.path.join(self.tmp, 'foo'), 'w') as fobj: fobj.write('bar') os.mkdir(os.path.join(self.tmp, 'dummydir')) self.eq(sorted(os.listdir(self.tmp)), ['dummydir', 'foo']) self.manager.files = Files( ('', view_value('baz')), ) self.manager.generate(self.tmp) # Check that the old destdir contents were removed self.eq(os.listdir(self.tmp), ['index.html']) def test_generate_different_index_file(self): self.manager.index_file = 'foofile.txt' self.manager.files += [ ('', view_value('foobar')), ('barfile.txt', view_value('barfoo')), ] self.manager.generate(self.tmp) self.eq(sorted(os.listdir(self.tmp)), ['barfile.txt', 'foofile.txt']) with open(os.path.join(self.tmp, 'foofile.txt')) as fobj: self.eq(fobj.read(), 'foobar') with open(os.path.join(self.tmp, 'barfile.txt')) as fobj: self.eq(fobj.read(), 'barfoo') def test_view_returns_a_bytes_object(self): self.manager.files = Files( ('', view_value(b'\xde\xad\xbe\xef')), ) self.manager.generate(self.tmp) self.eq(os.listdir(self.tmp), ['index.html']) with open(os.path.join(self.tmp, 'index.html'), 'rb') as fobj: self.eq(fobj.read(), b'\xde\xad\xbe\xef') def test_view_returns_a_bytearray_object(self): self.manager.files = Files( ('', view_value(bytearray(b'\xba\xdc\x0f\xfe'))), ) self.manager.generate(self.tmp) self.eq(os.listdir(self.tmp), ['index.html']) with open(os.path.join(self.tmp, 'index.html'), 'rb') as fobj: self.eq(fobj.read(), b'\xba\xdc\x0f\xfe') def test_view_returns_a_filelike_object_with_str_contents(self): self.manager.files = Files( ('', view_value(io.StringIO('foobar'))), ) self.manager.generate(self.tmp) self.eq(os.listdir(self.tmp), ['index.html']) with open(os.path.join(self.tmp, 'index.html'), 'r') as fobj: self.eq(fobj.read(), 'foobar') def test_view_returns_a_filelike_object_with_bytes_contents(self): self.manager.files = Files( ('', view_value(io.BytesIO(b'barfoo'))), ) self.manager.generate(self.tmp) self.eq(os.listdir(self.tmp), ['index.html']) with open(os.path.join(self.tmp, 'index.html'), 'r') as fobj: self.eq(fobj.read(), 'barfoo') def test_view_renders_a_template(self): self.manager.template_dirs.insert(0, self.template_path) self.manager.files = Files( ('', view_template('value.txt'), {'value': 'foobar'}) ) self.manager.generate(self.tmp) self.eq(os.listdir(self.tmp), ['index.html']) with open(os.path.join(self.tmp, 'index.html')) as fobj: self.eq(fobj.read(), 'value is: foobar') def test_no_index_file(self): self.manager.index_file = None self.manager.files = Files( ('quux/', dummy_view), ) exc = self.assert_raises(ValueError, self.manager.generate, self.tmp) self.eq(str(exc), "Directory path and no index_file: 'quux/'") def test_view_returns_None(self): self.manager.files = Files( ('', view_value(None)), ) exc = self.assert_raises(ValueError, self.manager.generate, self.tmp) self.eq(str(exc), "The result of view 'value_returner' for path '' is not a str, bytes or bytearray instance or a file-like object") def test_view_returns_an_integer(self): self.manager.files = Files( ('foo.txt', view_value(1)), ) exc = self.assert_raises(ValueError, self.manager.generate, self.tmp) self.eq(str(exc), "The result of view 'value_returner' for path 'foo.txt' is not a str, bytes or bytearray instance or a file-like object") def test_view_returns_a_filelike_object_with_invalid_contents(self): class InvalidFile(object): def read(self): return 42 self.manager.files = Files( ('', view_value(InvalidFile())), ) exc = self.assert_raises(ValueError, self.manager.generate, self.tmp) self.eq(str(exc), "Contents of the file-like object, returned by view 'value_returner' for path '', is not a str, bytes or bytearray instance") def test_post_render_hook(self): def post_render_hook(context, data): return data + b' hurr durr' self.manager.add_hook('post_render_hook', post_render_hook) self.manager.files = Files( ('', view_value('foobar')), ) self.manager.generate(self.tmp) self.eq(os.listdir(self.tmp), ['index.html']) with open(os.path.join(self.tmp, 'index.html'), 'rb') as fobj: self.eq(fobj.read(), b'foobar hurr durr') def test_post_render_hook_returns_None(self): self.manager.add_hook('post_render_hook', lambda x, y: None) self.manager.files = Files( ('', view_value('foobar')), ) exc = self.assert_raises(ValueError, self.manager.generate, self.tmp) self.eq(str(exc), 'The result of post_render_hook is not a bytes or bytearray instance for index.html')
def setup(self): self.manager = Stango()
def setup(self): self.manager = Stango() self.manager.index_file = 'index.html'
def run(): if (len(sys.argv) < 2 or sys.argv[1] not in ['runserver', 'generate', 'quickstart']): print_help() if sys.argv[1] == 'quickstart': if len(sys.argv) != 2: print_help() sys.exit(quickstart()) if not os.path.exists('conf.py'): print('conf.py not found', file=sys.stderr) sys.exit(1) try: backup = sys.path sys.path = [''] + sys.path config = {} exec(open('conf.py').read(), config) finally: sys.path = backup for k, v in list(CONFIG_DEFAULTS.items()): config.setdefault(k, v) if 'files' not in config: print("conf.py doesn't define the 'files' variable", file=sys.stderr) sys.exit(1) manager = Stango() 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']) if sys.argv[1] == 'runserver': host = '127.0.0.1' port = 8000 if len(sys.argv) == 3: if ':' in sys.argv[2]: host, port = sys.argv[2].split(':') else: port = sys.argv[2] try: port = int(port) except ValueError: print_help() elif len(sys.argv) > 3: print_help() def do_serve(): print('Starting server at http://%s:%d/' % (host, port)) httpd = manager.make_server(host, port, verbose=True) httpd.serve_forever() import stango.autoreload stango.autoreload.main(do_serve, config['autoreload']) elif sys.argv[1] == 'generate': if len(sys.argv) == 2: outdir = 'out' elif len(sys.argv) == 3: outdir = sys.argv[2] else: print_help() print('Generating to %s...' % outdir) sys.exit(manager.generate(outdir) or 0) else: print_usage()