This repository has been archived by the owner on May 31, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #48 from c-bata/develop
Refactor templates
- Loading branch information
Showing
7 changed files
with
17 additions
and
116 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
{% extends "base" %} | ||
{% extends "base.html" %} | ||
|
||
{% block title %}Hello!{% endblock %} | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
from .app import Kobin, Config, current_app, current_config | ||
from .environs import request, response | ||
from .templates import template, jinja2_template | ||
from .templates import render_template | ||
from .exceptions import HTTPError | ||
from .routes import redirect |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,84 +1,8 @@ | ||
from typing import List, Dict, Any, Callable | ||
import os | ||
import functools | ||
from jinja2 import Environment, FileSystemLoader # type: ignore | ||
|
||
from .exceptions import HTTPError | ||
|
||
|
||
def load_file(name: str, directories: List[str]) -> str: | ||
for directory in directories: | ||
if not os.path.isabs(directory): | ||
directory = os.path.abspath(directory) + os.sep | ||
file = os.path.join(directory, name) | ||
if os.path.exists(file) and os.path.isfile(file) and os.access(file, os.R_OK): | ||
return file | ||
# TODO: if not os.access: raise HTTPError(403, "You do not have permission to access this file.") | ||
raise HTTPError(404, "{name} not found.".format(name=name)) | ||
|
||
|
||
class TemplateMixin: | ||
extension = 'html' # type: str | ||
settings = {} # type: Dict[str, Any] # used in parepare() | ||
defaults = {} # type: Dict[str, Any] # used in render() | ||
|
||
def __init__(self, name: str, encoding: str='utf8', **settings) -> None: | ||
""" Create a new template. """ | ||
from . import current_config # type: ignore | ||
self.name = name | ||
config = current_config() # type: ignore | ||
self.template_dirs = config['TEMPLATE_DIRS'] # type: List[str] | ||
self.filename = self.search(self.name, self.template_dirs) # type: str | ||
|
||
self.encoding = encoding | ||
self.settings = self.settings.copy() | ||
self.prepare(**self.settings) | ||
|
||
@classmethod | ||
def search(cls, name: str, template_dirs: List[str]) -> str: | ||
""" Search name in all directories specified in lookup. """ | ||
filename = '{name}.{ext}'.format(name=name, ext=cls.extension) | ||
return load_file(filename, template_dirs) | ||
|
||
def prepare(self, **options): | ||
raise NotImplementedError | ||
|
||
def render(self, *args, **kwargs): | ||
raise NotImplementedError | ||
|
||
|
||
class Jinja2Template(TemplateMixin): | ||
def prepare(self, filters: Dict=None, tests: Dict=None, globals: Dict={}, **kwargs) -> None: | ||
from jinja2 import Environment, FunctionLoader # type: ignore | ||
self.env = Environment(loader=FunctionLoader(self.loader), **kwargs) | ||
if filters: | ||
self.env.filters.update(filters) | ||
if tests: | ||
self.env.tests.update(tests) | ||
if globals: | ||
self.env.globals.update(globals) | ||
self.tpl = self.env.get_template(self.filename) | ||
|
||
def render(self, *args, **kwargs) -> str: | ||
for dictarg in args: | ||
kwargs.update(dictarg) | ||
_defaults = self.defaults.copy() | ||
_defaults.update(kwargs) | ||
return self.tpl.render(**_defaults) | ||
|
||
def loader(self, name: str) -> str: | ||
if name == self.filename: | ||
fname = name | ||
else: | ||
fname = self.search(name, self.template_dirs) | ||
if not fname: | ||
return # type: ignore | ||
with open(fname, "rb") as f: | ||
return f.read().decode(self.encoding) | ||
|
||
|
||
def template(template_name: str, **kwargs) -> str: | ||
def render_template(template_name: str, **kwargs) -> str: | ||
""" Get a rendered template as string iterator. """ | ||
adapter = kwargs.pop('template_adapter', Jinja2Template) | ||
return adapter(name=template_name).render(**kwargs) | ||
|
||
jinja2_template = functools.partial(template, adapter=Jinja2Template) | ||
from . import current_config # type: ignore | ||
env = Environment(loader=FileSystemLoader(current_config()['TEMPLATE_DIRS'])) # type: ignore | ||
return env.get_template(template_name).render(**kwargs) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,39 +1,16 @@ | ||
import os | ||
from unittest import TestCase | ||
from unittest.mock import patch | ||
from kobin.exceptions import HTTPError | ||
from kobin.templates import Jinja2Template, load_file | ||
from kobin.templates import render_template | ||
|
||
TEMPLATE_DIRS = [os.path.join(os.path.dirname(os.path.abspath(__file__)), 'templates')] | ||
|
||
|
||
class LoadFileTests(TestCase): | ||
def test_load_file(self): | ||
actual = load_file('jinja2.html', TEMPLATE_DIRS) | ||
expected = os.path.join(TEMPLATE_DIRS[0], 'jinja2.html') | ||
self.assertEqual(actual, expected) | ||
|
||
@patch('os.access') | ||
def test_raise_403_do_not_have_access_permission(self, mock_os_access): | ||
mock_os_access.return_value = False | ||
self.assertRaises(HTTPError, load_file, | ||
name='jinja2.html', directories=TEMPLATE_DIRS) | ||
|
||
def test_raise_404_because_file_does_not_exist(self): | ||
self.assertRaises(HTTPError, load_file, | ||
name='does_not_exist.html', directories=TEMPLATE_DIRS) | ||
|
||
def test_raise_404_because_it_is_not_file(self): | ||
self.assertRaises(HTTPError, load_file, | ||
name='this_is_not_file.html', directories=TEMPLATE_DIRS) | ||
TEMPLATE_DIRS = [os.path.join(os.path.dirname(__file__), 'templates')] | ||
|
||
|
||
class Jinja2TemplateTests(TestCase): | ||
@patch('kobin.current_config') | ||
def test_file(self, mock_current_config): | ||
""" Templates: Jinja2 file """ | ||
mock_current_config.return_value = {'TEMPLATE_DIRS': TEMPLATE_DIRS} | ||
j2 = Jinja2Template(name='jinja2', template_dirs=TEMPLATE_DIRS) | ||
actual = j2.render(var='kobin') | ||
actual = render_template('jinja2.html', var='kobin') | ||
expected = "Hello kobin World." | ||
self.assertEqual(actual, expected) |