14
14
arbitrary fonts, but results may vary without proper tweaking and
15
15
metrics for those fonts.
16
16
"""
17
- from __future__ import (absolute_import , division , print_function ,
18
- unicode_literals )
19
-
20
- import six
21
- from six import unichr
22
17
18
+ import functools
19
+ from io import StringIO
23
20
import os
24
- from math import ceil
25
21
import types
26
22
import unicodedata
27
- from warnings import warn
28
- from functools import lru_cache
23
+ import warnings
29
24
30
25
import numpy as np
31
26
36
31
37
32
ParserElement .enablePackrat ()
38
33
39
- from matplotlib import _png , colors as mcolors , get_data_path , rcParams
34
+ from matplotlib import _png , cbook , colors as mcolors , get_data_path , rcParams
40
35
from matplotlib .afm import AFM
41
36
from matplotlib .cbook import get_realpath_and_stat
42
37
from matplotlib .ft2font import FT2Image , KERNING_DEFAULT , LOAD_NO_HINTING
@@ -81,14 +76,9 @@ def get_unicode_index(symbol, math=True):
81
76
TeX/Type1 symbol""" % locals ()
82
77
raise ValueError (message )
83
78
84
- def unichr_safe (index ):
85
- """Return the Unicode character corresponding to the index,
86
- or the replacement character if this is a narrow build of Python
87
- and the requested character is outside the BMP."""
88
- try :
89
- return unichr (index )
90
- except ValueError :
91
- return unichr (0xFFFD )
79
+
80
+ unichr_safe = cbook .deprecated ("3.0" )(chr )
81
+
92
82
93
83
class MathtextBackend (object ):
94
84
"""
@@ -166,7 +156,7 @@ def _update_bbox(self, x1, y1, x2, y2):
166
156
def set_canvas_size (self , w , h , d ):
167
157
MathtextBackend .set_canvas_size (self , w , h , d )
168
158
if self .mode != 'bbox' :
169
- self .image = FT2Image (ceil (w ), ceil (h + max (d , 0 )))
159
+ self .image = FT2Image (np . ceil (w ), np . ceil (h + max (d , 0 )))
170
160
171
161
def render_glyph (self , ox , oy , info ):
172
162
if self .mode == 'bbox' :
@@ -189,7 +179,7 @@ def render_rect_filled(self, x1, y1, x2, y2):
189
179
y = int (center - (height + 1 ) / 2.0 )
190
180
else :
191
181
y = int (y1 )
192
- self .image .draw_rect_filled (int (x1 ), y , ceil (x2 ), y + height )
182
+ self .image .draw_rect_filled (int (x1 ), y , np . ceil (x2 ), y + height )
193
183
194
184
def get_results (self , box , used_characters ):
195
185
self .mode = 'bbox'
@@ -230,7 +220,7 @@ class MathtextBackendPs(MathtextBackend):
230
220
backend.
231
221
"""
232
222
def __init__ (self ):
233
- self .pswriter = six . moves . cStringIO ()
223
+ self .pswriter = StringIO ()
234
224
self .lastfont = None
235
225
236
226
def render_glyph (self , ox , oy , info ):
@@ -361,7 +351,7 @@ def __init__(self):
361
351
362
352
def render_glyph (self , ox , oy , info ):
363
353
oy = oy - info .offset - self .height
364
- thetext = unichr_safe (info .num )
354
+ thetext = chr (info .num )
365
355
self .glyphs .append (
366
356
(info .font , info .fontsize , thetext , ox , oy ))
367
357
@@ -464,8 +454,9 @@ def set_canvas_size(self, w, h, d):
464
454
Set the size of the buffer used to render the math expression.
465
455
Only really necessary for the bitmap backends.
466
456
"""
467
10000
td>
- self .width , self .height , self .depth = ceil (w ), ceil (h ), ceil (d )
468
- self .mathtext_backend .set_canvas_size (self .width , self .height , self .depth )
457
+ self .width , self .height , self .depth = np .ceil ([w , h , d ])
458
+ self .mathtext_backend .set_canvas_size (
459
+ self .width , self .height , self .depth )
469
460
470
461
def render_glyph (self , ox , oy , facename , font_class , sym , fontsize , dpi ):
471
462
"""
@@ -661,7 +652,7 @@ def __init__(self, *args, **kwargs):
661
652
662
653
TruetypeFonts .__init__ (self , * args , ** kwargs )
663
654
self .fontmap = {}
664
- for key , val in six . iteritems ( self ._fontmap ):
655
+ for key , val in self ._fontmap . items ( ):
665
656
fullpath = findfont (val )
666
657
self .fontmap [key ] = fullpath
667
658
self .fontmap [val ] = fullpath
@@ -801,9 +792,9 @@ def _get_glyph(self, fontname, font_class, sym, fontsize, math=True):
801
792
found_symbol = True
802
793
except ValueError :
803
794
uniindex = ord ('?' )
804
- warn ("No TeX to unicode mapping for '%s'" %
805
- sym . encode ( 'ascii' , 'backslashreplace' ),
806
- MathTextWarning )
795
+ warnings . warn (
796
+ "No TeX to unicode mapping for {!a}." . format ( sym ),
797
+ MathTextWarning )
807
798
808
799
fontname , uniindex = self ._map_virtual_font (
809
800
fontname , font_class , uniindex )
@@ -815,7 +806,7 @@ def _get_glyph(self, fontname, font_class, sym, fontsize, math=True):
815
806
if found_symbol :
816
807
if fontname == 'it' :
817
808
if uniindex < 0x10000 :
818
- unistring = unichr (uniindex )
809
+ unistring = chr (uniindex )
819
810
if (not unicodedata .category (unistring )[0 ] == "L"
820
811
or unicodedata .name (unistring ).startswith ("GREEK CAPITAL" )):
821
812
new_fontname = 'rm'
@@ -831,8 +822,9 @@ def _get_glyph(self, fontname, font_class, sym, fontsize, math=True):
831
822
if not found_symbol :
832
823
if self .cm_fallback :
833
824
if isinstance (self .cm_fallback , BakomaFonts ):
834
- warn ("Substituting with a symbol from Computer Modern." ,
835
- MathTextWarning )
825
+ warnings .warn (
826
+ "Substituting with a symbol from Computer Modern." ,
827
+ MathTextWarning )
836
828
if (fontname in ('it' , 'regular' ) and
837
829
isinstance (self .cm_fallback , StixFonts )):
838
830
return self .cm_fallback ._get_glyph (
@@ -841,14 +833,14 @@ def _get_glyph(self, fontname, font_class, sym, fontsize, math=True):
841
833
return self .cm_fallback ._get_glyph (
842
834
fontname , font_class , sym , fontsize )
843
835
else :
844
- if fontname in ('it' , 'regular' ) and isinstance (self , StixFonts ):
836
+ if (fontname in ('it' , 'regular' )
837
+ and isinstance (self , StixFonts )):
845
838
return self ._get_glyph ('rm' , font_class , sym , fontsize )
846
- warn ("Font '%s' does not have a glyph for '%s' [U+%x]" %
847
- (new_fontname ,
848
- sym .encode ('ascii' , 'backslashreplace' ).decode ('ascii' ),
849
- uniindex ),
850
- MathTextWarning )
851
- warn ("Substituting with a dummy symbol." , MathTextWarning )
839
+ warnings .warn (
840
+ "Font {!r} does not have a glyph for {!a} [U+{:x}], "
841
+ "substituting with a dummy symbol." .format (
842
+ new_fontname , sym , uniindex ),
843
+ MathTextWarning )
852
844
fontname = 'rm'
853
845
new_fontname = fontname
854
846
font = self ._get_font (fontname )
@@ -885,7 +877,7 @@ def __init__(self, *args, **kwargs):
885
877
3 : 'STIXSizeThreeSym' ,
886
878
4 : 'STIXSizeFourSym' ,
887
879
5 : 'STIXSizeFiveSym' })
888
- for key , name in six . iteritems ( self ._fontmap ):
880
+ for key , name in self ._fontmap . items ( ):
889
881
fullpath = findfont (name )
890
882
self .fontmap [key ] = fullpath
891
883
self .fontmap [name ] = fullpath
@@ -972,7 +964,7 @@ class StixFonts(UnicodeFonts):
972
964
def __init__ (self , * args , ** kwargs ):
973
965
TruetypeFonts .__init__ (self , * args , ** kwargs )
974
966
7802
self .fontmap = {}
975
- for key , name in six . iteritems ( self ._fontmap ):
967
+ for key , name in self ._fontmap . items ( ):
976
968
fullpath = findfont (name )
977
969
self .fontmap [key ] = fullpath
978
970
self .fontmap [name ] = fullpath
@@ -1048,7 +1040,7 @@ def get_sized_alternatives_for_symbol(self, fontname, sym):
1048
1040
font = self ._get_font (i )
1049
1041
glyphindex = font .get_char_index (uniindex )
1050
1042
if glyphindex != 0 :
1051
- alternatives .append ((i , unichr_safe (uniindex )))
1043
+ alternatives .append ((i , chr (uniindex )))
1052
1044
1053
1045
# The largest size of the radical symbol in STIX has incorrect
1054
1046
# metrics that cause it to be disconnected from the stem.
@@ -1099,7 +1091,7 @@ def __init__(self, default_font_prop):
1099
1091
1100
1092
self .fonts ['default' ] = default_font
1101
1093
self .fonts ['regular' ] = default_font
1102
- self .pswriter = six . moves . cStringIO ()
1094
+ self .pswriter = StringIO ()
1103
1095
1104
1096
def _get_font (self , font ):
1105
1097
if font in self .fontmap :
@@ -1117,7 +1109,7 @@ def _get_font(self, font):
1117
1109
self .fonts [cached_font .get_fontname ()] = cached_font
1118
1110
return cached_font
1119
1111
1120
- def _get_info (self , fontname , font_class , sym , fontsize , dpi , math = True ):
1112
+ def _get_info (self , fontname , font_class , sym , fontsize , dpi , math = True ):
1121
1113
'load the cmfont, metrics and glyph with caching'
1122
1114
key = fontname , sym , fontsize , dpi
1123
1115
tup = self .glyphd .get (key )
@@ -1128,8 +1120,7 @@ def _get_info (self, fontname, font_class, sym, fontsize, dpi, math=True):
1128
1120
# Only characters in the "Letter" class should really be italicized.
1129
1121
# This class includes greek letters, so we're ok
1130
1122
if (fontname == 'it' and
1131
- (len (sym ) > 1 or
1132
- not unicodedata .category (six .text_type (sym )).startswith ("L" ))):
1123
+ (len (sym ) > 1 or not unicodedata .category (sym ).startswith ("L" ))):
1133
1124
fontname = 'rm'
1134
1125
1135
1126
found_symbol = False
@@ -1143,8 +1134,9 @@ def _get_info (self, fontname, font_class, sym, fontsize, dpi, math=True):
1143
1134
num = ord (glyph )
1144
1135
found_symbol = True
1145
1136
else :
1146
- warn ("No TeX to built-in Postscript mapping for {!r}" .format (sym ),
1147
- MathTextWarning )
1137
+ warnings .warn (
1138
+ "No TeX to built-in Postscript mapping for {!r}" .format (sym ),
1139
+ MathTextWarning )
1148
1140
1149
1141
slanted = (fontname == 'it' )
1150
1142
font = self ._get_font (fontname )
@@ -1153,8 +1145,10 @@ def _get_info (self, fontname, font_class, sym, fontsize, dpi, math=True):
1153
1145
try :
1154
1146
symbol_name = font .get_name_char (glyph )
1155
1147
except KeyError :
1156
- warn ("No glyph in standard Postscript font {!r} for {!r}"
1157
- .format (font .get_fontname (), sym ), MathTextWarning )
1148
+ warnings .warn (
1149
+ "No glyph in standard Postscript font {!r} for {!r}"
1150
+ .format (font .get_fontname (), sym ),
1151
+ MathTextWarning )
1158
1152
found_symbol = False
1159
1153
1160
1154
if not found_symbol :
@@ -1581,8 +1575,9 @@ def _set_glue(self, x, sign, totals, error_type):
1581
1575
self .glue_ratio = 0.
1582
1576
if o == 0 :
1583
1577
if len (self .children ):
1584
- warn ("%s %s: %r" % (error_type , self .__class__ .__name__ , self ),
1585
- MathTextWarning )
1578
+ warnings .warn (
1579
+ "%s %s: %r" % (error_type , self .__class__ .__name__ , self ),
1580
+ MathTextWarning )
1586
1581
1587
1582
def shrink (self ):
1588
1583
for child in self .children :
@@ -1824,19 +1819,19 @@ def __init__(self, state):
1824
1819
class Glue (Node ):
1825
1820
"""
1826
1821
Most of the information in this object is stored in the underlying
1827
- :class:`GlueSpec` class, which is shared between multiple glue objects. (This
1828
- is a memory optimization which probably doesn't matter anymore, but it's
1829
- easier to stick to what TeX does.)
1822
+ :class:`GlueSpec` class, which is shared between multiple glue objects.
1823
+ (This is a memory optimization which probably doesn't matter anymore, but
1824
+ it's easier to stick to what TeX does.)
1830
1825
"""
1831
1826
def __init__ (self , glue_type , copy = False ):
1832
1827
Node .__init__ (self )
1833
1828
self .glue_subtype = 'normal'
1834
- if isinstance (glue_type , six . string_types ):
1829
+ if isinstance (glue_type , str ):
1835
1830
glue_spec = GlueSpec .factory (glue_type )
1836
1831
elif isinstance (glue_type , GlueSpec ):
1837
1832
glue_spec = glue_type
1838
1833
else :
1839
- raise ValueError ("glue_type must be a glue spec name or instance. " )
1834
+ raise ValueError ("glue_type must be a glue spec name or instance" )
1840
1835
if copy :
1841
1836
glue_spec = glue_spec .copy ()
1842
1837
self .glue_spec = glue_spec
@@ -2515,11 +2510,10 @@ def parse(self, s, fonts_object, fontsize, dpi):
2515
2510
try :
2516
2511
result = self ._expression .parseString (s )
2517
2512
except ParseBaseException as err :
2518
- raise ValueError ("\n " .join ([
2519
- "" ,
2520
- err .line ,
2521
- " " * (err .column - 1 ) + "^" ,
2522
- six .text_type (err )]))
2513
+ raise ValueError ("\n " .join (["" ,
2514
+ err .line ,
2515
+ " " * (err .column - 1 ) + "^" ,
2516
+ str (err )]))
2523
2517
self ._state_stack = None
2524
2518
self ._em_width_cache = {}
2525
2519
self ._expression .resetCache ()
@@ -2641,14 +2635,11 @@ def symbol(self, s, loc, toks):
2641
2635
if c in self ._spaced_symbols :
2642
2636
# iterate until we find previous character, needed for cases
2643
2637
# such as ${ -2}$, $ -2$, or $ -2$.
2644
- for i in six .moves .xrange (1 , loc + 1 ):
2645
- prev_char = s [loc - i ]
2646
- if prev_char != ' ' :
2647
- break
2638
+ prev_char = next ((c for c in s [:loc ][::- 1 ] if c != ' ' ), '' )
2648
2639
# Binary operators at start of string should not be spaced
2649
2640
if (c in self ._binary_operators and
2650
2641
(len (s [:loc ].split ()) == 0 or prev_char == '{' or
2651
- prev_char in self ._left_delim )):
2642
+ prev_char in self ._left_delim )):
2652
2643
return [char ]
2653
2644
else :
2654
2645
return [Hlist ([self ._make_space (0.2 ),
@@ -2659,20 +2650,13 @@ def symbol(self, s, loc, toks):
2659
2650
2660
2651
# Do not space commas between brackets
2661
2652
if c == ',' :
2662
- prev_char , next_char = '' , ''
2663
- for i in six .moves .xrange (1 , loc + 1 ):
2664
- prev_char = s [loc - i ]
2665
- if prev_char != ' ' :
2666
- break
2667
- for i in six .moves .xrange (1 , len (s ) - loc ):
2668
- next_char = s [loc + i ]
2669
- if next_char != ' ' :
2670
- break
2671
- if (prev_char == '{' and next_char == '}' ):
2653
+ prev_char = next ((c for c in s [:loc ][::- 1 ] if c != ' ' ), '' )
2654
+ next_char = next ((c for c in s [loc + 1 :] if c != ' ' ), '' )
2655
+ if prev_char == '{' and next_char == '}' :
2672
2656
return [char ]
2673
2657
2674
2658
# Do not space dots as decimal separators
2675
- if ( c == '.' and s [loc - 1 ].isdigit () and s [loc + 1 ].isdigit () ):
2659
+ if c == '.' and s [loc - 1 ].isdigit () and s [loc + 1 ].isdigit ():
2676
2660
return [char ]
2677
2661
else :
2678
2662
return [Hlist ([char ,
@@ -2857,7 +2841,7 @@ def subsuper(self, s, loc, toks):
2857
2841
napostrophes = 0
2858
2842
new_toks = []
2859
2843
for tok in toks [0 ]:
2860
- if isinstance (tok , six . string_types ) and tok not in ('^' , '_' ):
2844
+ if isinstance (tok , str ) and tok not in ('^' , '_' ):
2861
2845
napostrophes += len (tok )
2862
2846
elif isinstance (tok , Char ) and tok .c == "'" :
2863
2847
napostrophes += 1
@@ -3249,7 +3233,7 @@ def __init__(self, output):
3249
3233
"""
3250
3234
self ._output = output .lower ()
3251
3235
3252
- @lru_cache (50 )
3236
+ @functools . lru_cache (50 )
3253
3237
def parse (self , s , dpi = 72 , prop = None ):
3254
3238
"""
3255
3239
Parse the given math expression *s* at the given *dpi*. If
0 commit comments