Patchwork [2,of,4] templatefuncs: declare resource requirements for future use

mail settings
Submitter Yuya Nishihara
Date June 18, 2018, 1:37 p.m.
Message ID <21015eb08c98d12fa206.1529329026@mimosa>
Download mbox | patch
Permalink /patch/32279/
State Accepted
Headers show


Yuya Nishihara - June 18, 2018, 1:37 p.m.
# HG changeset patch
# User Yuya Nishihara <>
# Date 1528978738 -32400
#      Thu Jun 14 21:18:58 2018 +0900
# Node ID 21015eb08c98d12fa2060e8d1414e9f557a448d7
# Parent  6d021282f5c6b39c4f3af64e3ed0a658253974d3
templatefuncs: declare resource requirements for future use


diff --git a/mercurial/ b/mercurial/
--- a/mercurial/
+++ b/mercurial/
@@ -351,7 +351,8 @@  class templatefunc(_templateregistrarbas
         templatefunc = registrar.templatefunc()
-        @templatefunc('myfunc(arg1, arg2[, arg3])', argspec='arg1 arg2 arg3')
+        @templatefunc('myfunc(arg1, arg2[, arg3])', argspec='arg1 arg2 arg3',
+                      requires={'ctx'})
         def myfuncfunc(context, mapping, args):
             '''Explanation of this template function ....
@@ -363,6 +364,9 @@  class templatefunc(_templateregistrarbas
     a dict of named arguments. Otherwise 'args' is a list of positional
+    Optional argument 'requires' should be a collection of resource names
+    which the template function depends on.
     'templatefunc' instance in example above can be used to
     decorate multiple functions.
@@ -374,8 +378,9 @@  class templatefunc(_templateregistrarbas
     _getname = _funcregistrarbase._parsefuncdecl
-    def _extrasetup(self, name, func, argspec=None):
+    def _extrasetup(self, name, func, argspec=None, requires=()):
         func._argspec = argspec
+        func._requires = requires
 class internalmerge(_funcregistrarbase):
     """Decorator to register in-process merge tool
diff --git a/mercurial/ b/mercurial/
--- a/mercurial/
+++ b/mercurial/
@@ -85,7 +85,7 @@  def dict_(context, mapping, args):
                 for k, v in args['kwargs'].iteritems())
     return templateutil.hybriddict(data)
-@templatefunc('diff([includepattern [, excludepattern]])')
+@templatefunc('diff([includepattern [, excludepattern]])', requires={'ctx'})
 def diff(context, mapping, args):
     """Show a diff, optionally
     specifying files to include or exclude."""
@@ -105,7 +105,7 @@  def diff(context, mapping, args):
     return ''.join(chunks)
-@templatefunc('extdata(source)', argspec='source')
+@templatefunc('extdata(source)', argspec='source', requires={'ctx', 'cache'})
 def extdata(context, mapping, args):
     """Show a text read from the specified extdata source. (EXPERIMENTAL)"""
     if 'source' not in args:
@@ -128,7 +128,7 @@  def extdata(context, mapping, args):
         data = cache[source] = scmutil.extdatasource(ctx.repo(), source)
     return data.get(ctx.rev(), '')
+@templatefunc('files(pattern)', requires={'ctx'})
 def files(context, mapping, args):
     """All files of the current changeset matching the pattern. See
     :hg:`help patterns`."""
@@ -166,7 +166,7 @@  def fill(context, mapping, args):
     return templatefilters.fill(text, width, initindent, hangindent)
+@templatefunc('formatnode(node)', requires={'ui'})
 def formatnode(context, mapping, args):
     """Obtain the preferred form of a changeset hash. (DEPRECATED)"""
     if len(args) != 1:
@@ -179,7 +179,7 @@  def formatnode(context, mapping, args):
         return node
     return templatefilters.short(node)
+@templatefunc('mailmap(author)', requires={'repo', 'cache'})
 def mailmap(context, mapping, args):
     """Return the author, updated according to the value
     set in the .mailmap file"""
@@ -331,7 +331,7 @@  def join(context, mapping, args):
         joiner = evalstring(context, mapping, args[1])
     return joinset.join(context, mapping, joiner)
-@templatefunc('label(label, expr)')
+@templatefunc('label(label, expr)', requires={'ui'})
 def label(context, mapping, args):
     """Apply a label to generated content. Content with
     a label applied can result in additional post-processing, such as
@@ -504,7 +504,7 @@  def obsfateverb(context, mapping, args):
         errmsg = _("obsfateverb first argument should be countable")
         raise error.ParseError(errmsg)
+@templatefunc('relpath(path)', requires={'repo'})
 def relpath(context, mapping, args):
     """Convert a repository-absolute path into a filesystem path relative to
     the current working directory."""
@@ -516,7 +516,7 @@  def relpath(context, mapping, args):
     path = evalstring(context, mapping, args[0])
     return repo.pathto(path)
-@templatefunc('revset(query[, formatargs...])')
+@templatefunc('revset(query[, formatargs...])', requires={'repo', 'cache'})
 def revset(context, mapping, args):
     """Execute a revision set query. See
     :hg:`help revset`."""
@@ -577,7 +577,7 @@  def separate(context, mapping, args):
             yield sep
         yield argstr
-@templatefunc('shortest(node, minlength=4)')
+@templatefunc('shortest(node, minlength=4)', requires={'repo'})
 def shortest(context, mapping, args):
     """Obtain the shortest representation of
     a node."""