[PATCH 1 of 3] registrar: add templatekeyword to mark a function as template keyword (API)
Sean Farley
sean at farley.io
Sun Mar 13 18:03:02 EDT 2016
FUJIWARA Katsunori <foozy at lares.dti.ne.jp> writes:
> 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)
Thanks for the explanation! I like this series now :-)
More information about the Mercurial-devel
mailing list