Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use some new Python3 types #10432

Merged
merged 2 commits into from Feb 17, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 5 additions & 0 deletions doc/api/next_api_changes/2018-02-15-ES.rst
@@ -0,0 +1,5 @@
matplotlib.cbook.Bunch deprecated
`````````````````````````````````
The ``matplotlib.cbook.Bunch`` class has been deprecated. Instead, use
`types.SimpleNamespace` from the standard library which provides the same
functionality.
3 changes: 2 additions & 1 deletion lib/matplotlib/axes/_base.py
Expand Up @@ -10,6 +10,7 @@
import warnings
import math
from operator import attrgetter
import types

import numpy as np

Expand Down Expand Up @@ -3954,7 +3955,7 @@ def start_pan(self, x, y, button):
Intended to be overridden by new projection types.

"""
self._pan_start = cbook.Bunch(
self._pan_start = types.SimpleNamespace(
lim=self.viewLim.frozen(),
trans=self.transData.frozen(),
trans_inverse=self.transData.inverted().frozen(),
Expand Down
8 changes: 5 additions & 3 deletions lib/matplotlib/backends/backend_pdf.py
Expand Up @@ -17,6 +17,7 @@
import struct
import sys
import time
import types
import warnings
import zlib

Expand All @@ -28,7 +29,7 @@
_Backend, FigureCanvasBase, FigureManagerBase, GraphicsContextBase,
RendererBase)
from matplotlib.backends.backend_mixed import MixedModeRenderer
from matplotlib.cbook import (Bunch, get_realpath_and_stat,
from matplotlib.cbook import (get_realpath_and_stat,
is_writable_file_like, maxdict)
from matplotlib.figure import Figure
from matplotlib.font_manager import findfont, is_opentype_cff_font, get_font
Expand Down Expand Up @@ -320,7 +321,8 @@ def pdfRepr(self):
grestore=b'Q', textpos=b'Td', selectfont=b'Tf', textmatrix=b'Tm',
show=b'Tj', showkern=b'TJ', setlinewidth=b'w', clip=b'W', shading=b'sh')

Op = Bunch(**{name: Operator(value) for name, value in _pdfops.items()})
Op = types.SimpleNamespace(**{name: Operator(value)
for name, value in _pdfops.items()})


def _paint_path(fill, stroke):
Expand Down Expand Up @@ -685,7 +687,7 @@ def dviFontName(self, dvifont):
pdfname = Name('F%d' % self.nextFont)
self.nextFont += 1
_log.debug('Assigning font %s = %s (dvi)', pdfname, dvifont.texname)
self.dviFontInfo[dvifont.texname] = Bunch(
self.dviFontInfo[dvifont.texname] = types.SimpleNamespace(
dvifont=dvifont,
pdfname=pdfname,
fontfile=psfont.filename,
Expand Down
13 changes: 3 additions & 10 deletions lib/matplotlib/cbook/__init__.py
Expand Up @@ -488,7 +488,8 @@ def strip_math(s):
return s


class Bunch(object):
@deprecated('3.0', alternative='types.SimpleNamespace')
class Bunch(types.SimpleNamespace):
"""
Often we want to just collect a bunch of stuff together, naming each
item of the bunch; a dictionary's OK for that, but a small do- nothing
Expand All @@ -497,16 +498,8 @@ class is even handier, and prettier to use. Whenever you want to

>>> point = Bunch(datum=2, squared=4, coord=12)
>>> point.datum

By: Alex Martelli
From: https://code.activestate.com/recipes/121294/
"""
def __init__(self, **kwds):
self.__dict__.update(kwds)

def __repr__(self):
return 'Bunch(%s)' % ', '.join(
'%s=%s' % kv for kv in six.iteritems(vars(self)))
pass


@deprecated('2.1')
Expand Down
12 changes: 7 additions & 5 deletions lib/matplotlib/dviread.py
Expand Up @@ -18,15 +18,17 @@

"""
from collections import namedtuple
import enum
from functools import lru_cache, partial, wraps
import logging
import numpy as np
import os
import re
import struct
import sys
import textwrap

import numpy as np

from matplotlib import cbook, rcParams
from matplotlib.compat import subprocess

Expand All @@ -48,7 +50,7 @@
# just stops reading)
# finale: the finale (unimplemented in our current implementation)

_dvistate = cbook.Bunch(pre=0, outer=1, inpage=2, post_post=3, finale=4)
_dvistate = enum.Enum('DviState', 'pre outer inpage post_post finale')

# The marks on a page consist of text and boxes. A page also has dimensions.
Page = namedtuple('Page', 'text boxes height width descent')
Expand Down Expand Up @@ -301,7 +303,7 @@ def _read(self):
self._dtable[byte](self, byte)
if byte == 140: # end of page
return True
if self.state == _dvistate.post_post: # end of file
if self.state is _dvistate.post_post: # end of file
self.close()
return False

Expand Down Expand Up @@ -622,7 +624,7 @@ def _read(self):
while True:
byte = self.file.read(1)[0]
# If we are in a packet, execute the dvi instructions
if self.state == _dvistate.inpage:
if self.state is _dvistate.inpage:
byte_at = self.file.tell()-1
if byte_at == packet_ends:
self._finalize_packet(packet_char, packet_width)
Expand Down Expand Up @@ -678,7 +680,7 @@ def _finalize_packet(self, packet_char, packet_width):
self.state = _dvistate.outer

def _pre(self, i, x, cs, ds):
if self.state != _dvistate.pre:
if self.state is not _dvistate.pre:
raise ValueError("pre command in middle of vf file")
if i != 202:
raise ValueError("Unknown vf format %d" % i)
Expand Down
17 changes: 9 additions & 8 deletions lib/matplotlib/mathtext.py
Expand Up @@ -22,6 +22,7 @@

import os
from math import ceil
import types
import unicodedata
from warnings import warn
from functools import lru_cache
Expand All @@ -37,7 +38,7 @@

from matplotlib import _png, colors as mcolors, get_data_path, rcParams
from matplotlib.afm import AFM
from matplotlib.cbook import Bunch, get_realpath_and_stat
from matplotlib.cbook import get_realpath_and_stat
from matplotlib.ft2font import FT2Image, KERNING_DEFAULT, LOAD_NO_HINTING
from matplotlib.font_manager import findfont, FontProperties, get_font
from matplotlib._mathtext_data import (latex_to_bakoma, latex_to_standard,
Expand Down Expand Up @@ -312,8 +313,8 @@ def render_rect_filled(self, x1, y1, x2, y2):

def get_results(self, box, used_characters):
ship(0, 0, box)
svg_elements = Bunch(svg_glyphs = self.svg_glyphs,
svg_rects = self.svg_rects)
svg_elements = types.SimpleNamespace(svg_glyphs=self.svg_glyphs,
svg_rects=self.svg_rects)
return (self.width,
self.height + self.depth,
self.depth,
Expand Down Expand Up @@ -587,7 +588,7 @@ def _get_info(self, fontname, font_class, sym, fontsize, dpi, math=True):

xmin, ymin, xmax, ymax = [val/64.0 for val in glyph.bbox]
offset = self._get_offset(font, glyph, fontsize, dpi)
metrics = Bunch(
metrics = types.SimpleNamespace(
advance = glyph.linearHoriAdvance/65536.0,
height = glyph.height/64.0,
width = glyph.width/64.0,
Expand All @@ -600,7 +601,7 @@ def _get_info(self, fontname, font_class, sym, fontsize, dpi, math=True):
slanted = slanted
)

result = self.glyphd[key] = Bunch(
result = self.glyphd[key] = types.SimpleNamespace(
font = font,
fontsize = fontsize,
postscript_name = font.postscript_name,
Expand Down Expand Up @@ -1167,7 +1168,7 @@ def _get_info (self, fontname, font_class, sym, fontsize, dpi, math=True):

xmin, ymin, xmax, ymax = [val * scale
for val in font.get_bbox_char(glyph)]
metrics = Bunch(
metrics = types.SimpleNamespace(
advance = font.get_width_char(glyph) * scale,
width = font.get_width_char(glyph) * scale,
height = font.get_height_char(glyph) * scale,
Expand All @@ -1180,7 +1181,7 @@ def _get_info (self, fontname, font_class, sym, fontsize, dpi, math=True):
slanted = slanted
)

self.glyphd[key] = Bunch(
self.glyphd[key] = types.SimpleNamespace(
font = font,
fontsize = fontsize,
postscript_name = font.get_fontname(),
Expand Down Expand Up @@ -2290,7 +2291,7 @@ class Parser(object):
_right_delim = set(r") ] \} > \rfloor \rangle \rceil".split())

def __init__(self):
p = Bunch()
p = types.SimpleNamespace()
# All forward declarations are here
p.accent = Forward()
p.ambi_delim = Forward()
Expand Down
3 changes: 2 additions & 1 deletion lib/matplotlib/projections/polar.py
Expand Up @@ -4,6 +4,7 @@
import six

from collections import OrderedDict
import types

import numpy as np

Expand Down Expand Up @@ -1362,7 +1363,7 @@ def start_pan(self, x, y, button):
elif button == 3:
mode = 'zoom'

self._pan_start = cbook.Bunch(
self._pan_start = types.SimpleNamespace(
rmax=self.get_rmax(),
trans=self.transData.frozen(),
trans_inverse=self.transData.inverted().frozen(),
Expand Down
8 changes: 5 additions & 3 deletions lib/matplotlib/sankey.py
Expand Up @@ -6,10 +6,11 @@

import six
import logging
from types import SimpleNamespace
from six.moves import zip
import numpy as np

from matplotlib.cbook import iterable, Bunch
from matplotlib.cbook import iterable
from matplotlib.path import Path
from matplotlib.patches import PathPatch
from matplotlib.transforms import Affine2D
Expand Down Expand Up @@ -780,8 +781,9 @@ def _get_angle(a, r):
# where either could determine the margins (e.g., arrow shoulders).

# Add this diagram as a subdiagram.
self.diagrams.append(Bunch(patch=patch, flows=flows, angles=angles,
tips=tips, text=text, texts=texts))
self.diagrams.append(
SimpleNamespace(patch=patch, flows=flows, angles=angles, tips=tips,
text=text, texts=texts))

# Allow a daisy-chained call structure (see docstring for the class).
return self
Expand Down
43 changes: 21 additions & 22 deletions lib/matplotlib/type1font.py
Expand Up @@ -28,6 +28,7 @@
import six

import binascii
import enum
import io
import itertools
import re
Expand All @@ -40,6 +41,11 @@ def ord(x):
return x


# token types
_TokenType = enum.Enum('_TokenType',
'whitespace name string delimiter number')


class Type1Font(object):
"""
A class representing a Type-1 font, for use by backends.
Expand Down Expand Up @@ -143,25 +149,18 @@ def _split(self, data):
_comment_re = re.compile(br'%[^\r\n\v]*')
_instring_re = re.compile(br'[()\\]')

# token types, compared via object identity (poor man's enum)
_whitespace = object()
_name = object()
_string = object()
_delimiter = object()
_number = object()

@classmethod
def _tokens(cls, text):
"""
A PostScript tokenizer. Yield (token, value) pairs such as
(cls._whitespace, ' ') or (cls._name, '/Foobar').
(_TokenType.whitespace, ' ') or (_TokenType.name, '/Foobar').
"""
pos = 0
while pos < len(text):
match = (cls._comment_re.match(text[pos:]) or
cls._whitespace_re.match(text[pos:]))
if match:
yield (cls._whitespace, match.group())
yield (_TokenType.whitespace, match.group())
pos += match.end()
elif text[pos] == b'(':
start = pos
Expand All @@ -178,25 +177,25 @@ def _tokens(cls, text):
depth -= 1
else: # a backslash - skip the next character
pos += 1
yield (cls._string, text[start:pos])
yield (_TokenType.string, text[start:pos])
elif text[pos:pos + 2] in (b'<<', b'>>'):
yield (cls._delimiter, text[pos:pos + 2])
yield (_TokenType.delimiter, text[pos:pos + 2])
pos += 2
elif text[pos] == b'<':
start = pos
pos += text[pos:].index(b'>')
yield (cls._string, text[start:pos])
yield (_TokenType.string, text[start:pos])
else:
match = cls._token_re.match(text[pos:])
if match:
try:
float(match.group())
yield (cls._number, match.group())
yield (_TokenType.number, match.group())
except ValueError:
yield (cls._name, match.group())
yield (_TokenType.name, match.group())
pos += match.end()
else:
yield (cls._delimiter, text[pos:pos + 1])
yield (_TokenType.delimiter, text[pos:pos + 1])
pos += 1

def _parse(self):
Expand All @@ -210,23 +209,23 @@ def _parse(self):
'UnderlinePosition': -100, 'UnderlineThickness': 50}
filtered = ((token, value)
for token, value in self._tokens(self.parts[0])
if token is not self._whitespace)
if token is not _TokenType.whitespace)
# The spec calls this an ASCII format; in Python 2.x we could
# just treat the strings and names as opaque bytes but let's
# turn them into proper Unicode, and be lenient in case of high bytes.
convert = lambda x: x.decode('ascii', 'replace')
for token, value in filtered:
if token is self._name and value.startswith(b'/'):
if token is _TokenType.name and value.startswith(b'/'):
key = convert(value[1:])
token, value = next(filtered)
if token is self._name:
if token is _TokenType.name:
if value in (b'true', b'false'):
value = value == b'true'
else:
value = convert(value.lstrip(b'/'))
elif token is self._string:
elif token is _TokenType.string:
value = convert(value.lstrip(b'(').rstrip(b')'))
elif token is self._number:
elif token is _TokenType.number:
if b'.' in value:
value = float(value)
else:
Expand Down Expand Up @@ -284,7 +283,7 @@ def replacer(tokens):
token, value = next(tokens) # name, e.g., /FontMatrix
yield bytes(value)
token, value = next(tokens) # possible whitespace
while token is cls._whitespace:
while token is _TokenType.whitespace:
yield bytes(value)
token, value = next(tokens)
if value != b'[': # name/number/etc.
Expand All @@ -309,7 +308,7 @@ def suppress(tokens):
b'/UniqueID': suppress}

for token, value in tokens:
if token is cls._name and value in table:
if token is _TokenType.name and value in table:
for value in table[value](itertools.chain([(token, value)],
tokens)):
yield value
Expand Down