Skip to content

Commit e02e501

Browse files
authored
pygmt.show_versions: Warn about incompatible ghostscript versions (#3244)
1 parent 8926fde commit e02e501

File tree

1 file changed

+68
-24
lines changed

1 file changed

+68
-24
lines changed

pygmt/__init__.py

Lines changed: 68 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,9 @@ def show_versions(file=sys.stdout):
102102
- System information (Python version, Operating System)
103103
- Core dependency versions (NumPy, Pandas, Xarray, etc)
104104
- GMT library information
105+
106+
It also warns users if the installed Ghostscript version has serious bugs or is
107+
incompatible with the installed GMT version.
105108
"""
106109

107110
import importlib
@@ -110,8 +113,18 @@ def show_versions(file=sys.stdout):
110113
import subprocess
111114

112115
from packaging.requirements import Requirement
116+
from packaging.version import Version
117+
118+
def _get_clib_info() -> dict:
119+
"""
120+
Return information about the GMT shared library.
121+
"""
122+
from pygmt.clib import Session
113123

114-
def _get_module_version(modname):
124+
with Session() as ses:
125+
return ses.info
126+
127+
def _get_module_version(modname: str) -> str | None:
115128
"""
116129
Get version information of a Python module.
117130
"""
@@ -128,17 +141,19 @@ def _get_module_version(modname):
128141
except ImportError:
129142
return None
130143

131-
def _get_ghostscript_version():
144+
def _get_ghostscript_version() -> str | None:
132145
"""
133-
Get ghostscript version.
146+
Get Ghostscript version.
134147
"""
135-
os_name = sys.platform
136-
if os_name.startswith(("linux", "freebsd", "darwin")):
137-
cmds = ["gs"]
138-
elif os_name == "win32":
139-
cmds = ["gswin64c.exe", "gswin32c.exe"]
140-
else:
141-
return None
148+
match sys.platform:
149+
case "linux" | "darwin":
150+
cmds = ["gs"]
151+
case os_name if os_name.startswith("freebsd"):
152+
cmds = ["gs"]
153+
case "win32":
154+
cmds = ["gswin64c.exe", "gswin32c.exe"]
155+
case _:
156+
return None
142157

143158
for gs_cmd in cmds:
144159
if (gsfullpath := shutil.which(gs_cmd)) is not None:
@@ -147,24 +162,53 @@ def _get_ghostscript_version():
147162
).strip()
148163
return None
149164

165+
def _check_ghostscript_version(gs_version: str) -> str | None:
166+
"""
167+
Check if the Ghostscript version is compatible with GMT versions.
168+
"""
169+
match Version(gs_version):
170+
case v if v < Version("9.53"):
171+
return (
172+
f"Ghostscript v{gs_version} is too old and may have serious bugs. "
173+
"Please consider upgrading your Ghostscript."
174+
)
175+
case v if Version("10.00") <= v < Version("10.02"):
176+
return (
177+
f"Ghostscript v{gs_version} has known bugs. "
178+
"Please consider upgrading to version v10.02 or later."
179+
)
180+
case v if v >= Version("10.02"):
181+
from pygmt.clib import __gmt_version__
182+
183+
if Version(__gmt_version__) < Version("6.5.0"):
184+
return (
185+
f"GMT v{__gmt_version__} doesn't support Ghostscript "
186+
"v{gs_version}. Please consider upgrading to GMT>=6.5.0 or "
187+
"downgrading to Ghostscript v9.56."
188+
)
189+
return None
190+
150191
sys_info = {
151192
"python": sys.version.replace("\n", " "),
152193
"executable": sys.executable,
153194
"machine": platform.platform(),
154195
}
155-
156196
deps = [Requirement(v).name for v in importlib.metadata.requires("pygmt")]
197+
gs_version = _get_ghostscript_version()
198+
199+
lines = []
200+
lines.append("PyGMT information:")
201+
lines.append(f" version: {__version__}")
202+
lines.append("System information:")
203+
lines.extend([f" {key}: {val}" for key, val in sys_info.items()])
204+
lines.append("Dependency information:")
205+
lines.extend([f" {modname}: {_get_module_version(modname)}" for modname in deps])
206+
lines.append(f" ghostscript: {gs_version}")
207+
lines.append("GMT library information:")
208+
lines.extend([f" {key}: {val}" for key, val in _get_clib_info().items()])
209+
210+
if warnmsg := _check_ghostscript_version(gs_version):
211+
lines.append("WARNING:")
212+
lines.append(f" {warnmsg}")
157213

158-
print("PyGMT information:", file=file)
159-
print(f" version: {__version__}", file=file)
160-
161-
print("System information:", file=file)
162-
for key, val in sys_info.items():
163-
print(f" {key}: {val}", file=file)
164-
165-
print("Dependency information:", file=file)
166-
for modname in deps:
167-
print(f" {modname}: {_get_module_version(modname)}", file=file)
168-
print(f" ghostscript: {_get_ghostscript_version()}", file=file)
169-
170-
print_clib_info(file=file)
214+
print("\n".join(lines), file=file)

0 commit comments

Comments
 (0)