Skip to content

Commit

Permalink
Add support for passing pathlib.Path objects as filenames (GenericMap…
Browse files Browse the repository at this point in the history
…pingTools#1382)

Co-authored-by: Dongdong Tian <[email protected]>
Co-authored-by: Wei Ji <[email protected]>
  • Loading branch information
3 people authored and Josh Sixsmith committed Dec 21, 2022
1 parent 09a07ef commit 3c630f6
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 8 deletions.
12 changes: 8 additions & 4 deletions pygmt/clib/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -1376,9 +1376,10 @@ def virtualfile_from_data(
check_kind : str
Used to validate the type of data that can be passed in. Choose
from 'raster', 'vector' or None. Default is None (no validation).
data : str or xarray.DataArray or {table-like} or None
Any raster or vector data format. This could be a file name, a
raster grid, a vector matrix/arrays, or other supported data input.
data : str or pathlib.Path or xarray.DataArray or {table-like} or None
Any raster or vector data format. This could be a file name or
path, a raster grid, a vector matrix/arrays, or other supported
data input.
x/y/z : 1d arrays or None
x, y and z columns as numpy arrays.
extra_arrays : list of 1d arrays
Expand Down Expand Up @@ -1439,8 +1440,11 @@ def virtualfile_from_data(
}[kind]

# Ensure the data is an iterable (Python list or tuple)
if kind in ("file", "geojson", "grid"):
if kind in ("geojson", "grid"):
_data = (data,)
elif kind == "file":
# Useful to handle `pathlib.Path` and string file path alike
_data = (str(data),)
elif kind == "vectors":
_data = [np.atleast_1d(x), np.atleast_1d(y)]
if z is not None:
Expand Down
13 changes: 9 additions & 4 deletions pygmt/helpers/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
Utilities and common tasks for wrapping the GMT modules.
"""
import os
import pathlib
import shutil
import subprocess
import sys
Expand All @@ -21,6 +22,7 @@ def data_kind(data, x=None, y=None, z=None):
Possible types:
* a file name provided as 'data'
* a pathlib.Path provided as 'data'
* an xarray.DataArray provided as 'data'
* a matrix provided as 'data'
* 1D arrays x and y (and z, optionally)
Expand All @@ -30,9 +32,9 @@ def data_kind(data, x=None, y=None, z=None):
Parameters
----------
data : str or xarray.DataArray or {table-like} or None
Pass in either a file name to an ASCII data table, an
:class:`xarray.DataArray`, a 1D/2D
data : str or pathlib.Path or xarray.DataArray or {table-like} or None
Pass in either a file name or :class:`pathlib.Path` to an ASCII data
table, an :class:`xarray.DataArray`, a 1D/2D
{table-classes}.
x/y : 1d arrays or None
x and y columns as numpy arrays.
Expand All @@ -50,12 +52,15 @@ def data_kind(data, x=None, y=None, z=None):
>>> import numpy as np
>>> import xarray as xr
>>> import pathlib
>>> data_kind(data=None, x=np.array([1, 2, 3]), y=np.array([4, 5, 6]))
'vectors'
>>> data_kind(data=np.arange(10).reshape((5, 2)), x=None, y=None)
'matrix'
>>> data_kind(data="my-data-file.txt", x=None, y=None)
'file'
>>> data_kind(data=pathlib.Path("my-data-file.txt"), x=None, y=None)
'file'
>>> data_kind(data=xr.DataArray(np.random.rand(4, 3)))
'grid'
"""
Expand All @@ -66,7 +71,7 @@ def data_kind(data, x=None, y=None, z=None):
if data is None and (x is None or y is None):
raise GMTInvalidInput("Must provided both x and y.")

if isinstance(data, str):
if isinstance(data, (str, pathlib.PurePath)):
kind = "file"
elif isinstance(data, xr.DataArray):
kind = "grid"
Expand Down
36 changes: 36 additions & 0 deletions pygmt/tests/test_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
Tests for gmtinfo.
"""
import os
import pathlib
import sys

import numpy as np
import numpy.testing as npt
Expand Down Expand Up @@ -29,6 +31,40 @@ def test_info():
assert output == expected_output


@pytest.mark.parametrize(
"table",
[
pathlib.Path(POINTS_DATA),
pytest.param(
pathlib.PureWindowsPath(POINTS_DATA),
marks=pytest.mark.skipif(
sys.platform != "win32",
reason="PureWindowsPath is only available on Windows",
),
),
pytest.param(
pathlib.PurePosixPath(POINTS_DATA),
marks=pytest.mark.skipif(
sys.platform == "win32",
reason="PurePosixPath is not available on Windows",
),
),
],
)
def test_info_path(table):
"""
Make sure info works on a pathlib.Path input.
"""
output = info(table=table)
expected_output = (
f"{POINTS_DATA}: N = 20 "
"<11.5309/61.7074> "
"<-2.9289/7.8648> "
"<0.1412/0.9338>\n"
)
assert output == expected_output


def test_info_2d_list():
"""
Make sure info works on a 2d list.
Expand Down

0 comments on commit 3c630f6

Please sign in to comment.