Skip to content

Commit

Permalink
updated behavior for pyramid
Browse files Browse the repository at this point in the history
  • Loading branch information
knowsuchagency committed Jul 2, 2017
1 parent 6e74d9b commit 295e3dc
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 37 deletions.
3 changes: 3 additions & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ While this will make each page load much faster after the first visit,
**IT ALSO MEANS YOU CANNOT HAVE ANY MUTABLE STATE IN YOUR TEMPLATE**
as the template itself will only be rendered once.

Rendered templates will be saved alongside the original template with ``.html`` replacing ``.pug``
as the suffix. This ensures relative paths in templates won't break.

It may be best to prototype by using ninjadog as normal - mutable state, conditionals, mixins... whatever -
but to set the aformentioned option to true and move any logic dealing with mutable state into
javascript for production. The choice yours.
Expand Down
2 changes: 2 additions & 0 deletions ninjadog/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,7 @@
EXTENSION_PATT = re.compile('(?:extends|include)\s+(.+)')
PUG_CLI_PATH = str(Path(sp.Popen(('which', 'pug'), stdout=sp.PIPE).communicate()[0].decode('utf8').strip()).absolute()) \
if sp.Popen(('which', 'npm'), stdout=sp.DEVNULL).wait() == 0 else None

# will likely be deprecated in the future as it's no longer being used
TEMPDIR = Path(gettempdir(), '.ninjadog/')

15 changes: 15 additions & 0 deletions ninjadog/decorators.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from functools import wraps
from time import time


def idempotent(func):
"""Ensure the function runs only once."""
cache = {}
now = hash(time())

@wraps(func)
def wrapped(*args):
if cache.get(args, now) == now:
cache[args] = func(*args)
return cache[args]
return wrapped
67 changes: 30 additions & 37 deletions ninjadog/ext/pyramid.py
Original file line number Diff line number Diff line change
@@ -1,29 +1,27 @@
import typing as T
from pathlib import Path
from shutil import rmtree as rmdir

from pyramid.path import AssetResolver

from ninjadog.ninjadog import render
from ninjadog.constants import TEMPDIR
from ninjadog.decorators import idempotent


def get_and_update(dictionary: dict, key: T.Any, value: T.Any) -> T.Any:
def changed(dictionary: dict, key: T.Any, value: T.Any) -> bool:
"""
Get the previous value for the key and update with the new value.
Return true if the value for the given key in the dictionary has changed.
Args:
dictionary: dict
key: any
value: any
Returns: the previous value for that key or the value if the key didn't exist
Returns:
"""
previous = dictionary.setdefault(key, value)
dictionary.update({key: value})

return previous
previous = dictionary.get(key)
dictionary[key] = value
return previous != value


def truth(value: T.Union[bool, str]) -> bool:
Expand Down Expand Up @@ -61,60 +59,55 @@ def resolve(path: str, caller=None) -> Path:
return Path(Path(caller.__file__).parent, path).absolute()


def run_once():
@idempotent
def remove_file_if_exists(file: Path) -> True:
"""
Creates the temporary directory at runtime idempotently.
"""
has_run = False
Removes the file from the file system if it exists.
def logic():
nonlocal has_run
if not has_run:
rmdir(TEMPDIR, ignore_errors=True)
TEMPDIR.mkdir(exist_ok=True)
has_run = True
Args:
file: filepath
return logic
Returns: True
"""
if file.exists():
file.unlink()

reset_tempdir = run_once()
return True


class PugRendererFactory:
def __init__(self, info):
self.reload = info.settings['reload_all'] or info.settings['reload_templates']
self.static_only = truth(info.settings.get('ninjadog.cache', False))
self.cached = truth(info.settings.get('ninjadog.cache', False))

self.template_path = resolve(info.name,
info.package)
self.template_name = self.template_path.name
self.template_path = resolve(info.name, info.package)
self.template_cache = {}

if self.static_only:
reset_tempdir()

def __call__(self, value, system):
if not isinstance(value, dict): raise ValueError('view must return dict')

context = system
context.update(value)

if self.static_only:
if self.cached:
html_file = self.template_path.with_suffix('.html')
remove_file_if_exists(html_file)
template_changed = False

if self.reload:
template_text = self.template_path.read_text()
template_changed = get_and_update(self.template_cache, self.template_name,
template_text) != template_text

template_file = Path(TEMPDIR, self.template_name)
template_changed = changed(self.template_cache, self.template_path, template_text)
if not template_changed:
print(f"template {self.template_path} didn't change")

if (not template_file.exists()) or (self.reload and template_changed):
if (not html_file.exists()) or (self.reload and template_changed):
html = render(file=self.template_path, context=context, with_jinja=True)
template_file.write_text(html)
html_file.write_text(html)

return html

return template_file.read_text()
return html_file.read_text()

return render(file=self.template_path, context=context, with_jinja=True)

Expand Down

0 comments on commit 295e3dc

Please sign in to comment.