Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge pull request #2789 from getnikola/template_hooks_dependencies
Save dependencies for template hooks properly
  • Loading branch information
Kwpolska committed May 22, 2017
2 parents e4c5336 + 581e340 commit 8157387
Show file tree
Hide file tree
Showing 6 changed files with 32 additions and 8 deletions.
2 changes: 2 additions & 0 deletions CHANGES.txt
Expand Up @@ -16,6 +16,8 @@ Features
Bugfixes
--------

* Save dependencies for template hooks properly (using .__doc__ or
.template_registry_identifier for callables)
* Enable larger panorama thumbnails (Issue #2780)
* Disable ``archive_rss`` link handler, which was useless because no
such RSS was ever generated (Issue #2783)
Expand Down
16 changes: 12 additions & 4 deletions docs/extending.txt
Expand Up @@ -537,21 +537,22 @@ HTML:

# In set_site
def generate_html_bit(name, ftype='js'):
"""Generate HTML for an asset."""
return '<script src="/assets/{t}/{n}.{t}">'.format(n=name, t=ftype)

site.template_hooks['extra_head'].append(generate_html_bit, False, 'fancyplugin', type='js')
site.template_hooks['extra_head'].append(generate_html_bit, False, 'fancyplugin', ftype='js')


The second argument to ``append()`` is used to determine whether the function
needs access to the current template context and the site. If it is set to
``True``, the function will also receive ``site`` and ``context`` keyword
arguments. Example use:


.. code-block:: python

# In set_site
def greeting(addr, endswith='', site=None, context=None):
"""Greet someone."""
if context['lang'] == 'en':
greet = u'Hello'
elif context['lang'] == 'es':
Expand All @@ -564,6 +565,13 @@ arguments. Example use:

site.template_hooks['page_header'].append(greeting, True, u'Nikola Tesla', endswith=u'!')

Dependencies for template hooks:

* if the input is a string, the string value, alongside arguments to ``append``, is used for calculating dependencies
* if the input is a callable, it attempts ``input.template_registry_identifier``, then ``input.__doc__``, and if neither is available, it uses a static string.

Make sure to provide at least a docstring, or a identifier, to ensure rebuilds work properly.

Shortcodes
==========

Expand All @@ -579,7 +587,7 @@ So, if you are creating a plugin that generates markup, it may be a good idea
to register it as a shortcode in addition of to restructured text directive or
markdown extension, thus making it available to all markup formats.

To implement your own shortcodes from a plugin, you can create a plugin inheriting ``ShortcodePlugin`` and
To implement your own shortcodes from a plugin, you can create a plugin inheriting ``ShortcodePlugin`` and
from its ``set_site`` method, call

``Nikola.register_shortcode(name, func)`` with the following arguments:
Expand Down Expand Up @@ -610,7 +618,7 @@ variable keyword arguments):
between them, otherwise ``None``.

``lang``:
The current language.
The current language.

If the shortcode tag has arguments of the form ``foo=bar`` they will be
passed as named arguments. Everything else will be passed as positional
Expand Down
2 changes: 1 addition & 1 deletion nikola/nikola.py
Expand Up @@ -2243,7 +2243,7 @@ def generic_renderer(self, lang, output_name, template_name, filters, file_deps=
deps_dict.update(post_deps_dict)

for k, v in self.GLOBAL_CONTEXT['template_hooks'].items():
deps_dict['||template_hooks|{0}||'.format(k)] = v._items
deps_dict['||template_hooks|{0}||'.format(k)] = v.calculate_deps()

for k in self._GLOBAL_CONTEXT_TRANSLATABLE:
deps_dict[k] = deps_dict['global'][k](lang)
Expand Down
2 changes: 1 addition & 1 deletion nikola/plugins/task/galleries.py
Expand Up @@ -173,7 +173,7 @@ def gen_tasks(self):
self.image_ext_list.extend(self.site.config.get('EXTRA_IMAGE_EXTENSIONS', []))

for k, v in self.site.GLOBAL_CONTEXT['template_hooks'].items():
self.kw['||template_hooks|{0}||'.format(k)] = v._items
self.kw['||template_hooks|{0}||'.format(k)] = v.calculate_deps()

self.site.scan_posts()
yield self.group_task()
Expand Down
2 changes: 1 addition & 1 deletion nikola/plugins/task/listings.py
Expand Up @@ -187,7 +187,7 @@ def render_listing(in_name, out_name, input_folder, output_folder, folders=[], f
uptodate = {'c': self.site.GLOBAL_CONTEXT}

for k, v in self.site.GLOBAL_CONTEXT['template_hooks'].items():
uptodate['||template_hooks|{0}||'.format(k)] = v._items
uptodate['||template_hooks|{0}||'.format(k)] = v.calculate_deps()

for k in self.site._GLOBAL_CONTEXT_TRANSLATABLE:
uptodate[k] = self.site.GLOBAL_CONTEXT[k](self.kw['default_lang'])
Expand Down
16 changes: 15 additions & 1 deletion nikola/utils.py
Expand Up @@ -512,9 +512,23 @@ def append(self, inp, wants_site_and_context=False, *args, **kwargs):
c = callable(inp)
self._items.append((c, inp, wants_site_and_context, args, kwargs))

def calculate_deps(self):
"""Calculate dependencies for a registry."""
deps = []
for is_callable, inp, wants_site_and_context, args, kwargs in self._items:
if not is_callable:
name = inp
elif hasattr(inp, 'template_registry_identifier'):
name = inp.template_registry_identifier
elif hasattr(inp, '__doc__'):
name = inp.__doc__
else:
name = '_undefined_callable_'
deps.append((is_callable, name, wants_site_and_context, args, kwargs))

def __hash__(self):
"""Return hash of a registry."""
return hash(config_changed({self.name: self._items})._calc_digest())
return hash(config_changed({self.name: self.calculate_deps()})._calc_digest())

def __str__(self):
"""Stringify a registry."""
Expand Down

0 comments on commit 8157387

Please sign in to comment.