diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py
--- a/mercurial/cmdutil.py
+++ b/mercurial/cmdutil.py
@@ -1428,24 +1428,8 @@ class changeset_templater(changeset_prin
 
     def _show(self, ctx, copies, matchfn, props):
         '''show a single changeset or file revision'''
-
-        showlist = templatekw.showlist
-
-        # showparents() behavior depends on ui trace level which
-        # causes unexpected behaviors at templating level and makes
-        # it harder to extract it in a standalone function. Its
-        # behavior cannot be changed so leave it here for now.
-        def showparents(**args):
-            ctx = args['ctx']
-            parents = [[('rev', p.rev()),
-                        ('node', p.hex()),
-                        ('phase', p.phasestr())]
-                       for p in scmutil.meaningfulparents(self.repo, ctx)]
-            return showlist('parent', parents, **args)
-
         props = props.copy()
         props.update(templatekw.keywords)
-        props['parents'] = showparents
         props['templ'] = self.t
         props['ctx'] = ctx
         props['repo'] = self.repo
diff --git a/mercurial/templatekw.py b/mercurial/templatekw.py
--- a/mercurial/templatekw.py
+++ b/mercurial/templatekw.py
@@ -397,11 +397,17 @@ def showp2node(repo, ctx, templ, **args)
     parent, all digits are 0."""
     return ctx.p2().hex()
 
-def _showparents(**args):
+def showparents(**args):
     """:parents: List of strings. The parents of the changeset in "rev:node"
     format. If the changeset has only one "natural" parent (the predecessor
     revision) nothing is shown."""
-    pass
+    repo = args['repo']
+    ctx = args['ctx']
+    parents = [[('rev', p.rev()),
+                ('node', p.hex()),
+                ('phase', p.phasestr())]
+               for p in scmutil.meaningfulparents(repo, ctx)]
+    return showlist('parent', parents, **args)
 
 def showphase(repo, ctx, templ, **args):
     """:phase: String. The changeset phase name."""
@@ -491,6 +497,7 @@ keywords = {
     'p1node': showp1node,
     'p2rev': showp2rev,
     'p2node': showp2node,
+    'parents': showparents,
     'phase': showphase,
     'phaseidx': showphaseidx,
     'rev': showrev,
@@ -499,7 +506,6 @@ keywords = {
 }
 
 dockeywords = {
-    'parents': _showparents,
 }
 dockeywords.update(keywords)
 del dockeywords['branches']