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

Skip to content

Commit d7ba944

Browse files
authored
Merge pull request #15233 from anntzer/ps
backend_ps cleanup.
2 parents 001dd9b + 43de13f commit d7ba944

File tree

2 files changed

+54
-104
lines changed

2 files changed

+54
-104
lines changed

doc/api/next_api_changes/behaviour.rst

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,3 +106,14 @@ multiple plot calls.
106106
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
107107
It previously raised `TypeError`, **except** when the input was of the form
108108
``b"C[number]"`` in which case it raised a ValueError.
109+
110+
`.FigureCanvasPS.print_ps` and `.FigureCanvasPS.print_eps` no longer apply edgecolor and facecolor
111+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
112+
113+
These methods now assume that the figure edge and facecolor have been correctly
114+
applied by `.FigureCanvasBase.print_figure`, as they are normally called
115+
through it.
116+
117+
This behavior is consistent with other figure saving methods
118+
(`.FigureCanvasAgg.print_png`, `.FigureCanvasPdf.print_pdf`,
119+
`.FigureCanvasSVG.print_svg`).

lib/matplotlib/backends/backend_ps.py

Lines changed: 43 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -764,10 +764,30 @@ def print_ps(self, outfile, *args, **kwargs):
764764
def print_eps(self, outfile, *args, **kwargs):
765765
return self._print_ps(outfile, 'eps', *args, **kwargs)
766766

767-
def _print_ps(self, outfile, format, *args,
768-
papertype=None, dpi=72, facecolor='w', edgecolor='w',
769-
orientation='portrait',
770-
**kwargs):
767+
def _print_ps(
768+
self, outfile, format, *args,
769+
dpi=72, metadata=None, papertype=None, orientation='portrait',
770+
**kwargs):
771+
772+
self.figure.set_dpi(72) # Override the dpi kwarg
773+
774+
dsc_comments = {}
775+
if isinstance(outfile, (str, os.PathLike)):
776+
dsc_comments["Title"] = \
777+
os.fspath(outfile).encode("ascii", "replace").decode("ascii")
778+
dsc_comments["Creator"] = (metadata or {}).get(
779+
"Creator",
780+
f"matplotlib version {mpl.__version__}, http://matplotlib.org/")
781+
# See https://reproducible-builds.org/specs/source-date-epoch/
782+
source_date_epoch = os.getenv("SOURCE_DATE_EPOCH")
783+
dsc_comments["CreationDate"] = (
784+
datetime.datetime.utcfromtimestamp(
785+
int(source_date_epoch)).strftime("%a %b %d %H:%M:%S %Y")
786+
if source_date_epoch
787+
else time.ctime())
788+
dsc_comments = "\n".join(
789+
f"%%{k}: {v}" for k, v in dsc_comments.items())
790+
771791
if papertype is None:
772792
papertype = mpl.rcParams['ps.papersize']
773793
papertype = papertype.lower()
@@ -776,42 +796,29 @@ def _print_ps(self, outfile, format, *args,
776796
orientation = cbook._check_getitem(
777797
_Orientation, orientation=orientation.lower())
778798

779-
self.figure.set_dpi(72) # Override the dpi kwarg
780-
781799
printer = (self._print_figure_tex
782800
if mpl.rcParams['text.usetex'] else
783801
self._print_figure)
784-
printer(outfile, format, dpi, facecolor, edgecolor,
785-
orientation, papertype, **kwargs)
802+
printer(outfile, format, dpi=dpi, dsc_comments=dsc_comments,
803+
orientation=orientation, papertype=papertype, **kwargs)
786804

787805
@cbook._delete_parameter("3.2", "dryrun")
788806
def _print_figure(
789-
self, outfile, format, dpi, facecolor, edgecolor,
790-
orientation, papertype, *,
791-
metadata=None, dryrun=False, bbox_inches_restore=None, **kwargs):
807+
self, outfile, format, *,
808+
dpi, dsc_comments, orientation, papertype,
809+
dryrun=False, bbox_inches_restore=None, **kwargs):
792810
"""
793-
Render the figure to hardcopy. Set the figure patch face and
794-
edge colors. This is useful because some of the GUIs have a
795-
gray figure face color background and you'll probably want to
796-
override this on hardcopy
797-
798-
If outfile is a string, it is interpreted as a file name.
799-
If the extension matches .ep* write encapsulated postscript,
800-
otherwise write a stand-alone PostScript file.
801-
802-
If outfile is a file object, a stand-alone PostScript file is
803-
written into this file object.
811+
Render the figure to a filesystem path or a file-like object.
804812
805-
metadata must be a dictionary. Currently, only the value for
806-
the key 'Creator' is used.
813+
Parameters are as for `.print_figure`, except that *dsc_comments* is a
814+
all string containing Document Structuring Convention comments,
815+
generated from the *metadata* parameter to `.print_figure`.
807816
"""
808817
is_eps = format == 'eps'
809818
if isinstance(outfile, (str, os.PathLike)):
810-
outfile = title = os.fspath(outfile)
811-
title = title.encode("ascii", "replace").decode("ascii")
819+
outfile = os.fspath(outfile)
812820
passed_in_file_object = False
813821
elif is_writable_file_like(outfile):
814-
title = None
815822
passed_in_file_object = True
816823
else:
817824
raise ValueError("outfile must be a path or a file-like object")
@@ -848,12 +855,6 @@ def _print_figure(
848855
rotation = 90
849856
bbox = (llx, lly, urx, ury)
850857

851-
# generate PostScript code for the figure and store it in a string
852-
origfacecolor = self.figure.get_facecolor()
853-
origedgecolor = self.figure.get_edgecolor()
854-
self.figure.set_facecolor(facecolor)
855-
self.figure.set_edgecolor(edgecolor)
856-
857858
if dryrun:
858859
class NullWriter:
859860
def write(self, *args, **kwargs):
@@ -874,16 +875,6 @@ def write(self, *args, **kwargs):
874875
if dryrun: # return immediately if dryrun (tightbbox=True)
875876
return
876877

877-
self.figure.set_facecolor(origfacecolor)
878-
self.figure.set_edgecolor(origedgecolor)
879-
880-
# check for custom metadata
881-
if metadata is not None and 'Creator' in metadata:
882-
creator_str = metadata['Creator']
883-
else:
884-
creator_str = \
885-
f"matplotlib version {mpl.__version__}, http://matplotlib.org/"
886-
887878
def print_figure_impl(fh):
888879
# write the PostScript headers
889880
if is_eps:
@@ -893,18 +884,7 @@ def print_figure_impl(fh):
893884
f"%%DocumentPaperSizes: {papertype}\n"
894885
f"%%Pages: 1\n",
895886
end="", file=fh)
896-
if title:
897-
print("%%Title: " + title, file=fh)
898-
# get source date from SOURCE_DATE_EPOCH, if set
899-
# See https://reproducible-builds.org/specs/source-date-epoch/
900-
source_date_epoch = os.getenv("SOURCE_DATE_EPOCH")
901-
if source_date_epoch:
902-
source_date = datetime.datetime.utcfromtimestamp(
903-
int(source_date_epoch)).strftime("%a %b %d %H:%M:%S %Y")
904-
else:
905-
source_date = time.ctime()
906-
print(f"%%Creator: {creator_str}\n"
907-
f"%%CreationDate: {source_date}\n"
887+
print(f"{dsc_comments}\n"
908888
f"%%Orientation: {orientation.name}\n"
909889
f"%%BoundingBox: {bbox[0]} {bbox[1]} {bbox[2]} {bbox[3]}\n"
910890
f"%%EndComments\n",
@@ -1005,28 +985,18 @@ def print_figure_impl(fh):
1005985

1006986
@cbook._delete_parameter("3.2", "dryrun")
1007987
def _print_figure_tex(
1008-
self, outfile, format, dpi, facecolor, edgecolor,
1009-
orientation, papertype, *,
1010-
metadata=None, dryrun=False, bbox_inches_restore=None, **kwargs):
988+
self, outfile, format, *,
989+
dpi, dsc_comments, orientation, papertype,
990+
dryrun=False, bbox_inches_restore=None, **kwargs):
1011991
"""
1012-
If text.usetex is True in rc, a temporary pair of tex/eps files
992+
If :rc:`text.usetex` is True, a temporary pair of tex/eps files
1013993
are created to allow tex to manage the text layout via the PSFrags
1014994
package. These files are processed to yield the final ps or eps file.
1015995
1016-
metadata must be a dictionary. Currently, only the value for
1017-
the key 'Creator' is used.
996+
The rest of the behavior is as for `._print_figure`.
1018997
"""
1019998
is_eps = format == 'eps'
1020-
if is_writable_file_like(outfile):
1021-
title = None
1022-
else:
1023-
try:
1024-
title = os.fspath(outfile)
1025-
except TypeError as err:
1026-
raise ValueError(
1027-
"outfile must be a path or a file-like object") from err
1028999

1029-
self.figure.dpi = 72 # ignore the dpi kwarg
10301000
width, height = self.figure.get_size_inches()
10311001
xo = 0
10321002
yo = 0
@@ -1038,12 +1008,6 @@ def _print_figure_tex(
10381008
ury = lly + h
10391009
bbox = (llx, lly, urx, ury)
10401010

1041-
# generate PostScript code for the figure and store it in a string
1042-
origfacecolor = self.figure.get_facecolor()
1043-
origedgecolor = self.figure.get_edgecolor()
1044-
self.figure.set_facecolor(facecolor)
1045-
self.figure.set_edgecolor(edgecolor)
1046-
10471011
if dryrun:
10481012
class NullWriter:
10491013
def write(self, *args, **kwargs):
@@ -1064,35 +1028,13 @@ def write(self, *args, **kwargs):
10641028
if dryrun: # return immediately if dryrun (tightbbox=True)
10651029
return
10661030

1067-
self.figure.set_facecolor(origfacecolor)
1068-
self.figure.set_edgecolor(origedgecolor)
1069-
1070-
# check for custom metadata
1071-
if metadata is not None and 'Creator' in metadata:
1072-
creator_str = metadata['Creator']
1073-
else:
1074-
creator_str = \
1075-
f"matplotlib version {mpl.__version__}, http://matplotlib.org/"
1076-
10771031
# write to a temp file, we'll move it to outfile when done
1078-
10791032
with TemporaryDirectory() as tmpdir:
10801033
tmpfile = os.path.join(tmpdir, "tmp.ps")
1081-
# get source date from SOURCE_DATE_EPOCH, if set
1082-
# See https://reproducible-builds.org/specs/source-date-epoch/
1083-
source_date_epoch = os.getenv("SOURCE_DATE_EPOCH")
1084-
if source_date_epoch:
1085-
source_date = datetime.datetime.utcfromtimestamp(
1086-
int(source_date_epoch)).strftime("%a %b %d %H:%M:%S %Y")
1087-
else:
1088-
source_date = time.ctime()
10891034
pathlib.Path(tmpfile).write_text(
10901035
f"""\
10911036
%!PS-Adobe-3.0 EPSF-3.0
1092-
{f'''%%Title: {title}
1093-
''' if title else ""}\
1094-
%%Creator: {creator_str}
1095-
%%CreationDate: {source_date}
1037+
{dsc_comments}
10961038
%%BoundingBox: {bbox[0]} {bbox[1]} {bbox[2]} {bbox[3]}
10971039
%%EndComments
10981040
%%BeginProlog
@@ -1121,12 +1063,9 @@ def write(self, *args, **kwargs):
11211063
paper_width, paper_height = orientation.swap_if_landscape(
11221064
self.figure.get_size_inches())
11231065
else:
1124-
temp_papertype = _get_papertype(width, height)
11251066
if papertype == 'auto':
1126-
papertype = temp_papertype
1127-
paper_width, paper_height = papersize[temp_papertype]
1128-
else:
1129-
paper_width, paper_height = papersize[papertype]
1067+
papertype = _get_papertype(width, height)
1068+
paper_width, paper_height = papersize[papertype]
11301069

11311070
texmanager = ps_renderer.get_texmanager()
11321071
font_preamble = texmanager.get_font_preamble()

0 commit comments

Comments
 (0)