1414arbitrary fonts, but results may vary without proper tweaking and
1515metrics for those fonts.
1616"""
17- from __future__ import (absolute_import , division , print_function ,
18- unicode_literals )
19-
20- import six
21- from six import unichr
2217
18+ import functools
19+ from io import StringIO
2320import os
24- from math import ceil
2521import types
2622import unicodedata
27- from warnings import warn
28- from functools import lru_cache
23+ import warnings
2924
3025import numpy as np
3126
3631
3732ParserElement .enablePackrat ()
3833
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
4035from matplotlib .afm import AFM
4136from matplotlib .cbook import get_realpath_and_stat
4237from matplotlib .ft2font import FT2Image , KERNING_DEFAULT , LOAD_NO_HINTING
@@ -81,14 +76,9 @@ def get_unicode_index(symbol, math=True):
8176TeX/Type1 symbol""" % locals ()
8277 raise ValueError (message )
8378
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+
9282
9383class MathtextBackend (object ):
9484 """
@@ -166,7 +156,7 @@ def _update_bbox(self, x1, y1, x2, y2):
166156 def set_canvas_size (self , w , h , d ):
167157 MathtextBackend .set_canvas_size (self , w , h , d )
168158 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 )))
170160
171161 def render_glyph (self , ox , oy , info ):
172162 if self .mode == 'bbox' :
@@ -189,7 +179,7 @@ def render_rect_filled(self, x1, y1, x2, y2):
189179 y = int (center - (height + 1 ) / 2.0 )
190180 else :
191181 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 )
193183
194184 def get_results (self , box , used_characters ):
195185 self .mode = 'bbox'
@@ -230,7 +220,7 @@ class MathtextBackendPs(MathtextBackend):
230220 backend.
231221 """
232222 def __init__ (self ):
233- self .pswriter = six . moves . cStringIO ()
223+ self .pswriter = StringIO ()
234224 self .lastfont = None
235225
236226 def render_glyph (self , ox , oy , info ):
@@ -361,7 +351,7 @@ def __init__(self):
361351
362352 def render_glyph (self , ox , oy , info ):
363353 oy = oy - info .offset - self .height
364- thetext = unichr_safe (info .num )
354+ thetext = chr (info .num )
365355 self .glyphs .append (
366356 (info .font , info .fontsize , thetext , ox , oy ))
367357
@@ -464,8 +454,9 @@ def set_canvas_size(self, w, h, d):
464454 Set the size of the buffer used to render the math expression.
465455 Only really necessary for the bitmap backends.
466456 """
467- 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 )
469460
470461 def render_glyph (self , ox , oy , facename , font_class , sym , fontsize , dpi ):
471462 """
@@ -661,7 +652,7 @@ def __init__(self, *args, **kwargs):
661652
662653 TruetypeFonts .__init__ (self , * args , ** kwargs )
663654 self .fontmap = {}
664- for key , val in six . iteritems ( self ._fontmap ):
655+ for key , val in self ._fontmap . items ( ):
665656 fullpath = findfont (val )
666657 self .fontmap [key ] = fullpath
667658 self .fontmap [val ] = fullpath
@@ -801,9 +792,9 @@ def _get_glyph(self, fontname, font_class, sym, fontsize, math=True):
801792 found_symbol = True
802793 except ValueError :
803794 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 )
807798
808799 fontname , uniindex = self ._map_virtual_font (
809800 fontname , font_class , uniindex )
@@ -815,7 +806,7 @@ def _get_glyph(self, fontname, font_class, sym, fontsize, math=True):
815806 if found_symbol :
816807 if fontname == 'it' :
817808 if uniindex < 0x10000 :
818- unistring = unichr (uniindex )
809+ unistring = chr (uniindex )
819810 if (not unicodedata .category (unistring )[0 ] == "L"
820811 or unicodedata .name (unistring ).startswith ("GREEK CAPITAL" )):
821812 new_fontname = 'rm'
@@ -831,8 +822,9 @@ def _get_glyph(self, fontname, font_class, sym, fontsize, math=True):
831822 if not found_symbol :
832823 if self .cm_fallback :
833824 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 )
836828 if (fontname in ('it' , 'regular' ) and
837829 isinstance (self .cm_fallback , StixFonts )):
838830 return self .cm_fallback ._get_glyph (
@@ -841,14 +833,14 @@ def _get_glyph(self, fontname, font_class, sym, fontsize, math=True):
841833 return self .cm_fallback ._get_glyph (
842834 fontname , font_class , sym , fontsize )
843835 else :
844- if fontname in ('it' , 'regular' ) and isinstance (self , StixFonts ):
836+ if (fontname in ('it' , 'regular' )
837+ and isinstance (self , StixFonts )):
845838 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 )
852844 fontname = 'rm'
853845 new_fontname = fontname
854846 font = self ._get_font (fontname )
@@ -885,7 +877,7 @@ def __init__(self, *args, **kwargs):
885877 3 : 'STIXSizeThreeSym' ,
886878 4 : 'STIXSizeFourSym' ,
887879 5 : 'STIXSizeFiveSym' })
888- for key , name in six . iteritems ( self ._fontmap ):
880+ for key , name in self ._fontmap . items ( ):
889881 fullpath = findfont (name )
890882 self .fontmap [key ] = fullpath
891883 self .fontmap [name ] = fullpath
@@ -972,7 +964,7 @@ class StixFonts(UnicodeFonts):
972964 def __init__ (self , * args , ** kwargs ):
973965 TruetypeFonts .__init__ (self , * args , ** kwargs )
974966 self .fontmap = {}
975- for key , name in six . iteritems ( self ._fontmap ):
967+ for key , name in self ._fontmap . items ( ):
976968 fullpath = findfont (name )
977969 self .fontmap [key ] = fullpath
978970 self .fontmap [name ] = fullpath
@@ -1048,7 +1040,7 @@ def get_sized_alternatives_for_symbol(self, fontname, sym):
10481040 font = self ._get_font (i )
10491041 glyphindex = font .get_char_index (uniindex )
10501042 if glyphindex != 0 :
1051- alternatives .append ((i , unichr_safe (uniindex )))
1043+ alternatives .append ((i , chr (uniindex )))
10521044
10531045 # The largest size of the radical symbol in STIX has incorrect
10541046 # metrics that cause it to be disconnected from the stem.
@@ -1099,7 +1091,7 @@ def __init__(self, default_font_prop):
10991091
11001092 self .fonts ['default' ] = default_font
11011093 self .fonts ['regular' ] = default_font
1102- self .pswriter = six . moves . cStringIO ()
1094+ self .pswriter = StringIO ()
11031095
11041096 def _get_font (self , font ):
11051097 if font in self .fontmap :
@@ -1117,7 +1109,7 @@ def _get_font(self, font):
11171109 self .fonts [cached_font .get_fontname ()] = cached_font
11181110 return cached_font
11191111
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 ):
11211113 'load the cmfont, metrics and glyph with caching'
11221114 key = fontname , sym , fontsize , dpi
11231115 tup = self .glyphd .get (key )
@@ -1128,8 +1120,7 @@ def _get_info (self, fontname, font_class, sym, fontsize, dpi, math=True):
11281120 # Only characters in the "Letter" class should really be italicized.
11291121 # This class includes greek letters, so we're ok
11301122 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" ))):
11331124 fontname = 'rm'
11341125
11351126 found_symbol = False
@@ -1143,8 +1134,9 @@ def _get_info (self, fontname, font_class, sym, fontsize, dpi, math=True):
11431134 num = ord (glyph )
11441135 found_symbol = True
11451136 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 )
11481140
11491141 slanted = (fontname == 'it' )
11501142 font = self ._get_font (fontname )
@@ -1153,8 +1145,10 @@ def _get_info (self, fontname, font_class, sym, fontsize, dpi, math=True):
11531145 try :
11541146 symbol_name = font .get_name_char (glyph )
11551147 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 )
11581152 found_symbol = False
11591153
11601154 if not found_symbol :
@@ -1581,8 +1575,9 @@ def _set_glue(self, x, sign, totals, error_type):
15811575 self .glue_ratio = 0.
15821576 if o == 0 :
15831577 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 )
15861581
15871582 def shrink (self ):
15881583 for child in self .children :
@@ -1824,19 +1819,19 @@ def __init__(self, state):
18241819class Glue (Node ):
18251820 """
18261821 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.)
18301825 """
18311826 def __init__ (self , glue_type , copy = False ):
18321827 Node .__init__ (self )
18331828 self .glue_subtype = 'normal'
1834- if isinstance (glue_type , six . string_types ):
1829+ if isinstance (glue_type , str ):
18351830 glue_spec = GlueSpec .factory (glue_type )
18361831 elif isinstance (glue_type , GlueSpec ):
18371832 glue_spec = glue_type
18381833 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" )
18401835 if copy :
18411836 glue_spec = glue_spec .copy ()
18421837 self .glue_spec = glue_spec
@@ -2515,11 +2510,10 @@ def parse(self, s, fonts_object, fontsize, dpi):
25152510 try :
25162511 result = self ._expression .parseString (s )
25172512 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 )]))
25232517 self ._state_stack = None
25242518 self ._em_width_cache = {}
25252519 self ._expression .resetCache ()
@@ -2641,14 +2635,11 @@ def symbol(self, s, loc, toks):
26412635 if c in self ._spaced_symbols :
26422636 # iterate until we find previous character, needed for cases
26432637 # 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 != ' ' ), '' )
26482639 # Binary operators at start of string should not be spaced
26492640 if (c in self ._binary_operators and
26502641 (len (s [:loc ].split ()) == 0 or prev_char == '{' or
2651- prev_char in self ._left_delim )):
2642+ prev_char in self ._left_delim )):
26522643 return [char ]
26532644 else :
26542645 return [Hlist ([self ._make_space (0.2 ),
@@ -2659,20 +2650,13 @@ def symbol(self, s, loc, toks):
26592650
26602651 # Do not space commas between brackets
26612652 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 == '}' :
26722656 return [char ]
26732657
26742658 # 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 ():
26762660 return [char ]
26772661 else :
26782662 return [Hlist ([char ,
@@ -2857,7 +2841,7 @@ def subsuper(self, s, loc, toks):
28572841 napostrophes = 0
28582842 new_toks = []
28592843 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 ('^' , '_' ):
28612845 napostrophes += len (tok )
28622846 elif isinstance (tok , Char ) and tok .c == "'" :
28632847 napostrophes += 1
@@ -3249,7 +3233,7 @@ def __init__(self, output):
32493233 """
32503234 self ._output = output .lower ()
32513235
3252- @lru_cache (50 )
3236+ @functools . lru_cache (50 )
32533237 def parse (self , s , dpi = 72 , prop = None ):
32543238 """
32553239 Parse the given math expression *s* at the given *dpi*. If
0 commit comments