[PATCH 1 of 3] registrar: add templatekeyword to mark a function as template keyword (API)

FUJIWARA Katsunori foozy at lares.dti.ne.jp
Sun Mar 13 09:57:56 EDT 2016


At Sat, 12 Mar 2016 12:48:36 -0800,
Sean Farley wrote:
> 
> 
> FUJIWARA Katsunori <foozy at lares.dti.ne.jp> writes:
> 
> > # HG changeset patch
> > # User FUJIWARA Katsunori <foozy at lares.dti.ne.jp>
> > # Date 1457813826 -32400
> > #      Sun Mar 13 05:17:06 2016 +0900
> > # Node ID dec6fedbede5d40088f18057f49ae5c4ebd634ef
> > # Parent  70c2f8a982766b512e9d7f41f2d93fdb92f5481f
> > registrar: add templatekeyword to mark a function as template keyword (API)
> >
> > _templateregistrarbase is defined as a super class of templatekeyword,
> > for ease of adding template common features between "keyword",
> > "filter" and "function".
> >
> > This patch also adds loadkeyword() to templatekw, because this
> > combination helps to figure out how they cooperate with each other.
> >
> > Listing up loadkeyword() in dispatch.extraloaders causes implicit
> > loading template keyword functions at loading (3rd party) extension.
> >
> > This change requires that "templatekeyword" attribute of (3rd party)
> > extension is registrar.templatekeyword or so.
> 
> A few things are a little unclear to me:
> 
> - these patches are needed so that template keywords in 3rd party
>   extensions aren't implicitly loaded? How is that bad?

Main purpose of this (, previous and subsequent) series is increasing
maintainability of function registration in Mercurial source. For
example, usage of annotation can:

  - localize "function definition" and "putting it into table"

  - hide internal implementation of optional attributes
    (e.g. "safe" of revset, "callstatus" and "callexisting" of fileset)

Loading template keyword function from 3rd party extension implicitly
is a side effect.


> - how will extensions support both 3.7 and 3.8 with your changes?

It might be like as below:

    # code for portability >>>>
    try:
        from mercurial import registrar
        if not util.safehasattr(registrar, 'templatekeyword'):
            raise ImportError()

        templatekeyword = registrar.templatekeyword()
        loadkeyword = lambda registrarobj: None # nop
    except ImportError:
        # registrar.templatekeyword isn't available = loading by old hg

        # minimum copy from registrar._funcregistrarbase
        class _funcregistrarbase(object):
            ....

        templatekeyword = _funcregistrarbase()
        templatekeyword._docformat = ":%s: %s"

        # minimum copy from templatekw.loadkeyword
        def loadkeyword(registrarobj):
            from mercurial import templatekw
            for name, func in registrarobj._table.iteritems():
                templatekw.keywords[name] = func
    # <<<< code for portability


    # use templatekeyword to mark function as template keyword
    @templatekeywrd('xxxx')
    def xxxx(...):
        """Explanation of keyword xxxx
        """

        :
        :


    def extsetup(ui):
        # load keyword function, if registrar.templatekeyword not available
        loadkeyword(templatekeyword)


I'm planning to write detail of this into WritingExtensions wiki page,
and to provide an utility module as a part of "a skeleton extension"
proposed as issue4677 by Matt.

    https://bz.mercurial-scm.org/show_bug.cgi?id=4677


> - how can an extension dynamically create a template keyword with your
>   changes?

It can dynamically create template keyword by code path like as below:

    dynpredicate = registrar.templatekeyword()

    # mark function as template keyword by dynpredicate
    dynpredicate("name_of_keyword")(keyword_func)
        :
        :

    # register marked functions as template keyword
    templatekw.loadkeyword(ui, 'name_of_extension', dynpredicate)


----------------------------------------------------------------------
[FUJIWARA Katsunori]                             foozy at lares.dti.ne.jp


More information about the Mercurial-devel mailing list