Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for passing pathlib.Path objects as filenames #1382

Merged
merged 9 commits into from
Sep 13, 2021
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
seisman marked this conversation as resolved.
Show resolved Hide resolved
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