diff --git a/.gitignore b/.gitignore index caafad79432..ae67eb868d5 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ *~ *.so *.pyd +.pytest_cache/ build/ dist/ .*.swp diff --git a/gmt/__init__.py b/gmt/__init__.py index d3169d25243..7d70d270e0b 100644 --- a/gmt/__init__.py +++ b/gmt/__init__.py @@ -17,7 +17,7 @@ # Import modules to make the high-level GMT Python API from .session_management import begin as _begin, end as _end from .figure import Figure -from .modules import info +from .modules import info, which # Get the version number through versioneer diff --git a/gmt/modules.py b/gmt/modules.py index ca6fbfd8c01..7f48a50528f 100644 --- a/gmt/modules.py +++ b/gmt/modules.py @@ -2,7 +2,7 @@ Non-plot GMT modules. """ from .clib import LibGMT -from .helpers import build_arg_string, fmt_docstring, GMTTempFile +from .helpers import build_arg_string, fmt_docstring, GMTTempFile, use_alias @fmt_docstring @@ -25,3 +25,55 @@ def info(fname, **kwargs): with LibGMT() as lib: lib.call_module('info', arg_str) return tmpfile.read() + + +@fmt_docstring +@use_alias(G='download') +def which(fname, **kwargs): + """ + Find the full path to specified files. + + Reports the full paths to the files given through *fname*. We look for + the file in (1) the current directory, (2) in $GMT_USERDIR (if defined), + (3) in $GMT_DATADIR (if defined), or (4) in $GMT_CACHEDIR (if defined). + + *fname* can also be a downloadable file (either a full URL, a + `@file` special file for downloading from the GMT Site Cache, or + `@earth_relief_*` topography grids). In these cases, use option *download* + to set the desired behavior. If *download* is not used (or False), the file + will not be found. + + {gmt_module_docs} + + {aliases} + + Parameters + ---------- + fname : str + The file name that you want to check. + G : bool or str + If the file is downloadable and not found, we will try to download the + it. Use True or 'l' (default) to download to the current directory. Use + 'c' to place in the user cache directory or 'u' user data directory + instead. + + Returns + ------- + path : str + The path of the file, depending on the options used. + + Raises + ------ + FileNotFoundError + If the file is not found. + + """ + with GMTTempFile() as tmpfile: + arg_str = ' '.join([fname, build_arg_string(kwargs), + "->" + tmpfile.name]) + with LibGMT() as lib: + lib.call_module('which', arg_str) + path = tmpfile.read().strip() + if not path: + raise FileNotFoundError("File '{}' not found.".format(fname)) + return path diff --git a/gmt/tests/test_which.py b/gmt/tests/test_which.py new file mode 100644 index 00000000000..80c6a91d212 --- /dev/null +++ b/gmt/tests/test_which.py @@ -0,0 +1,24 @@ +""" +Tests for gmt.which +""" +import os + +import pytest + +from .. import which +from ..helpers import unique_name + + +def test_which(): + "Make sure which returns file paths for @files correctly without errors" + for fname in 'tut_quakes.ngdc tut_bathy.nc'.split(): + cached_file = which('@{}'.format(fname), download='c') + assert os.path.exists(cached_file) + assert os.path.basename(cached_file) == fname + + +def test_which_fails(): + "which should fail with a FileNotFoundError" + bogus_file = unique_name() + with pytest.raises(FileNotFoundError): + which(bogus_file)