registrar: add filesetpredicate to mark a function as fileset predicate
authorFUJIWARA Katsunori <foozy@lares.dti.ne.jp>
Fri, 11 Mar 2016 04:14:54 +0900
changeset 28447 4eb5496c2bd4
parent 28446 08bd09921102
child 28448 7108834c76a2
registrar: add filesetpredicate to mark a function as fileset predicate filesetpredicate is used to replace fileset.predicate in subsequent patch. This patch also adds loadpredicate() to fileset, because this combination helps to figure out how the name of "status caller" (or "existing caller") predicate is put into _statuscallers (or _existingcallers). Listing up loadpredicate() in dispatch.extraloaders causes implicit loading fileset predicate functions at loading (3rd party) extension.
mercurial/dispatch.py
mercurial/fileset.py
mercurial/registrar.py
tests/test-fileset.t
--- a/mercurial/dispatch.py	Fri Mar 11 04:14:54 2016 +0900
+++ b/mercurial/dispatch.py	Fri Mar 11 04:14:54 2016 +0900
@@ -31,6 +31,7 @@
     error,
     extensions,
     fancyopts,
+    fileset,
     hg,
     hook,
     revset,
@@ -753,6 +754,7 @@
 #   extraobj) arguments
 extraloaders = [
     ('cmdtable', commands, 'loadcmdtable'),
+    ('filesetpredicate', fileset, 'loadpredicate'),
     ('revsetpredicate', revset, 'loadpredicate'),
 ]
 
--- a/mercurial/fileset.py	Fri Mar 11 04:14:54 2016 +0900
+++ b/mercurial/fileset.py	Fri Mar 11 04:14:54 2016 +0900
@@ -560,5 +560,15 @@
 def prettyformat(tree):
     return parser.prettyformat(tree, ('string', 'symbol'))
 
+def loadpredicate(ui, extname, registrarobj):
+    """Load fileset predicates from specified registrarobj
+    """
+    for name, func in registrarobj._table.iteritems():
+        symbols[name] = func
+        if func._callstatus:
+            _statuscallers.add(name)
+        if func._callexisting:
+            _existingcallers.add(name)
+
 # tell hggettext to extract docstrings from these functions:
 i18nfunctions = symbols.values()
--- a/mercurial/registrar.py	Fri Mar 11 04:14:54 2016 +0900
+++ b/mercurial/registrar.py	Fri Mar 11 04:14:54 2016 +0900
@@ -122,3 +122,42 @@
 
     def _extrasetup(self, name, func, safe=False):
         func._safe = safe
+
+class filesetpredicate(_funcregistrarbase):
+    """Decorator to register fileset predicate
+
+    Usage::
+
+        filesetpredicate = registrar.filesetpredicate()
+
+        @filesetpredicate('mypredicate()')
+        def mypredicatefunc(mctx, x):
+            '''Explanation of this fileset predicate ....
+            '''
+            pass
+
+    The first string argument is used also in online help.
+
+    Optional argument 'callstatus' indicates whether a predicate
+     implies 'matchctx.status()' at runtime or not (False, by
+     default).
+
+    Optional argument 'callexisting' indicates whether a predicate
+    implies 'matchctx.existing()' at runtime or not (False, by
+    default).
+
+    'filesetpredicate' instance in example above can be used to
+    decorate multiple functions.
+
+    Decorated functions are registered automatically at loading
+    extension, if an instance named as 'filesetpredicate' is used for
+    decorating in extension.
+
+    Otherwise, explicit 'fileset.loadpredicate()' is needed.
+    """
+    _getname = _funcregistrarbase._parsefuncdecl
+    _docformat = "``%s``\n    %s"
+
+    def _extrasetup(self, name, func, callstatus=False, callexisting=False):
+        func._callstatus = callstatus
+        func._callexisting = callexisting
--- a/tests/test-fileset.t	Fri Mar 11 04:14:54 2016 +0900
+++ b/tests/test-fileset.t	Fri Mar 11 04:14:54 2016 +0900
@@ -351,9 +351,10 @@
 Test detection of unintentional 'matchctx.existing()' invocation
 
   $ cat > $TESTTMP/existingcaller.py <<EOF
-  > from mercurial import fileset
+  > from mercurial import registrar
   > 
-  > @fileset.predicate('existingcaller()', callexisting=False)
+  > filesetpredicate = registrar.filesetpredicate()
+  > @filesetpredicate('existingcaller()', callexisting=False)
   > def existingcaller(mctx, x):
   >     # this 'mctx.existing()' invocation is unintentional
   >     return [f for f in mctx.existing()]