Skip to content

Commit

Permalink
Move pygmt.show_versions function to _show_versions.py (#3277)
Browse files Browse the repository at this point in the history
  • Loading branch information
weiji14 committed May 29, 2024
1 parent 09e2352 commit a42be05
Show file tree
Hide file tree
Showing 2 changed files with 140 additions and 128 deletions.
129 changes: 1 addition & 128 deletions pygmt/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,10 @@
"""

import atexit as _atexit
import sys
from importlib.metadata import version

# Get semantic version through setuptools-scm
__version__ = f'v{version("pygmt")}' # e.g. v0.1.2.dev3+g0ab3cd78
__commit__ = __version__.split("+g")[-1] if "+g" in __version__ else "" # 0ab3cd78

# Import modules to make the high-level GMT Python API
from pygmt import datasets
from pygmt._show_versions import __commit__, __version__, show_versions
from pygmt.accessors import GMTDataArrayAccessor
from pygmt.figure import Figure, set_display
from pygmt.io import load_dataarray
Expand Down Expand Up @@ -75,125 +70,3 @@
_begin()
# Tell Python to run _end when shutting down
_atexit.register(_end)


def show_versions(file=sys.stdout):
"""
Print various dependency versions which are useful when submitting bug reports.
This includes information about:
- PyGMT itself
- System information (Python version, Operating System)
- Core dependency versions (NumPy, Pandas, Xarray, etc)
- GMT library information
It also warns users if the installed Ghostscript version has serious bugs or is
incompatible with the installed GMT version.
"""

import importlib
import platform
import shutil
import subprocess

from packaging.requirements import Requirement
from packaging.version import Version

def _get_clib_info() -> dict:
"""
Return information about the GMT shared library.
"""
from pygmt.clib import Session

with Session() as ses:
return ses.info

def _get_module_version(modname: str) -> str | None:
"""
Get version information of a Python module.
"""
try:
if modname in sys.modules:
module = sys.modules[modname]
else:
module = importlib.import_module(modname)

try:
return module.__version__
except AttributeError:
return module.version
except ImportError:
return None

def _get_ghostscript_version() -> str | None:
"""
Get Ghostscript version.
"""
match sys.platform:
case "linux" | "darwin":
cmds = ["gs"]
case os_name if os_name.startswith("freebsd"):
cmds = ["gs"]
case "win32":
cmds = ["gswin64c.exe", "gswin32c.exe"]
case _:
return None

for gs_cmd in cmds:
if (gsfullpath := shutil.which(gs_cmd)) is not None:
return subprocess.check_output(
[gsfullpath, "--version"], universal_newlines=True
).strip()
return None

def _check_ghostscript_version(gs_version: str) -> str | None:
"""
Check if the Ghostscript version is compatible with GMT versions.
"""
match Version(gs_version):
case v if v < Version("9.53"):
return (
f"Ghostscript v{gs_version} is too old and may have serious bugs. "
"Please consider upgrading your Ghostscript."
)
case v if Version("10.00") <= v < Version("10.02"):
return (
f"Ghostscript v{gs_version} has known bugs. "
"Please consider upgrading to version v10.02 or later."
)
case v if v >= Version("10.02"):
from pygmt.clib import __gmt_version__

if Version(__gmt_version__) < Version("6.5.0"):
return (
f"GMT v{__gmt_version__} doesn't support Ghostscript "
"v{gs_version}. Please consider upgrading to GMT>=6.5.0 or "
"downgrading to Ghostscript v9.56."
)
return None

sys_info = {
"python": sys.version.replace("\n", " "),
"executable": sys.executable,
"machine": platform.platform(),
}
deps = [Requirement(v).name for v in importlib.metadata.requires("pygmt")]
gs_version = _get_ghostscript_version()

lines = []
lines.append("PyGMT information:")
lines.append(f" version: {__version__}")
lines.append("System information:")
lines.extend([f" {key}: {val}" for key, val in sys_info.items()])
lines.append("Dependency information:")
lines.extend([f" {modname}: {_get_module_version(modname)}" for modname in deps])
lines.append(f" ghostscript: {gs_version}")
lines.append("GMT library information:")
lines.extend([f" {key}: {val}" for key, val in _get_clib_info().items()])

if warnmsg := _check_ghostscript_version(gs_version):
lines.append("WARNING:")
lines.append(f" {warnmsg}")

print("\n".join(lines), file=file)
139 changes: 139 additions & 0 deletions pygmt/_show_versions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
"""
Utility methods to print system info for debugging.
Adapted from :func:`rioxarray.show_versions` and :func:`pandas.show_versions`.
"""

import importlib
import platform
import shutil
import sys
from importlib.metadata import version

# Get semantic version through setuptools-scm
__version__ = f'v{version("pygmt")}' # e.g. v0.1.2.dev3+g0ab3cd78
__commit__ = __version__.split("+g")[-1] if "+g" in __version__ else "" # 0ab3cd78


def _get_clib_info() -> dict:
"""
Return information about the GMT shared library.
"""
from pygmt.clib import Session

with Session() as ses:
return ses.info


def _get_module_version(modname: str) -> str | None:
"""
Get version information of a Python module.
"""
try:
if modname in sys.modules:
module = sys.modules[modname]
else:
module = importlib.import_module(modname)

try:
return module.__version__
except AttributeError:
return module.version
except ImportError:
return None


def _get_ghostscript_version() -> str | None:
"""
Get Ghostscript version.
"""
import subprocess

match sys.platform:
case "linux" | "darwin":
cmds = ["gs"]
case os_name if os_name.startswith("freebsd"):
cmds = ["gs"]
case "win32":
cmds = ["gswin64c.exe", "gswin32c.exe"]
case _:
return None

for gs_cmd in cmds:
if (gsfullpath := shutil.which(gs_cmd)) is not None:
return subprocess.check_output(
[gsfullpath, "--version"], universal_newlines=True
).strip()
return None


def _check_ghostscript_version(gs_version: str) -> str | None:
"""
Check if the Ghostscript version is compatible with GMT versions.
"""
from packaging.version import Version

match Version(gs_version):
case v if v < Version("9.53"):
return (
f"Ghostscript v{gs_version} is too old and may have serious bugs. "
"Please consider upgrading your Ghostscript."
)
case v if Version("10.00") <= v < Version("10.02"):
return (
f"Ghostscript v{gs_version} has known bugs. "
"Please consider upgrading to version v10.02 or later."
)
case v if v >= Version("10.02"):
from pygmt.clib import __gmt_version__

if Version(__gmt_version__) < Version("6.5.0"):
return (
f"GMT v{__gmt_version__} doesn't support Ghostscript "
"v{gs_version}. Please consider upgrading to GMT>=6.5.0 or "
"downgrading to Ghostscript v9.56."
)
return None


def show_versions(file=sys.stdout):
"""
Print various dependency versions which are useful when submitting bug reports.
This includes information about:
- PyGMT itself
- System information (Python version, Operating System)
- Core dependency versions (NumPy, Pandas, Xarray, etc)
- GMT library information
It also warns users if the installed Ghostscript version has serious bugs or is
incompatible with the installed GMT version.
"""

from packaging.requirements import Requirement

sys_info = {
"python": sys.version.replace("\n", " "),
"executable": sys.executable,
"machine": platform.platform(),
}
deps = [Requirement(v).name for v in importlib.metadata.requires("pygmt")]
gs_version = _get_ghostscript_version()

lines = []
lines.append("PyGMT information:")
lines.append(f" version: {__version__}")
lines.append("System information:")
lines.extend([f" {key}: {val}" for key, val in sys_info.items()])
lines.append("Dependency information:")
lines.extend([f" {modname}: {_get_module_version(modname)}" for modname in deps])
lines.append(f" ghostscript: {gs_version}")
lines.append("GMT library information:")
lines.extend([f" {key}: {val}" for key, val in _get_clib_info().items()])

if warnmsg := _check_ghostscript_version(gs_version):
lines.append("WARNING:")
lines.append(f" {warnmsg}")

print("\n".join(lines), file=file)

0 comments on commit a42be05

Please sign in to comment.