-def find_template(wikitext, template_title):
- """Returns the tuple (start, end) of the first occurence of the template '{{template ...}} within wikitext'.
- (None, None) is returned if the template is not found.
- If you are sure that the wikitext contains the template, the template could be extracted like follows:
-
- >>> wikitext = u'This is a {{Color|red|red text}} template.'
- >>> start, end = find_template(wikitext, u'Color')
- >>> print wikitext[start:end]
- {{Color|red|red text}}
-
- or just:
-
- >>> print wikitext.__getslice__(*find_template(wikitext, u'Color'))
- {{Color|red|red text}}
-
- The search is done with regular expression. It gives wrong results when parsing a template
- containing the characters "}}"
-
- :param wikitext: The text (preferalbe unicode) that has the template in it.
- :param template_title: The page title of the template with or without namespace (but as in the wikitext).
- :return:
- (start, end) of the first occurence with start >= 0 and end > start.
- (None, None) if the template is not found.
- """
- match = re.search(u"\{\{" + template_title + "\s*(\|[^\}]*)?\}\}", wikitext, re.DOTALL)
- if match is None: return None, None
- return match.start(), match.end()
-
-
-class TemplateValidator(formencode.FancyValidator):
- def __init__(self, strip=True, as_table=False, as_table_keylen=None):
- """Validates a MediaWiki template, e.g. {{Color|red}}
- :param stip: If strip is True, the title, and the parameter keys and values are stripped in to_python.
- :param as_table: formats the returned template in one row for each parameter
- :param as_table_keylen: length of the key field for from_python. None for "automatic"."""
- self.strip = (lambda s: s.strip()) if strip else (lambda s: s)
- self.as_table = as_table
- self.as_table_keylen = as_table_keylen
-
- def to_python(self, value, state=None):
- """Takes a template, like u'{{Color|red|text=Any text}}' and translates it to a Python tuple
- (title, anonym_params, named_params) where title is the template title,
- anonym_params is a list of anonymous parameters and named_params is a OrderedDict
- of named parameters. Whitespace of the parameters is stripped."""
- if not value.startswith(u'{{'):
- raise formencode.Invalid(u'Template does not start with "{{"', value, state)
- if not value.endswith(u'}}'):
- raise formencode.Invalid(u'Template does not end with "}}"', value, state)
- parts = value[2:-2].split(u'|')
-
- # template name
- title = self.strip(parts[0])
- if len(title) == 0:
- raise formencode.Invalid(u'Empty template tilte.', value, state)
- del parts[0]
-
- # anonymous parameters
- anonym_params = []
- while len(parts) > 0:
- equalsign_pos = parts[0].find(u'=')
- if equalsign_pos >= 0: break # named parameter
- anonym_params.append(self.strip(parts[0]))
- del parts[0]
-
- # named or numbered parameters
- named_params = collections.OrderedDict()
- while len(parts) > 0:
- equalsign_pos = parts[0].find(u'=')
- if equalsign_pos < 0:
- raise formencode.Invalid(u'Anonymous parameter after named parameter.', value, state)
- key, sep, value = parts[0].partition(u'=')
- key = self.strip(key)
- if len(key) == 0:
- raise formencode.Invalid(u'Empty key.', value, state)
- if named_params.has_key(key):
- raise formencode.Invalid(u'Duplicate key: "{0}"'.format(key), value, state)
- named_params[key] = self.strip(value)
- del parts[0]
-
- return title, anonym_params, named_params
-
- def from_python(self, value, state=None):
- """Formats a MediaWiki template.
- value is a tuple: (title, anonym_params, named_params)
- where title is the template title, anonym_params is a list of anonymous parameters and
- named_params is a dict or OrderedDict of named parameters."""
- title, anonym_params, named_params = value
- pipe_char, equal_char, end_char = (u'\n| ', u' = ', u'\n}}') if self.as_table else (u'|', u'=', u'}}')
- parts = [u"{{" + title]
- parts += anonym_params
- as_table_keylen = self.as_table_keylen
- if self.as_table and as_table_keylen is None:
- as_table_keylen = max(map(len, named_params.iterkeys()))
- for k, v in named_params.iteritems():
- if self.as_table:
- k = k.ljust(as_table_keylen)
- parts.append((k + equal_char + v).rstrip())
- else:
- parts.append(k + equal_char + v)
- return pipe_char.join(parts) + end_char
-
-
-def split_template(template):
- """Deprecated legacy function.
-
- Takes a template, like u'{{Color|red|text=Any text}}' and translates it to a Python tuple
- (template_title, parameters) where parameters is a Python dictionary {u'1': u'red', u'text'=u'Any text'}.
- Anonymous parameters get integer keys (converted to unicode) starting with 1
- like in MediaWiki, named parameters are unicode strings.
- Whitespace is stripped.
- If an unexpected format is encountered, a ValueError is raised."""
- try:
- title, anonym_params, named_params = TemplateValidator().to_python(template)
- parameters = dict(named_params)
- for i in xrange(len(anonym_params)):
- parameters[unicode(i+1)] = anonym_params[i]
- except formencode.Invalid as e:
- raise ValueError(e[0])
- return title, parameters
-
-
-def create_template(template_title, anonym_params=[], named_param_keys=[], named_param_values=[], as_table=False, as_table_keylen=None):
- """Deprecated legacy function.
-
- Formats a MediaWiki template.
- :param template_title: Unicode string with the template name
- :param anonym_params: list with parameters without keys
- :param named_param_keys: list with keys of named parameters
- :param named_param_values: list with values of named parameters, corresponding to named_param_keys.
- :param as_table: formats the returned template in one row for each parameter
- :param as_table_keylen: length of the key field. None for "automatic".
- :return: unicode template"""
- named_params = collections.OrderedDict(zip(named_param_keys, named_param_values))
- return TemplateValidator(as_table=as_table, as_table_keylen=as_table_keylen).from_python((template_title, anonym_params, named_params))