comparison env/lib/python3.9/site-packages/docutils/transforms/__init__.py @ 0:4f3585e2f14b draft default tip

"planemo upload commit 60cee0fc7c0cda8592644e1aad72851dec82c959"
author shellac
date Mon, 22 Mar 2021 18:12:50 +0000
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:4f3585e2f14b
1 # $Id: __init__.py 8358 2019-08-26 16:45:09Z milde $
2 # Authors: David Goodger <goodger@python.org>; Ueli Schlaepfer
3 # Copyright: This module has been placed in the public domain.
4
5 """
6 This package contains modules for standard tree transforms available
7 to Docutils components. Tree transforms serve a variety of purposes:
8
9 - To tie up certain syntax-specific "loose ends" that remain after the
10 initial parsing of the input plaintext. These transforms are used to
11 supplement a limited syntax.
12
13 - To automate the internal linking of the document tree (hyperlink
14 references, footnote references, etc.).
15
16 - To extract useful information from the document tree. These
17 transforms may be used to construct (for example) indexes and tables
18 of contents.
19
20 Each transform is an optional step that a Docutils component may
21 choose to perform on the parsed document.
22 """
23
24 __docformat__ = 'reStructuredText'
25
26
27 from docutils import languages, ApplicationError, TransformSpec
28
29
30 class TransformError(ApplicationError): pass
31
32
33 class Transform(object):
34
35 """
36 Docutils transform component abstract base class.
37 """
38
39 default_priority = None
40 """Numerical priority of this transform, 0 through 999 (override)."""
41
42 def __init__(self, document, startnode=None):
43 """
44 Initial setup for in-place document transforms.
45 """
46
47 self.document = document
48 """The document tree to transform."""
49
50 self.startnode = startnode
51 """Node from which to begin the transform. For many transforms which
52 apply to the document as a whole, `startnode` is not set (i.e. its
53 value is `None`)."""
54
55 self.language = languages.get_language(
56 document.settings.language_code, document.reporter)
57 """Language module local to this document."""
58
59 def apply(self, **kwargs):
60 """Override to apply the transform to the document tree."""
61 raise NotImplementedError('subclass must override this method')
62
63
64 class Transformer(TransformSpec):
65
66 """
67 Stores transforms (`Transform` classes) and applies them to document
68 trees. Also keeps track of components by component type name.
69 """
70
71 def __init__(self, document):
72 self.transforms = []
73 """List of transforms to apply. Each item is a 4-tuple:
74 ``(priority string, transform class, pending node or None, kwargs)``.
75 """
76
77 self.unknown_reference_resolvers = []
78 """List of hook functions which assist in resolving references"""
79
80 self.document = document
81 """The `nodes.document` object this Transformer is attached to."""
82
83 self.applied = []
84 """Transforms already applied, in order."""
85
86 self.sorted = 0
87 """Boolean: is `self.tranforms` sorted?"""
88
89 self.components = {}
90 """Mapping of component type name to component object. Set by
91 `self.populate_from_components()`."""
92
93 self.serialno = 0
94 """Internal serial number to keep track of the add order of
95 transforms."""
96
97 def add_transform(self, transform_class, priority=None, **kwargs):
98 """
99 Store a single transform. Use `priority` to override the default.
100 `kwargs` is a dictionary whose contents are passed as keyword
101 arguments to the `apply` method of the transform. This can be used to
102 pass application-specific data to the transform instance.
103 """
104 if priority is None:
105 priority = transform_class.default_priority
106 priority_string = self.get_priority_string(priority)
107 self.transforms.append(
108 (priority_string, transform_class, None, kwargs))
109 self.sorted = 0
110
111 def add_transforms(self, transform_list):
112 """Store multiple transforms, with default priorities."""
113 for transform_class in transform_list:
114 priority_string = self.get_priority_string(
115 transform_class.default_priority)
116 self.transforms.append(
117 (priority_string, transform_class, None, {}))
118 self.sorted = 0
119
120 def add_pending(self, pending, priority=None):
121 """Store a transform with an associated `pending` node."""
122 transform_class = pending.transform
123 if priority is None:
124 priority = transform_class.default_priority
125 priority_string = self.get_priority_string(priority)
126 self.transforms.append(
127 (priority_string, transform_class, pending, {}))
128 self.sorted = 0
129
130 def get_priority_string(self, priority):
131 """
132 Return a string, `priority` combined with `self.serialno`.
133
134 This ensures FIFO order on transforms with identical priority.
135 """
136 self.serialno += 1
137 return '%03d-%03d' % (priority, self.serialno)
138
139 def populate_from_components(self, components):
140 """
141 Store each component's default transforms, with default priorities.
142 Also, store components by type name in a mapping for later lookup.
143 """
144 for component in components:
145 if component is None:
146 continue
147 self.add_transforms(component.get_transforms())
148 self.components[component.component_type] = component
149 self.sorted = 0
150 # Set up all of the reference resolvers for this transformer. Each
151 # component of this transformer is able to register its own helper
152 # functions to help resolve references.
153 unknown_reference_resolvers = []
154 for i in components:
155 unknown_reference_resolvers.extend(i.unknown_reference_resolvers)
156 decorated_list = sorted((f.priority, f) for f in unknown_reference_resolvers)
157 self.unknown_reference_resolvers.extend(f[1] for f in decorated_list)
158
159 def apply_transforms(self):
160 """Apply all of the stored transforms, in priority order."""
161 self.document.reporter.attach_observer(
162 self.document.note_transform_message)
163 while self.transforms:
164 if not self.sorted:
165 # Unsorted initially, and whenever a transform is added.
166 self.transforms.sort()
167 self.transforms.reverse()
168 self.sorted = 1
169 priority, transform_class, pending, kwargs = self.transforms.pop()
170 transform = transform_class(self.document, startnode=pending)
171 transform.apply(**kwargs)
172 self.applied.append((priority, transform_class, pending, kwargs))