Repository: GenericMappingTools/pygmt

Issue:
Figure.savefig should support postscript format
**Description of the problem**

Screen Errors when I try a fig.savefig when using filenames with a ".ps" extension  ; same savefig works fine with 'eps' extension or 'png' extension


**Full code that generated the error**

```python

#!/usr/bin/python3
import pygmt
fig = pygmt.Figure()
region = [176.5, 178.7, -39.8, -38.05]
print(region)
fig.basemap(region=region, projection="M4i", frame=True)
fig.coast(land="grey", water="azure1",shorelines=True)
fig.savefig("trythis_pygmt_map.ps")

```

**Full error message**

```
(pygmt) [stephen@akatea autogps]$ python example.py
[176.5, 178.7, -39.8, -38.05]
Traceback (most recent call last):
  File "example.py", line 11, in <module>
    fig.savefig("trythis_pygmt_map.ps")
  File "/sp/prj/tvz95/mypython8_pip_python3p6_pygmt/pygmt/figure.py", line 211, in savefig
    raise GMTInvalidInput("Unknown extension '.{}'".format(ext))
pygmt.exceptions.GMTInvalidInput: Unknown extension '.ps'

```

**System information**

* Operating system:  Linux
* Python installation (Anaconda, system, ETS): Anaconda 
* Version of GMT:  6.0
* Version of Python:  3.6
* Version of this package: 

"date": "2019-03-25T11:59:11-1000",
 "full-revisionid": "5b8c6590ea7031c4e2a708d0dd94c1ec363bc198",
 "version": "0.0.1a0+25.g5b8c659"



* If using conda, paste the output of `conda list` below:

<details>
<summary>output of conda list</summary>
<pre>
#
# Name                    Version                   Build  Channel
asn1crypto                0.24.0                py36_1003    conda-forge
basemap                   1.2.0            py36h673bf1a_2    conda-forge
ca-certificates           2019.3.9             hecc5488_0    conda-forge
certifi                   2019.3.9                 py36_0    conda-forge
cffi                      1.12.2           py36hf0e25f4_1    conda-forge
chardet                   3.0.4                 py36_1003    conda-forge
cryptography              2.6.1            py36h72c5cf5_0    conda-forge
cycler                    0.10.0                     py_1    conda-forge
dbus                      1.13.2               h714fa37_1  
decorator                 4.4.0                      py_0    conda-forge
expat                     2.2.5             hf484d3e_1002    conda-forge
fontconfig                2.13.1            he4413a7_1000    conda-forge
freetype                  2.10.0               he983fc9_0    conda-forge
future                    0.17.1                py36_1000    conda-forge
geos                      3.7.1             hf484d3e_1000    conda-forge
gettext                   0.19.8.1          hc5be6a0_1002    conda-forge
glib                      2.56.2            had28632_1001    conda-forge
gst-plugins-base          1.14.0               hbbd80ab_1  
gstreamer                 1.14.0               hb453b48_1  
icu                       58.2              hf484d3e_1000    conda-forge
idna                      2.8                   py36_1000    conda-forge
jpeg                      9c                h14c3975_1001    conda-forge
kiwisolver                1.0.1           py36h6bb024c_1002    conda-forge
libblas                   3.8.0                4_openblas    conda-forge
libcblas                  3.8.0                4_openblas    conda-forge
libffi                    3.2.1             he1b5a44_1006    conda-forge
libgcc-ng                 8.2.0                hdf63c60_1  
libgfortran               3.0.0                         1    conda-forge
libgfortran-ng            7.3.0                hdf63c60_0  
libiconv                  1.15              h516909a_1005    conda-forge
liblapack                 3.8.0                4_openblas    conda-forge
libpng                    1.6.36            h84994c4_1000    conda-forge
libstdcxx-ng              8.2.0                hdf63c60_1  
libtiff                   4.0.10            h648cc4a_1001    conda-forge
libuuid                   2.32.1            h14c3975_1000    conda-forge
libxcb                    1.13              h14c3975_1002    conda-forge
libxml2                   2.9.8             h143f9aa_1005    conda-forge
libxslt                   1.1.32            h4785a14_1002    conda-forge
lxml                      4.3.3            py36h7ec2d77_0    conda-forge
matplotlib                3.0.3                    py36_0    conda-forge
matplotlib-base           3.0.3            py36h167e16e_0    conda-forge
ncurses                   6.1               hf484d3e_1002    conda-forge
numpy                     1.16.2           py36h8b7e671_1    conda-forge
obspy                     1.1.1            py36h3010b51_0    conda-forge
olefile                   0.46                       py_0    conda-forge
openblas                  0.3.5                ha44fe06_0    conda-forge
openssl                   1.1.1b               h14c3975_1    conda-forge
packaging                 19.0                       py_0    conda-forge
pandas                    0.24.2           py36hf484d3e_0    conda-forge
pcre                      8.43                 he6710b0_0  
pillow                    6.0.0            py36he7afcd5_0    conda-forge
pip                       19.0.3                   py36_0    conda-forge
proj4                     4.9.3                h470a237_8    conda-forge
pthread-stubs             0.4               h14c3975_1001    conda-forge
pycparser                 2.19                     py36_1    conda-forge
pyopenssl                 19.0.0                   py36_0    conda-forge
pyparsing                 2.3.1                      py_0    conda-forge
pypdf2                    1.26.0                     py_2    conda-forge
pyproj                    1.9.5.1         py36h2944ce7_1006    conda-forge
pyqt                      5.6.0           py36h13b7fb3_1008    conda-forge
pyshp                     2.1.0                      py_0    conda-forge
pysocks                   1.6.8                 py36_1002    conda-forge
python                    3.6.7             h381d211_1004    conda-forge
python-dateutil           2.8.0                      py_0    conda-forge
pytz                      2018.9                     py_0    conda-forge
qt                        5.6.3                h8bf5577_3  
readline                  7.0               hf8c457e_1001    conda-forge
reportlab                 3.5.17           py36h7d98c4e_0    conda-forge
requests                  2.21.0                py36_1000    conda-forge
scipy                     1.2.1            py36h09a28d5_1    conda-forge
setuptools                40.8.0                   py36_0    conda-forge
sip                       4.18.1          py36hf484d3e_1000    conda-forge
six                       1.12.0                py36_1000    conda-forge
sqlalchemy                1.3.2            py36h516909a_0    conda-forge
sqlite                    3.26.0            h67949de_1001    conda-forge
tk                        8.6.9             h84994c4_1001    conda-forge
tornado                   6.0.2            py36h516909a_0    conda-forge
urllib3                   1.24.1                py36_1000    conda-forge
wheel                     0.33.1                   py36_0    conda-forge
xarray                    0.12.0                     py_0    conda-forge
xorg-libxau               1.0.9                h14c3975_0    conda-forge
xorg-libxdmcp             1.1.3                h516909a_0    conda-forge
xz                        5.2.4             h14c3975_1001    conda-forge
zlib                      1.2.11            h14c3975_1004    conda-forge
</pre>
</details>


Discussion:

Patch:
diff --git a/pygmt/figure.py b/pygmt/figure.py
index e2b9089c..043f5617 100644
--- a/pygmt/figure.py
+++ b/pygmt/figure.py
@@ -237,12 +237,17 @@ class Figure:
         prefix, ext = os.path.splitext(fname)
         ext = ext[1:]  # Remove the .
         if ext not in fmts:
-            raise GMTInvalidInput("Unknown extension '.{}'".format(ext))
+            if ext == "ps":
+                raise GMTInvalidInput(
+                    "Extension '.ps' is not supported. "
+                    "Please use '.eps' or '.pdf' instead."
+                )
+            raise GMTInvalidInput(f"Unknown extension '.{ext}'.")
         fmt = fmts[ext]
         if transparent:
             if fmt != "g":
                 raise GMTInvalidInput(
-                    "Transparency unavailable for '{}', only for png.".format(ext)
+                    f"Transparency unavailable for '{ext}', only for png."
                 )
             fmt = fmt.upper()
         if anti_alias:


Test patch:
diff --git a/pygmt/tests/test_figure.py b/pygmt/tests/test_figure.py
index 213c0048..ba43b0b6 100644
--- a/pygmt/tests/test_figure.py
+++ b/pygmt/tests/test_figure.py
@@ -74,7 +74,18 @@ def test_figure_savefig_unknown_extension():
     prefix = "test_figure_savefig_unknown_extension"
     fmt = "test"
     fname = ".".join([prefix, fmt])
-    with pytest.raises(GMTInvalidInput):
+    with pytest.raises(GMTInvalidInput, match="Unknown extension '.test'."):
+        fig.savefig(fname)
+
+
+def test_figure_savefig_ps_extension():
+    """
+    Check that an error is raised when .ps extension is specified.
+    """
+    fig = Figure()
+    fig.basemap(region="10/70/-300/800", projection="X3c/5c", frame="af")
+    fname = "test_figure_savefig_ps_extension.ps"
+    with pytest.raises(GMTInvalidInput, match="Extension '.ps' is not supported."):
         fig.savefig(fname)