Source code for echofilter.path

"""
Path utilities.
"""

# This file is part of Echofilter.
#
# Copyright (C) 2020-2022  Scott C. Lowe and Offshore Energy Research Association (OERA)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <https://www.gnu.org/licenses/>.

import os
import sys


[docs]def check_if_windows(): """ Check if the operating system is Windows. Returns ------- bool Whether the OS is Windows. """ return sys.platform.startswith("win")
[docs]def parse_files_in_folders(files_or_folders, source_dir, extension, recursive=True): """ Walk through folders and find suitable files. Parameters ---------- files_or_folders : iterable List of files and folders. source_dir : str Root directory within which elements of ``files_or_folders`` may be found. extension : str or Collection Extension (or list of extensions) which files within directories must bear to be included, without leading ``'.'``, for instance ``'.csv'``. Note that explicitly given files are always used. recursive : bool, optional Whether to walk through the tree of files in a subfolders of a directory input. If ``False``, only files in the folder itself and not its child folders will be included. Yields ------ str Paths to explicitly given files and files within directories with extension ``extension``. """ if extension is None or not isinstance(extension, str): extensions = extension else: extensions = {extension} if extensions is not None: extensions = {ext.lower() for ext in extensions} for path in files_or_folders: if check_if_windows(): # Remove trailing slashes on Windows, because isdir("some\path\") # fails even though isdir("some\path") would succeed. path = path.rstrip("\\") if os.path.isfile(path) or os.path.isfile(os.path.join(source_dir, path)): yield path continue elif os.path.isdir(path): folder = path elif os.path.isdir(os.path.join(source_dir, path)): folder = os.path.join(source_dir, path) else: raise EnvironmentError("Missing file or directory: {}".format(path)) if recursive: full_filenames = [] for dirpath, _dirnames, fnames in os.walk(folder): for fname in fnames: full_filenames.append(os.path.join(dirpath, fname)) else: full_filenames = ( os.path.join(folder, filename) for filename in os.listdir(folder) ) for filename in full_filenames: if not os.path.isfile(filename): continue ext = os.path.splitext(filename)[1] if extensions is None or (len(ext) > 0 and ext[1:].lower() in extensions): yield filename
[docs]def determine_file_path(fname, source_dir): """ Determine the path to use to an input file. Parameters ---------- fname : str Path to an input file. Either an absolute path, or a path relative to to ``source_dir``, or a path relative to the working directory. source_dir : str Path to a directory where the file bearing name ``fname`` is expected to be located. Returns ------- str Path to where file can be found, either absolute or relative. """ # Check what the full path should be if os.path.isabs(fname) and os.path.isfile(fname): fname_full = fname elif os.path.isfile(os.path.join(source_dir, fname)): fname_full = os.path.join(source_dir, fname) elif os.path.isfile(fname): fname_full = fname else: raise EnvironmentError("Could not locate file {}".format(fname)) return fname_full
[docs]def determine_destination(fname, fname_full, source_dir, output_dir): """ Determine where destination should be placed for a file, preserving subtree paths. Parameters ---------- fname : str Original input path. fname_full : str Path to file, either absolute or relative; possibly containing ``source_dir``. source_dir : str Path to a directory where the file bearing name ``fname`` is expected to be located. output_dir : str Path to root output directory. Returns ------- str Path to where file can be found, either absolute or relative. """ # Determine where destination should be placed if output_dir is None or output_dir == "": return fname_full if os.path.isabs(fname): return os.path.join(output_dir, os.path.split(fname)[1]) full_source_dir = os.path.join(os.path.abspath(source_dir), "") if os.path.abspath(fname).startswith(full_source_dir): return os.path.join(output_dir, os.path.abspath(fname)[len(full_source_dir) :]) return os.path.join(output_dir, fname)