Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit cf819b6

Browse files
committed
Deprecate the top-level functions in path.py
1 parent d39f9c0 commit cf819b6

File tree

4 files changed

+182
-19
lines changed

4 files changed

+182
-19
lines changed

doc/api/api_changes.rst

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,22 @@ For new features that were added to matplotlib, please see
1515
Changes in 1.3.x
1616
================
1717

18+
* The top-level functions in `matplotlib.path` that are implemented in
19+
C++ were never meant to be public. Instead, users should use the
20+
Pythonic wrappers for them in the `path.Path` and
21+
`collections.Collection` classes. Use the following mapping to update
22+
your code:
23+
24+
- `point_in_path` -> `path.Path.contains_point`
25+
- `get_path_extents` -> `path.Path.get_extents`
26+
- `point_in_path_collection` -> `collection.Collection.contains`
27+
- `path_in_path` -> `path.Path.contains_path`
28+
- `path_intersects_path` -> `path.Path.intersects_path`
29+
- `convert_path_to_polygons` -> `path.Path.to_polygons`
30+
- `cleanup_path` -> `path.Path.cleaned`
31+
- `points_in_path` -> `path.Path.contains_points`
32+
- `clip_path_to_rect` -> `path.Path.clip_to_bbox`
33+
1834
* `Path` objects can now be marked as `readonly` by passing
1935
`readonly=True` to its constructor. The built-in path singletons,
2036
obtained through `Path.unit*` class methods return readonly paths.

lib/matplotlib/cbook.py

Lines changed: 120 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
"""
2-
A collection of utility functions and classes. Originally, many
2+
A collection of utility functions and classes. Originally, many
33
(but not all) were from the Python Cookbook -- hence the name cbook.
44
55
This module is safe to import from anywhere within matplotlib;
@@ -44,6 +44,125 @@ class MatplotlibDeprecationWarning(UserWarning):
4444

4545
mplDeprecation = MatplotlibDeprecationWarning
4646

47+
48+
def deprecated(since, message='', name='', alternative='', pending=False,
49+
obj_type='function'):
50+
"""
51+
Used to mark a function as deprecated.
52+
53+
Parameters
54+
------------
55+
since : str
56+
The release at which this API became deprecated. This is
57+
required.
58+
59+
message : str, optional
60+
Override the default deprecation message. The format
61+
specifier `%(func)s` may be used for the name of the function,
62+
and `%(alternative)s` may be used in the deprecation message
63+
to insert the name of an alternative to the deprecated
64+
function. `%(obj_type)` may be used to insert a friendly name
65+
for the type of object being deprecated.
66+
67+
name : str, optional
68+
The name of the deprecated function; if not provided the name
69+
is automatically determined from the passed in function,
70+
though this is useful in the case of renamed functions, where
71+
the new function is just assigned to the name of the
72+
deprecated function. For example::
73+
74+
def new_function():
75+
...
76+
oldFunction = new_function
77+
78+
alternative : str, optional
79+
An alternative function that the user may use in place of the
80+
deprecated function. The deprecation warning will tell the user about
81+
this alternative if provided.
82+
83+
pending : bool, optional
84+
If True, uses a PendingDeprecationWarning instead of a
85+
DeprecationWarning.
86+
"""
87+
88+
def deprecate(func, message=message, name=name, alternative=alternative,
89+
pending=pending):
90+
import functools
91+
import textwrap
92+
93+
if isinstance(func, classmethod):
94+
try:
95+
func = func.__func__
96+
except AttributeError:
97+
# classmethods in Python2.6 and below lack the __func__
98+
# attribute so we need to hack around to get it
99+
method = func.__get__(None, object)
100+
if hasattr(method, '__func__'):
101+
func = method.__func__
102+
elif hasattr(method, 'im_func'):
103+
func = method.im_func
104+
else:
105+
# Nothing we can do really... just return the original
106+
# classmethod
107+
return func
108+
is_classmethod = True
109+
else:
110+
is_classmethod = False
111+
112+
if not name:
113+
name = func.__name__
114+
115+
altmessage = ''
116+
if not message or type(message) == type(deprecate):
117+
if pending:
118+
message = ('The %(func)s %(obj_type)s will be deprecated in a '
119+
'future version.')
120+
else:
121+
message = ('The %(func)s %(obj_type)s is deprecated and may '
122+
'be removed in a future version.')
123+
if alternative:
124+
altmessage = '\n Use %s instead.' % alternative
125+
126+
message = ((message % {
127+
'func': name,
128+
'name': name,
129+
'alternative': alternative,
130+
'obj_type': obj_type}) +
131+
altmessage)
132+
133+
@functools.wraps(func)
134+
def deprecated_func(*args, **kwargs):
135+
warnings.warn(message, mplDeprecation, stacklevel=2)
136+
137+
return func(*args, **kwargs)
138+
139+
old_doc = deprecated_func.__doc__
140+
if not old_doc:
141+
old_doc = ''
142+
old_doc = textwrap.dedent(old_doc).strip('\n')
143+
altmessage = altmessage.strip()
144+
if not altmessage:
145+
altmessage = message.strip()
146+
new_doc = (('\n.. deprecated:: %(since)s'
147+
'\n %(message)s\n\n' %
148+
{'since': since, 'message': altmessage.strip()}) + old_doc)
149+
if not old_doc:
150+
# This is to prevent a spurious 'unexected unindent' warning from
151+
# docutils when the original docstring was blank.
152+
new_doc += r'\ '
153+
154+
deprecated_func.__doc__ = new_doc
155+
156+
if is_classmethod:
157+
deprecated_func = classmethod(deprecated_func)
158+
return deprecated_func
159+
160+
if type(message) == type(deprecate):
161+
return deprecate(message)
162+
163+
return deprecate
164+
165+
47166
# On some systems, locale.getpreferredencoding returns None,
48167
# which can break unicode; and the sage project reports that
49168
# some systems have incorrect locale specifications, e.g.,

lib/matplotlib/collections.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
from matplotlib.artist import allow_rasterization
2323
import matplotlib.backend_bases as backend_bases
2424
import matplotlib.path as mpath
25+
from matplotlib import _path
2526
import matplotlib.mlab as mlab
2627

2728

@@ -315,7 +316,7 @@ def contains(self, mouseevent):
315316

316317
transform, transOffset, offsets, paths = self._prepare_points()
317318

318-
ind = mpath.point_in_path_collection(
319+
ind = _path.point_in_path_collection(
319320
mouseevent.x, mouseevent.y, pickradius,
320321
transform.frozen(), paths, self.get_transforms(),
321322
offsets, transOffset, pickradius <= 0,

lib/matplotlib/path.py

Lines changed: 44 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,16 @@
99
import numpy as np
1010
from numpy import ma
1111

12-
from matplotlib._path import point_in_path, get_path_extents, \
13-
point_in_path_collection, get_path_collection_extents, \
14-
path_in_path, path_intersects_path, convert_path_to_polygons, \
15-
cleanup_path, points_in_path, clip_path_to_rect
12+
from matplotlib import _path
13+
14+
# ._path import point_in_path, get_path_extents, \
15+
# point_in_path_collection, get_path_collection_extents, \
16+
# path_in_path, path_intersects_path, convert_path_to_polygons, \
17+
# cleanup_path, points_in_path, clip_path_to_rect
1618
from matplotlib.cbook import simple_linear_interpolation, maxdict
1719
from matplotlib import rcParams
1820

21+
1922
class Path(object):
2023
"""
2124
:class:`Path` represents a series of possibly disconnected,
@@ -356,9 +359,10 @@ def iter_segments(self, transform=None, remove_nans=True, clip=None,
356359
CLOSEPOLY = self.CLOSEPOLY
357360
STOP = self.STOP
358361

359-
vertices, codes = cleanup_path(self, transform, remove_nans, clip,
360-
snap, stroke_width, simplify, curves,
361-
sketch)
362+
vertices, codes = _path.cleanup_path(
363+
self, transform, remove_nans, clip,
364+
snap, stroke_width, simplify, curves,
365+
sketch)
362366
len_vertices = len(vertices)
363367

364368
i = 0
@@ -398,7 +402,7 @@ def contains_point(self, point, transform=None, radius=0.0):
398402
"""
399403
if transform is not None:
400404
transform = transform.frozen()
401-
result = point_in_path(point[0], point[1], radius, self, transform)
405+
result = _path.point_in_path(point[0], point[1], radius, self, transform)
402406
return result
403407

404408
def contains_points(self, points, transform=None, radius=0.0):
@@ -414,7 +418,7 @@ def contains_points(self, points, transform=None, radius=0.0):
414418
"""
415419
if transform is not None:
416420
transform = transform.frozen()
417-
result = points_in_path(points, radius, self, transform)
421+
result = _path.points_in_path(points, radius, self, transform)
418422
return result
419423

420424
def contains_path(self, path, transform=None):
@@ -426,7 +430,7 @@ def contains_path(self, path, transform=None):
426430
"""
427431
if transform is not None:
428432
transform = transform.frozen()
429-
return path_in_path(self, None, path, transform)
433+
return _path.path_in_path(self, None, path, transform)
430434

431435
def get_extents(self, transform=None):
432436
"""
@@ -444,7 +448,7 @@ def get_extents(self, transform=None):
444448
if not transform.is_affine:
445449
path = self.transformed(transform)
446450
transform = None
447-
return Bbox(get_path_extents(path, transform))
451+
return Bbox(_path.get_path_extents(path, transform))
448452

449453
def intersects_path(self, other, filled=True):
450454
"""
@@ -454,7 +458,7 @@ def intersects_path(self, other, filled=True):
454458
That is, if one path completely encloses the other,
455459
:meth:`intersects_path` will return True.
456460
"""
457-
return path_intersects_path(self, other, filled)
461+
return _path.path_intersects_path(self, other, filled)
458462

459463
def intersects_bbox(self, bbox, filled=True):
460464
"""
@@ -514,7 +518,7 @@ def to_polygons(self, transform=None, width=0, height=0):
514518

515519
# Deal with the case where there are curves and/or multiple
516520
# subpaths (using extension code)
517-
return convert_path_to_polygons(self, transform, width, height)
521+
return _path.convert_path_to_polygons(self, transform, width, height)
518522

519523
_unit_rectangle = None
520524
@classmethod
@@ -833,12 +837,11 @@ def clip_to_bbox(self, bbox, inside=True):
833837
to the outside of the box.
834838
"""
835839
# Use make_compound_path_from_polys
836-
verts = clip_path_to_rect(self, bbox, inside)
840+
verts = _path.clip_path_to_rect(self, bbox, inside)
837841
paths = [Path(poly) for poly in verts]
838842
return self.make_compound_path(*paths)
839843

840844

841-
_get_path_collection_extents = get_path_collection_extents
842845
def get_path_collection_extents(
843846
master_transform, paths, transforms, offsets, offset_transform):
844847
"""
@@ -869,9 +872,10 @@ def get_path_collection_extents(
869872
from transforms import Bbox
870873
if len(paths) == 0:
871874
raise ValueError("No paths provided")
872-
return Bbox.from_extents(*_get_path_collection_extents(
875+
return Bbox.from_extents(*_path.get_path_collection_extents(
873876
master_transform, paths, transforms, offsets, offset_transform))
874877

878+
875879
def get_paths_extents(paths, transforms=[]):
876880
"""
877881
Given a sequence of :class:`Path` objects and optional
@@ -887,5 +891,28 @@ def get_paths_extents(paths, transforms=[]):
887891
from transforms import Bbox, Affine2D
888892
if len(paths) == 0:
889893
raise ValueError("No paths provided")
890-
return Bbox.from_extents(*_get_path_collection_extents(
894+
return Bbox.from_extents(*_path.get_path_collection_extents(
891895
Affine2D(), paths, transforms, [], Affine2D()))
896+
897+
898+
def _define_deprecated_functions(ns):
899+
from cbook import deprecated
900+
901+
# The C++ functions are not meant to be used directly.
902+
# Users should use the more pythonic wrappers in the Path
903+
# class instead.
904+
for func, alternative in [
905+
('point_in_path', 'path.Path.contains_point'),
906+
('get_path_extents', 'path.Path.get_extents'),
907+
('point_in_path_collection', 'collection.Collection.contains'),
908+
('path_in_path', 'path.Path.contains_path'),
909+
('path_intersects_path', 'path.Path.intersects_path'),
910+
('convert_path_to_polygons', 'path.Path.to_polygons'),
911+
('cleanup_path', 'path.Path.cleaned'),
912+
('points_in_path', 'path.Path.contains_points'),
913+
('clip_path_to_rect', 'path.Path.clip_to_bbox')]:
914+
ns[func] = deprecated(
915+
since='1.3', alternative=alternative)(getattr(_path, func))
916+
917+
918+
_define_deprecated_functions(locals())

0 commit comments

Comments
 (0)