示例#1
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')
示例#2
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')
示例#3
0
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()