diff --git a/doc/whats-new.rst b/doc/whats-new.rst index df2afdd9c4d..516c4b5772f 100644 --- a/doc/whats-new.rst +++ b/doc/whats-new.rst @@ -80,6 +80,9 @@ Bug fixes By `Jimmy Westling `_. - Numbers are properly formatted in a plot's title (:issue:`5788`, :pull:`5789`). By `Maxime Liquet `_. +- With backends, check for path-like objects rather than ``pathlib.Path`` + type, use ``os.fspath`` (:pull:`5879`). + By `Mike Taves `_. - ``open_mfdataset()`` now accepts a single ``pathlib.Path`` object (:issue: `5881`). By `Panos Mavrogiorgos `_. diff --git a/xarray/backends/api.py b/xarray/backends/api.py index 0cde8ab7315..0ca82555c8f 100644 --- a/xarray/backends/api.py +++ b/xarray/backends/api.py @@ -2,7 +2,6 @@ from glob import glob from io import BytesIO from numbers import Number -from pathlib import Path from typing import ( TYPE_CHECKING, Callable, @@ -808,7 +807,7 @@ def open_mfdataset( - "override": if indexes are of same size, rewrite indexes to be those of the first object with that dimension. Indexes for the same dimension must have the same size in all objects. - attrs_file : str or pathlib.Path, optional + attrs_file : str or path-like, optional Path of the file used to read global attributes from. By default global attributes are read from the first file provided, with wildcard matches sorted by filename. @@ -868,7 +867,7 @@ def open_mfdataset( elif isinstance(paths, os.PathLike): paths = [os.fspath(paths)] else: - paths = [str(p) if isinstance(p, Path) else p for p in paths] + paths = [os.fspath(p) if isinstance(p, os.PathLike) else p for p in paths] if not paths: raise OSError("no files to open") @@ -960,8 +959,8 @@ def multi_file_closer(): # read global attributes from the attrs_file or from the first dataset if attrs_file is not None: - if isinstance(attrs_file, Path): - attrs_file = str(attrs_file) + if isinstance(attrs_file, os.PathLike): + attrs_file = os.fspath(attrs_file) combined.attrs = datasets[paths.index(attrs_file)].attrs return combined @@ -994,8 +993,8 @@ def to_netcdf( The ``multifile`` argument is only for the private use of save_mfdataset. """ - if isinstance(path_or_file, Path): - path_or_file = str(path_or_file) + if isinstance(path_or_file, os.PathLike): + path_or_file = os.fspath(path_or_file) if encoding is None: encoding = {} @@ -1136,7 +1135,7 @@ def save_mfdataset( ---------- datasets : list of Dataset List of datasets to save. - paths : list of str or list of Path + paths : list of str or list of path-like objects List of paths to which to save each corresponding dataset. mode : {"w", "a"}, optional Write ("w") or append ("a") mode. If mode="w", any existing file at @@ -1304,7 +1303,7 @@ def check_dtype(var): def to_zarr( dataset: Dataset, - store: Union[MutableMapping, str, Path] = None, + store: Union[MutableMapping, str, os.PathLike] = None, chunk_store=None, mode: str = None, synchronizer=None, @@ -1328,7 +1327,7 @@ def to_zarr( if v.size == 0: v.load() - # expand str and Path arguments + # expand str and path-like arguments store = _normalize_path(store) chunk_store = _normalize_path(chunk_store) diff --git a/xarray/backends/common.py b/xarray/backends/common.py index 64a245ddead..f33a9ab2814 100644 --- a/xarray/backends/common.py +++ b/xarray/backends/common.py @@ -1,8 +1,7 @@ import logging -import os.path +import os import time import traceback -from pathlib import Path from typing import Any, Dict, Tuple, Type, Union import numpy as np @@ -20,8 +19,8 @@ def _normalize_path(path): - if isinstance(path, Path): - path = str(path) + if isinstance(path, os.PathLike): + path = os.fspath(path) if isinstance(path, str) and not is_remote_uri(path): path = os.path.abspath(os.path.expanduser(path)) diff --git a/xarray/backends/netCDF4_.py b/xarray/backends/netCDF4_.py index 769c96c99ce..4536f74766c 100644 --- a/xarray/backends/netCDF4_.py +++ b/xarray/backends/netCDF4_.py @@ -1,7 +1,6 @@ import functools import operator import os -import pathlib from contextlib import suppress import numpy as np @@ -346,7 +345,7 @@ def open( autoclose=False, ): - if isinstance(filename, pathlib.Path): + if isinstance(filename, os.PathLike): filename = os.fspath(filename) if not isinstance(filename, str): diff --git a/xarray/backends/zarr.py b/xarray/backends/zarr.py index 12499103fb9..d8548ca702f 100644 --- a/xarray/backends/zarr.py +++ b/xarray/backends/zarr.py @@ -1,5 +1,4 @@ import os -import pathlib import warnings from distutils.version import LooseVersion @@ -346,7 +345,7 @@ def open_group( ): # zarr doesn't support pathlib.Path objects yet. zarr-python#601 - if isinstance(store, pathlib.Path): + if isinstance(store, os.PathLike): store = os.fspath(store) open_kwargs = dict( diff --git a/xarray/core/dataset.py b/xarray/core/dataset.py index 550c3587aa6..3055e50aaf5 100644 --- a/xarray/core/dataset.py +++ b/xarray/core/dataset.py @@ -7,7 +7,7 @@ from html import escape from numbers import Number from operator import methodcaller -from pathlib import Path +from os import PathLike from typing import ( TYPE_CHECKING, Any, @@ -1832,7 +1832,7 @@ def to_netcdf( Parameters ---------- - path : str, Path or file-like, optional + path : str, path-like or file-like, optional Path to which to save this dataset. File-like objects are only supported by the scipy engine. If no path is provided, this function returns the resulting netCDF file as bytes; in this case, @@ -1914,8 +1914,8 @@ def to_netcdf( def to_zarr( self, - store: Union[MutableMapping, str, Path] = None, - chunk_store: Union[MutableMapping, str, Path] = None, + store: Union[MutableMapping, str, PathLike] = None, + chunk_store: Union[MutableMapping, str, PathLike] = None, mode: str = None, synchronizer=None, group: str = None, @@ -1944,9 +1944,9 @@ def to_zarr( Parameters ---------- - store : MutableMapping, str or Path, optional + store : MutableMapping, str or path-like, optional Store or path to directory in local or remote file system. - chunk_store : MutableMapping, str or Path, optional + chunk_store : MutableMapping, str or path-like, optional Store or path to directory in local or remote file system only for Zarr array chunks. Requires zarr-python v2.4.0 or later. mode : {"w", "w-", "a", "r+", None}, optional diff --git a/xarray/tutorial.py b/xarray/tutorial.py index 78471be7a0e..b0a3e110d84 100644 --- a/xarray/tutorial.py +++ b/xarray/tutorial.py @@ -23,7 +23,7 @@ def _construct_cache_dir(path): import pooch - if isinstance(path, pathlib.Path): + if isinstance(path, os.PathLike): path = os.fspath(path) elif path is None: path = pooch.os_cache(_default_cache_dir_name)