Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .github/workflows/cache_data.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ jobs:
with:
name: gmt-cache
path: |
~/.gmt/cache
~/.gmt/server
~/.gmt/gmt_data_server.txt
~/.gmt/gmt_hash_server.txt
~/.gmt/cache
~/.gmt/server
~/.gmt/gmt_data_server.txt
~/.gmt/gmt_hash_server.txt
12 changes: 12 additions & 0 deletions pygmt/datatypes/dataset.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"""

import ctypes as ctp
import warnings
from collections.abc import Mapping
from typing import Any, ClassVar

Expand Down Expand Up @@ -153,6 +154,17 @@ def to_strings(self) -> np.ndarray[Any, np.dtype[np.str_]]:
for segment in table.contents.segment[: table.contents.n_segments]:
if segment.contents.text:
textvector.extend(segment.contents.text[: segment.contents.n_rows])
if None in textvector:
# Workaround for upstream GMT bug reported in
# https://github.com/GenericMappingTools/pygmt/issues/3170.
msg = (
"The trailing text column contains `None' values and has been replace "
"with an empty string to avoid TypeError exceptions. "
"It's likely caused by an upstream GMT API bug. "
"Please consider reporting to us."
)
warnings.warn(msg, category=RuntimeWarning, stacklevel=1)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
warnings.warn(msg, category=RuntimeWarning, stacklevel=1)
warnings.warn(msg, category=RuntimeWarning, stacklevel=2)

Copy link
Member Author

@seisman seisman Apr 16, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

stacklevel=1 makes more sense here.

stacklevel=1:

pygmt/datatypes/dataset.py:166: RuntimeWarning: The trailing text column contains `None' values and has been replace with an empty string to avoid TypeError exceptions. It's likely caused by an upstream GMT API bug. Please consider reporting to us.
  warnings.warn(msg, category=RuntimeWarning, stacklevel=1)

stacklevel=2:

pygmt/clib/session.py:1940: RuntimeWarning: The trailing text column contains `None' values and has been replace with an empty string to avoid TypeError exceptions. It's likely caused by an upstream GMT API bug. Please consider reporting to us.
  return result.to_strings()

textvector = [item if item is not None else b"" for item in textvector]
return np.char.decode(textvector) if textvector else np.array([], dtype=str)

def to_dataframe(
Expand Down
26 changes: 26 additions & 0 deletions pygmt/tests/test_datatypes_dataset.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

import pandas as pd
import pytest
from pygmt import which
from pygmt.clib import Session
from pygmt.helpers import GMTTempFile

Expand Down Expand Up @@ -81,3 +82,28 @@ def test_dataset_empty():
assert df.empty # Empty DataFrame
expected_df = dataframe_from_pandas(tmpfile.name)
pd.testing.assert_frame_equal(df, expected_df)


def test_dataset_to_strings_with_none_values():
"""
Test that None values in the trailing text doesn't raise an excetion.

Due to a likely upstream bug, the trailing texts sometimes can be ``None'' when
downloading tiled grids. The temporary workaround is to replace any None values with
an empty string.

See the bug report at https://github.com/GenericMappingTools/pygmt/issues/3170.
"""
tiles = ["@N30W120.earth_relief_15s_p.nc", "@N00E000.earth_relief_15s_p.nc"]
paths = which(fname=tiles, download="a")
assert len(paths) == 2
# 'paths' may contain an empty string or not, depending on if the tiles are cached.
if "" not in paths: # Contains two valid paths.
# Delete the cached tiles and try again.
for path in paths:
Path(path).unlink()
with pytest.warns(expected_warning=RuntimeWarning) as record:
paths = which(fname=tiles, download="a")
assert len(record) == 1
assert len(paths) == 2
assert "" in paths