1
- # -*- coding: utf-8 -*-
2
- from __future__ import absolute_import
3
1
from itertools import groupby
4
- from typing import List , Optional , Tuple
2
+ from html import escape
3
+ from typing import Optional
5
4
6
5
import numpy as np
7
6
from jinja2 import Environment , PackageLoader
32
31
))
33
32
34
33
35
- def format_as_html (explanation , # type : Explanation
36
- include_styles = True , # type: bool
37
- force_weights = True , # type: bool
34
+ def format_as_html (explanation : Explanation ,
35
+ include_styles = True ,
36
+ force_weights = True ,
38
37
show = fields .ALL ,
39
- preserve_density = None , # type: Optional[bool]
40
- highlight_spaces = None , # type: Optional[bool]
41
- horizontal_layout = True , # type: bool
42
- show_feature_values = False # type: bool
43
- ):
44
- # type: (...) -> str
38
+ preserve_density : Optional [bool ] = None ,
39
+ highlight_spaces : Optional [bool ] = None ,
40
+ horizontal_layout = True ,
41
+ show_feature_values = False ,
42
+ ) -> str :
45
43
""" Format explanation as html.
46
44
Most styles are inline, but some are included separately in <style> tag,
47
45
you can omit them by passing ``include_styles=False`` and call
@@ -130,42 +128,37 @@ def format_as_html(explanation, # type: Explanation
130
128
''' .replace ('\n ' , ' ' )
131
129
132
130
133
- def format_html_styles ():
134
- # type: () -> str
131
+ def format_html_styles () -> str :
135
132
""" Format just the styles,
136
133
use with ``format_as_html(explanation, include_styles=False)``.
137
134
"""
138
135
return template_env .get_template ('styles.html' ).render ()
139
136
140
137
141
138
def render_targets_weighted_spans (
142
- targets , # type: List[TargetExplanation]
143
- preserve_density , # type: Optional[bool]
144
- ):
145
- # type: (...) -> List[Optional[str]]
139
+ targets : list [TargetExplanation ],
140
+ preserve_density : Optional [bool ],
141
+ ) -> list [Optional [str ]]:
146
142
""" Return a list of rendered weighted spans for targets.
147
143
Function must accept a list in order to select consistent weight
148
144
ranges across all targets.
149
145
"""
150
146
prepared_weighted_spans = prepare_weighted_spans (
151
147
targets , preserve_density )
152
148
153
- def _fmt_pws (pws ):
154
- # type: (PreparedWeightedSpans) -> str
149
+ def _fmt_pws (pws : PreparedWeightedSpans ) -> str :
155
150
name = ('<b>{}:</b> ' .format (pws .doc_weighted_spans .vec_name )
156
151
if pws .doc_weighted_spans .vec_name else '' )
157
152
return '{}{}' .format (name , render_weighted_spans (pws ))
158
153
159
- def _fmt_pws_list (pws_lst ):
160
- # type: (List[PreparedWeightedSpans]) -> str
154
+ def _fmt_pws_list (pws_lst : list [PreparedWeightedSpans ]) -> str :
161
155
return '<br/>' .join (_fmt_pws (pws ) for pws in pws_lst )
162
156
163
157
return [_fmt_pws_list (pws_lst ) if pws_lst else None
164
158
for pws_lst in prepared_weighted_spans ]
165
159
166
160
167
- def render_weighted_spans (pws ):
168
- # type: (PreparedWeightedSpans) -> str
161
+ def render_weighted_spans (pws : PreparedWeightedSpans ) -> str :
169
162
# TODO - for longer documents, an option to remove text
170
163
# without active features
171
164
return '' .join (
@@ -177,11 +170,10 @@ def render_weighted_spans(pws):
177
170
key = lambda x : x [1 ]))
178
171
179
172
180
- def _colorize (token , # type: str
181
- weight , # type: float
182
- weight_range , # type: float
183
- ):
184
- # type: (...) -> str
173
+ def _colorize (token : str ,
174
+ weight : float ,
175
+ weight_range : float ,
176
+ ) -> str :
185
177
""" Return token wrapped in a span with some styles
186
178
(calculated from weight and weight_range) applied.
187
179
"""
@@ -208,8 +200,7 @@ def _colorize(token, # type: str
208
200
)
209
201
210
202
211
- def _weight_opacity (weight , weight_range ):
212
- # type: (float, float) -> str
203
+ def _weight_opacity (weight : float , weight_range : float ) -> str :
213
204
""" Return opacity value for given weight as a string.
214
205
"""
215
206
min_opacity = 0.8
@@ -220,11 +211,10 @@ def _weight_opacity(weight, weight_range):
220
211
return '{:.2f}' .format (min_opacity + (1 - min_opacity ) * rel_weight )
221
212
222
213
223
- _HSL_COLOR = Tuple [float , float , float ]
214
+ _HSL_COLOR = tuple [float , float , float ]
224
215
225
216
226
- def weight_color_hsl (weight , weight_range , min_lightness = 0.8 ):
227
- # type: (float, float, float) -> _HSL_COLOR
217
+ def weight_color_hsl (weight : float , weight_range : float , min_lightness = 0.8 ) -> _HSL_COLOR :
228
218
""" Return HSL color components for given weight,
229
219
where the max absolute weight is given by weight_range.
230
220
"""
@@ -235,21 +225,18 @@ def weight_color_hsl(weight, weight_range, min_lightness=0.8):
235
225
return hue , saturation , lightness
236
226
237
227
238
- def format_hsl (hsl_color ):
239
- # type: (_HSL_COLOR) -> str
228
+ def format_hsl (hsl_color : _HSL_COLOR ) -> str :
240
229
""" Format hsl color as css color string.
241
230
"""
242
231
hue , saturation , lightness = hsl_color
243
232
return 'hsl({}, {:.2%}, {:.2%})' .format (hue , saturation , lightness )
244
233
245
234
246
- def _hue (weight ):
247
- # type: (float) -> float
235
+ def _hue (weight : float ) -> float :
248
236
return 120 if weight > 0 else 0
249
237
250
238
251
- def get_weight_range (weights ):
252
- # type: (FeatureWeights) -> float
239
+ def get_weight_range (weights : FeatureWeights ) -> float :
253
240
""" Max absolute feature for pos and neg weights.
254
241
"""
255
242
return max_or_0 (abs (fw .weight )
@@ -258,11 +245,10 @@ def get_weight_range(weights):
258
245
259
246
260
247
def remaining_weight_color_hsl (
261
- ws , # type: List[FeatureWeight]
262
- weight_range , # type: float
263
- pos_neg , # type: str
264
- ):
265
- # type: (...) -> _HSL_COLOR
248
+ ws : list [FeatureWeight ],
249
+ weight_range : float ,
250
+ pos_neg : str ,
251
+ ) -> _HSL_COLOR :
266
252
""" Color for "remaining" row.
267
253
Handles a number of edge cases: if there are no weights in ws or weight_range
268
254
is zero, assume the worst (most intensive positive or negative color).
@@ -278,8 +264,7 @@ def remaining_weight_color_hsl(
278
264
return weight_color_hsl (weight , weight_range )
279
265
280
266
281
- def _format_unhashed_feature (feature , weight , hl_spaces ):
282
- # type: (...) -> str
267
+ def _format_unhashed_feature (feature , weight , hl_spaces ) -> str :
283
268
""" Format unhashed feature: show first (most probable) candidate,
284
269
display other candidates in title attribute.
285
270
"""
@@ -295,8 +280,7 @@ def _format_unhashed_feature(feature, weight, hl_spaces):
295
280
return html
296
281
297
282
298
- def _format_feature (feature , weight , hl_spaces ):
299
- # type: (...) -> str
283
+ def _format_feature (feature , weight , hl_spaces ) -> str :
300
284
""" Format any feature.
301
285
"""
302
286
if isinstance (feature , FormattedFeatureName ):
@@ -308,14 +292,12 @@ def _format_feature(feature, weight, hl_spaces):
308
292
return _format_single_feature (feature , weight , hl_spaces = hl_spaces )
309
293
310
294
311
- def _format_single_feature (feature , weight , hl_spaces ):
312
- # type: (str, float, bool) -> str
295
+ def _format_single_feature (feature : str , weight : float , hl_spaces : bool ) -> str :
313
296
feature = html_escape (feature )
314
297
if not hl_spaces :
315
298
return feature
316
299
317
- def replacer (n_spaces , side ):
318
- # type: (int, str) -> str
300
+ def replacer (n_spaces : int , side : str ) -> str :
319
301
m = '0.1em'
320
302
margins = {'left' : (m , 0 ), 'right' : (0 , m ), 'center' : (m , m )}[side ]
321
303
style = '; ' .join ([
@@ -331,18 +313,12 @@ def replacer(n_spaces, side):
331
313
return replace_spaces (feature , replacer )
332
314
333
315
334
- def _format_decision_tree (treedict ):
335
- # type: (...) -> str
316
+ def _format_decision_tree (treedict ) -> str :
336
317
if treedict .graphviz and _graphviz .is_supported ():
337
318
return _graphviz .dot2svg (treedict .graphviz )
338
319
else :
339
320
return tree2text (treedict )
340
321
341
322
342
- def html_escape (text ):
343
- # type: (str) -> str
344
- try :
345
- from html import escape
346
- except ImportError :
347
- from cgi import escape # type: ignore
323
+ def html_escape (text ) -> str :
348
324
return escape (text , quote = True )
0 commit comments