# HG changeset patch # User Paul Boddie # Date 1532628638 -7200 # Node ID 437e2de72754bb46f6935e55eb9935e12c1ca9a3 # Parent 2361cce71e0ef2ff1cbc5f648714b2d87419831c# Parent 68fb30a6392d275042f43d50f9abc234d37ec12e Merged changes from the default branch. diff -r 2361cce71e0e -r 437e2de72754 convert.py --- a/convert.py Thu Jul 26 16:34:42 2018 +0200 +++ b/convert.py Thu Jul 26 20:10:38 2018 +0200 @@ -1,6 +1,6 @@ #!/usr/bin/env python -from moinformat import get_serialiser, make_parser, parse, serialise +from moinformat import make_linker, make_parser, make_serialiser, parse, serialise from os.path import split import sys @@ -65,8 +65,9 @@ if tree: print d.prettyprint() else: - p.translate_links(format, pagename) - print serialise(d, get_serialiser(format)) + l = make_linker(format, pagename) + s = make_serialiser(format, l) + print serialise(d, s) finally: f.close() diff -r 2361cce71e0e -r 437e2de72754 moinformat/__init__.py --- a/moinformat/__init__.py Thu Jul 26 16:34:42 2018 +0200 +++ b/moinformat/__init__.py Thu Jul 26 20:10:38 2018 +0200 @@ -19,6 +19,7 @@ this program. If not, see . """ +from moinformat.links import make_linker from moinformat.parsers import parse, parsers as all_parsers from moinformat.serialisers import serialise, serialisers as all_serialisers @@ -40,4 +41,16 @@ return all_serialisers["%s.moin" % name] +def make_serialiser(name, linker=None): + + """ + Return a serialiser instance for the format having the given 'name'. + + The optional 'linker' is used to control which linking scheme is used with + the serialiser, with the default having the same name as the serialiser. + """ + + linker = linker or make_linker(name, "") + return get_serialiser(name)(formats=all_serialisers, linker=linker) + # vim: tabstop=4 expandtab shiftwidth=4 diff -r 2361cce71e0e -r 437e2de72754 moinformat/links/__init__.py --- a/moinformat/links/__init__.py Thu Jul 26 16:34:42 2018 +0200 +++ b/moinformat/links/__init__.py Thu Jul 26 20:10:38 2018 +0200 @@ -26,10 +26,23 @@ def get_linker(name): """ - Return the linking scheme handler with the given 'name' or None if no such - handler is found. + Return the linking scheme handler class with the given 'name' or None if no + such handler is found. """ return linkers.get(name) +def make_linker(name, pagename): + + """ + Return a linking scheme handler with the given 'name' and using the given + 'pagename'. + """ + + linker_cls = get_linker(name) + if not linker_cls: + return None + + return linker_cls(pagename) + # vim: tabstop=4 expandtab shiftwidth=4 diff -r 2361cce71e0e -r 437e2de72754 moinformat/links/html.py --- a/moinformat/links/html.py Thu Jul 26 16:34:42 2018 +0200 +++ b/moinformat/links/html.py Thu Jul 26 20:10:38 2018 +0200 @@ -35,12 +35,12 @@ levels = self.pagename.count("/") return "/".join([".."] * levels) - def is_url(self, link): + def is_url(self, target): - "Return whether the 'link' references a URL." + "Return whether the 'target' references a URL." - scheme, host, path, params, query, fragment = urlparse(link.target) - return scheme + scheme, host, path, params, query, fragment = urlparse(target) + return scheme and target or None def normalise(self, path): @@ -48,92 +48,91 @@ return not path.endswith("/") and "%s/" % path or path - def translate(self, link): + def translate(self, target): - "Translate the 'link', rewriting the target." + "Translate the 'target' and return the rewritten string." - target = link.target.rstrip("/") + target = target.rstrip("/") # Sub-pages. if target.startswith("/"): - self.translate_subpage(link, target) + return self.translate_subpage(target) # Sibling (of ancestor) pages. - elif target.startswith("../"): - self.translate_relative(link, target) + if target.startswith("../"): + return self.translate_relative(target) # Attachment or interwiki link. - elif self.translate_qualified_link(link, target): - pass + rewritten = self.translate_qualified_link(target) + if rewritten: + return rewritten # Plain URL. - elif self.is_url(link): - pass + rewritten = self.is_url(target) + if rewritten: + return rewritten # Top-level pages. - else: - top_level = self.get_top_level() - link.target = "%s%s" % (top_level and "%s/" % top_level or "", target) + top_level = self.get_top_level() + return "%s%s" % (top_level and "%s/" % top_level or "", target) - def translate_qualified_link(self, link, target): + def translate_qualified_link(self, target): """ - Translate a possible qualified 'link', returning whether translation - occurred. + Translate a possible qualified link 'target', returning a rewritten + target or None if the link is not suitable. """ t = target.split(":", 1) if len(t) != 2: - return False + return None prefix, target = t # Attachment links. if prefix == "attachment": - self.translate_attachment(link, target) - return True + return self.translate_attachment(target) # Interwiki links. url = self.mapping.get(prefix) if url: - self.translate_interwiki(link, url, target) - return True + return self.translate_interwiki(url, target) - return False + return None # Specific link translators. - def translate_attachment(self, link, target): + def translate_attachment(self, target): - "Update 'link' for the given attachment 'target'." + "Return a translation of the given attachment 'target'." - link.target = "%sattachments/%s/%s" % ( + return "%sattachments/%s/%s" % ( self.get_top_level(), self.pagename, target) - def translate_interwiki(self, link, url, target): + def translate_interwiki(self, url, target): - "Update 'link' for the given interwiki 'target'." + "Return a translation of the given interwiki 'target'." - link.target = "%s%s" % (self.normalise(url), target) + return "%s%s" % (self.normalise(url), target) - def translate_relative(self, link, target): + def translate_relative(self, target): - "Update 'link' for the given relative 'target'." + "Return a translation of the given relative 'target'." - link.target = target[len("../"):] + return target[len("../"):] - def translate_subpage(self, link, target): + def translate_subpage(self, target): - "Update 'link' for the given subpage 'target'." + "Return a translation of the given subpage 'target'." - link.target = ".%s" % target + return ".%s" % target linker = HTMLLinker diff -r 2361cce71e0e -r 437e2de72754 moinformat/parsers/moin.py --- a/moinformat/parsers/moin.py Thu Jul 26 16:34:42 2018 +0200 +++ b/moinformat/parsers/moin.py Thu Jul 26 20:10:38 2018 +0200 @@ -21,7 +21,6 @@ # Document transformations. -from moinformat.links import get_linker from moinformat.macros import get_macro # Parser functionality and pattern definition. @@ -68,7 +67,6 @@ # Record certain node occurrences for later evaluation. self.macros = [] - self.links = [] # Principal parser methods. @@ -119,30 +117,6 @@ macro = macro_cls(node, self.region) macro.evaluate() - # Link translation. - - def translate_links(self, scheme, name, base=""): - - """ - Translate the link nodes in the document for the given 'scheme' and - employing the given document 'name' and 'base'. - """ - - # Obtain a class for the named linker. - - linker_cls = get_linker(scheme) - if not linker_cls: - return - - # Instantiate the class with document metadata. - - linker = linker_cls(name, base) - - for node in self.links: - - # Translate the link. - - linker.translate(node) # Parser methods supporting different page features. @@ -517,10 +491,6 @@ link = Link(text and [Text(text)], target) region.append_inline(link) - # Record the link for later processing. - - self.root.links.append(link) - def parse_macro(self, region): name = self.match_group("name") args = self.match_group("args") diff -r 2361cce71e0e -r 437e2de72754 moinformat/serialisers/__init__.py --- a/moinformat/serialisers/__init__.py Thu Jul 26 16:34:42 2018 +0200 +++ b/moinformat/serialisers/__init__.py Thu Jul 26 20:10:38 2018 +0200 @@ -24,12 +24,17 @@ # Top-level functions. -def serialise(doc, serialiser=MoinSerialiser): +def serialise(doc, serialiser=None): - "Serialise 'doc' using 'serialiser' or the Moin serialiser if omitted." + """ + Serialise 'doc' using the given 'serialiser' instance or the Moin serialiser + if omitted. + """ l = [] - doc.to_string(serialiser(l.append, serialisers)) + serialiser = serialiser or MoinSerialiser(formats=serialisers) + serialiser.out = l.append + doc.to_string(serialiser) return "".join(l) # vim: tabstop=4 expandtab shiftwidth=4 diff -r 2361cce71e0e -r 437e2de72754 moinformat/serialisers/common.py --- a/moinformat/serialisers/common.py Thu Jul 26 16:34:42 2018 +0200 +++ b/moinformat/serialisers/common.py Thu Jul 26 20:10:38 2018 +0200 @@ -25,15 +25,17 @@ format = None # defined by subclasses - def __init__(self, out, formats=None): + def __init__(self, out=None, formats=None, linker=None): """ - Initialise the serialiser with an 'out' callable and an optional - 'formats' mapping from names to serialiser classes. + Initialise the serialiser with an 'out' callable, an optional 'formats' + mapping from names to serialiser classes, and an optional 'linker' + object for translating links. """ self.out = out self.formats = formats + self.linker = linker self.init() def init(self): @@ -43,7 +45,8 @@ pass def __repr__(self): - return "%s(%r, %r)" % (self.__class__.__name__, self.out, self.formats) + return "%s(%r, %r, %r)" % (self.__class__.__name__, self.out, + self.formats, self.linker) def escape_attr(s): diff -r 2361cce71e0e -r 437e2de72754 moinformat/serialisers/html/moin.py --- a/moinformat/serialisers/html/moin.py Thu Jul 26 16:34:42 2018 +0200 +++ b/moinformat/serialisers/html/moin.py Thu Jul 26 20:10:38 2018 +0200 @@ -97,6 +97,8 @@ self.out("") def start_link(self, target): + if self.linker: + target = self.linker.translate(target) self.out('' % escape_attr(target)) def end_link(self): diff -r 2361cce71e0e -r 437e2de72754 moinformat/tree/moin.py --- a/moinformat/tree/moin.py Thu Jul 26 16:34:42 2018 +0200 +++ b/moinformat/tree/moin.py Thu Jul 26 20:10:38 2018 +0200 @@ -146,8 +146,9 @@ # Retain the same serialiser if no appropriate serialiser could be # obtained. - region_out = serialiser_cls and serialiser_cls(out.out, out.formats) \ - or out + region_out = serialiser_cls and serialiser_cls is not out and \ + serialiser_cls(out.out, out.formats, out.linker) or \ + out # Serialise the region. diff -r 2361cce71e0e -r 437e2de72754 tests/test_parser.py --- a/tests/test_parser.py Thu Jul 26 16:34:42 2018 +0200 +++ b/tests/test_parser.py Thu Jul 26 20:10:38 2018 +0200 @@ -12,7 +12,7 @@ if split(parent)[1] == "MoinLight": sys.path.append(parent) -from moinformat import get_serialiser, parse, serialise +from moinformat import make_serialiser, parse, serialise from moinformat.tree.moin import Container from glob import glob @@ -36,7 +36,7 @@ print "-" * 60 print s print "-" * 60 - print serialise(d, get_serialiser("html")) + print serialise(d, make_serialiser("html")) print "-" * 60 print