Skip to content

Commit

Permalink
Merge pull request #53 from mdrachuk/jinja-cache
Browse files Browse the repository at this point in the history
Jinja Cache
  • Loading branch information
mdrachuk committed Jan 22, 2020
2 parents 1c5adf3 + fcce731 commit 6037f69
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 10 deletions.
2 changes: 1 addition & 1 deletion lightweight/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,4 @@ def blog_posts(source):
logger = logging.getLogger('lightweight')
logger.setLevel(logging.INFO)

__version__ = '1.0.0.dev42'
__version__ = '1.0.0.dev43'
3 changes: 2 additions & 1 deletion lightweight/site.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from datetime import datetime
from itertools import chain
from os import getcwd
from os.path import abspath
from pathlib import Path
from shutil import rmtree
from typing import overload, Union, Optional, Collection, List, Set, Dict
Expand Down Expand Up @@ -202,7 +203,7 @@ def generate(self, out: Union[str, Path] = 'out'):
If the out directory already exists – it will be deleted with all of it contents.
"""
out = Path(out)
out = Path(abspath(out))
if out.exists():
rmtree(out)
out.mkdir(parents=True, exist_ok=True)
Expand Down
84 changes: 83 additions & 1 deletion lightweight/template.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
from collections import defaultdict
from os import PathLike, getcwd
from pathlib import Path
from typing import Union, cast
from typing import Union, cast, Dict

from jinja2 import Environment, FileSystemLoader, Template, StrictUndefined
from jinja2.utils import LRUCache


class DynamicCwd(PathLike):
Expand All @@ -27,6 +29,86 @@ def __fspath__(self):
)


class LruCachePerCwd:
"""A proxy for Jinja native LRU cache, supplying cache specific to current working directory."""
by_cwd: Dict[str, LRUCache]

def __init__(self, capacity: int):
self.by_cwd = defaultdict(lambda: LRUCache(capacity))

def instance(self):
return self.by_cwd[getcwd()]

def __getstate__(self, *args, **kwargs):
return self.instance().__getstate__(*args, **kwargs)

def __setstate__(self, *args, **kwargs):
return self.instance().__setstate__(*args, **kwargs)

def __getnewargs__(self, *args, **kwargs):
return self.instance().__getnewargs__(*args, **kwargs)

def copy(self, *args, **kwargs):
return self.instance().copy(*args, **kwargs)

def get(self, *args, **kwargs):
return self.instance().get(*args, **kwargs)

def setdefault(self, *args, **kwargs):
return self.instance().setdefault(*args, **kwargs)

def clear(self, *args, **kwargs):
return self.instance().clear(*args, **kwargs)

def __contains__(self, *args, **kwargs):
return self.instance().__contains__(*args, **kwargs)

def __len__(self, *args, **kwargs):
return self.instance().__len__(*args, **kwargs)

def __repr__(self, *args, **kwargs):
return self.instance().__repr__(*args, **kwargs)

def __getitem__(self, *args, **kwargs):
return self.instance().__getitem__(*args, **kwargs)

def __setitem__(self, *args, **kwargs):
return self.instance().__setitem__(*args, **kwargs)

def __delitem__(self, *args, **kwargs):
return self.instance().__delitem__(*args, **kwargs)

def items(self, *args, **kwargs):
return self.instance().items(*args, **kwargs)

def iteritems(self, *args, **kwargs):
return self.instance().iteritems(*args, **kwargs)

def values(self, *args, **kwargs):
return self.instance().values(*args, **kwargs)

def itervalue(self, *args, **kwargs):
return self.instance().itervalue(*args, **kwargs)

def keys(self, *args, **kwargs):
return self.instance().keys(*args, **kwargs)

def iterkeys(self, *args, **kwargs):
return self.instance().iterkeys(*args, **kwargs)

def __reversed__(self, *args, **kwargs):
return self.instance().__reversed__(*args, **kwargs)

def __iter__(self, *args, **kwargs):
return self.instance().__iter__(*args, **kwargs)

def __copy__(self, *args, **kwargs):
return self.instance().__copy__(*args, **kwargs)


jinja_env.cache = LruCachePerCwd(250)


def template(location: Union[str, Path]) -> Template:
"""A shorthand for loading a Jinja2 template from the current working directory."""
return jinja_env.get_template(str(location))
12 changes: 10 additions & 2 deletions tests/test_include_jinja.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import asyncio
from os import chdir, getcwd
from pathlib import Path

import pytest
from jinja2 import TemplateNotFound
from jinja2 import TemplateNotFound, UndefinedError

from lightweight import Site, jinja, Content, directory, GenContext, GenPath, from_ctx
from lightweight import Site, jinja, Content, directory, GenContext, GenPath, from_ctx, jinja_env


def test_render_jinja(tmp_path: Path):
Expand Down Expand Up @@ -85,3 +86,10 @@ def test_lazy_params(tmp_path: Path):
assert (test_out / out_location).exists()
with open('expected/jinja/lazy.html') as expected:
assert (test_out / out_location).read_text() == expected.read()


def test_jinja_env_does_not_allow_undefined():
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
with pytest.raises(UndefinedError):
jinja_env.from_string('{{something}}').render()
5 changes: 0 additions & 5 deletions tests/test_other.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,3 @@ def test_gen_path_location(tmp_path: Path):
assert style.location == 'style.css'
assert page.location == 'page'
assert index.location == ''


def test_jinja_env_does_not_allow_undefined():
with pytest.raises(UndefinedError):
jinja_env.from_string('{{something}}').render()

0 comments on commit 6037f69

Please sign in to comment.