예제 #1
0
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')
예제 #2
0
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')
예제 #3
0
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)
예제 #4
0
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)
예제 #5
0
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')
예제 #6
0
 def setup(self):
     self.tmp = self.tempdir()
     self.manager = Stango()
예제 #7
0
 def setup(self):
     self.tmp = self.tempdir()
     self.manager = Stango()
     self.manager.index_file = 'index.html'
예제 #8
0
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')
예제 #9
0
 def setup(self):
     self.manager = Stango()
예제 #10
0
 def setup(self):
     self.manager = Stango()
     self.manager.index_file = 'index.html'
예제 #11
0
파일: main.py 프로젝트: pombredanne/stango
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()
예제 #12
0
 def setup(self):
     self.tmp = self.tempdir()
     self.manager = Stango()
예제 #13
0
 def setup(self):
     self.manager = Stango()
     self.manager.index_file = 'index.html'