Mercurial > repos > shellac > sam_consensus_v3
comparison env/lib/python3.9/site-packages/docutils/parsers/rst/directives/images.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: images.py 8370 2019-08-27 12:10:39Z milde $ | |
2 # Author: David Goodger <goodger@python.org> | |
3 # Copyright: This module has been placed in the public domain. | |
4 | |
5 """ | |
6 Directives for figures and simple images. | |
7 """ | |
8 | |
9 __docformat__ = 'reStructuredText' | |
10 | |
11 | |
12 import sys | |
13 | |
14 from docutils import nodes, utils | |
15 from docutils.parsers.rst import Directive | |
16 from docutils.parsers.rst import directives, states | |
17 from docutils.nodes import fully_normalize_name, whitespace_normalize_name | |
18 from docutils.parsers.rst.roles import set_classes | |
19 | |
20 try: # check for the Python Imaging Library | |
21 import PIL.Image | |
22 except ImportError: | |
23 try: # sometimes PIL modules are put in PYTHONPATH's root | |
24 import Image | |
25 class PIL(object): pass # dummy wrapper | |
26 PIL.Image = Image | |
27 except ImportError: | |
28 PIL = None | |
29 | |
30 if sys.version_info >= (3, 0): | |
31 from urllib.request import url2pathname | |
32 else: | |
33 from urllib import url2pathname | |
34 | |
35 | |
36 class Image(Directive): | |
37 | |
38 align_h_values = ('left', 'center', 'right') | |
39 align_v_values = ('top', 'middle', 'bottom') | |
40 align_values = align_v_values + align_h_values | |
41 | |
42 def align(argument): | |
43 # This is not callable as self.align. We cannot make it a | |
44 # staticmethod because we're saving an unbound method in | |
45 # option_spec below. | |
46 return directives.choice(argument, Image.align_values) | |
47 | |
48 required_arguments = 1 | |
49 optional_arguments = 0 | |
50 final_argument_whitespace = True | |
51 option_spec = {'alt': directives.unchanged, | |
52 'height': directives.length_or_unitless, | |
53 'width': directives.length_or_percentage_or_unitless, | |
54 'scale': directives.percentage, | |
55 'align': align, | |
56 'name': directives.unchanged, | |
57 'target': directives.unchanged_required, | |
58 'class': directives.class_option} | |
59 | |
60 def run(self): | |
61 if 'align' in self.options: | |
62 if isinstance(self.state, states.SubstitutionDef): | |
63 # Check for align_v_values. | |
64 if self.options['align'] not in self.align_v_values: | |
65 raise self.error( | |
66 'Error in "%s" directive: "%s" is not a valid value ' | |
67 'for the "align" option within a substitution ' | |
68 'definition. Valid values for "align" are: "%s".' | |
69 % (self.name, self.options['align'], | |
70 '", "'.join(self.align_v_values))) | |
71 elif self.options['align'] not in self.align_h_values: | |
72 raise self.error( | |
73 'Error in "%s" directive: "%s" is not a valid value for ' | |
74 'the "align" option. Valid values for "align" are: "%s".' | |
75 % (self.name, self.options['align'], | |
76 '", "'.join(self.align_h_values))) | |
77 messages = [] | |
78 reference = directives.uri(self.arguments[0]) | |
79 self.options['uri'] = reference | |
80 reference_node = None | |
81 if 'target' in self.options: | |
82 block = states.escape2null( | |
83 self.options['target']).splitlines() | |
84 block = [line for line in block] | |
85 target_type, data = self.state.parse_target( | |
86 block, self.block_text, self.lineno) | |
87 if target_type == 'refuri': | |
88 reference_node = nodes.reference(refuri=data) | |
89 elif target_type == 'refname': | |
90 reference_node = nodes.reference( | |
91 refname=fully_normalize_name(data), | |
92 name=whitespace_normalize_name(data)) | |
93 reference_node.indirect_reference_name = data | |
94 self.state.document.note_refname(reference_node) | |
95 else: # malformed target | |
96 messages.append(data) # data is a system message | |
97 del self.options['target'] | |
98 set_classes(self.options) | |
99 image_node = nodes.image(self.block_text, **self.options) | |
100 self.add_name(image_node) | |
101 if reference_node: | |
102 reference_node += image_node | |
103 return messages + [reference_node] | |
104 else: | |
105 return messages + [image_node] | |
106 | |
107 | |
108 class Figure(Image): | |
109 | |
110 def align(argument): | |
111 return directives.choice(argument, Figure.align_h_values) | |
112 | |
113 def figwidth_value(argument): | |
114 if argument.lower() == 'image': | |
115 return 'image' | |
116 else: | |
117 return directives.length_or_percentage_or_unitless(argument, 'px') | |
118 | |
119 option_spec = Image.option_spec.copy() | |
120 option_spec['figwidth'] = figwidth_value | |
121 option_spec['figclass'] = directives.class_option | |
122 option_spec['align'] = align | |
123 has_content = True | |
124 | |
125 def run(self): | |
126 figwidth = self.options.pop('figwidth', None) | |
127 figclasses = self.options.pop('figclass', None) | |
128 align = self.options.pop('align', None) | |
129 (image_node,) = Image.run(self) | |
130 if isinstance(image_node, nodes.system_message): | |
131 return [image_node] | |
132 figure_node = nodes.figure('', image_node) | |
133 if figwidth == 'image': | |
134 if PIL and self.state.document.settings.file_insertion_enabled: | |
135 imagepath = url2pathname(image_node['uri']) | |
136 try: | |
137 img = PIL.Image.open( | |
138 imagepath.encode(sys.getfilesystemencoding())) | |
139 except (IOError, UnicodeEncodeError): | |
140 pass # TODO: warn? | |
141 else: | |
142 self.state.document.settings.record_dependencies.add( | |
143 imagepath.replace('\\', '/')) | |
144 figure_node['width'] = '%dpx' % img.size[0] | |
145 del img | |
146 elif figwidth is not None: | |
147 figure_node['width'] = figwidth | |
148 if figclasses: | |
149 figure_node['classes'] += figclasses | |
150 if align: | |
151 figure_node['align'] = align | |
152 if self.content: | |
153 node = nodes.Element() # anonymous container for parsing | |
154 self.state.nested_parse(self.content, self.content_offset, node) | |
155 first_node = node[0] | |
156 if isinstance(first_node, nodes.paragraph): | |
157 caption = nodes.caption(first_node.rawsource, '', | |
158 *first_node.children) | |
159 caption.source = first_node.source | |
160 caption.line = first_node.line | |
161 figure_node += caption | |
162 elif not (isinstance(first_node, nodes.comment) | |
163 and len(first_node) == 0): | |
164 error = self.state_machine.reporter.error( | |
165 'Figure caption must be a paragraph or empty comment.', | |
166 nodes.literal_block(self.block_text, self.block_text), | |
167 line=self.lineno) | |
168 return [figure_node, error] | |
169 if len(node) > 1: | |
170 figure_node += nodes.legend('', *node[1:]) | |
171 return [figure_node] |