forked from spack/spack
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge remote-tracking branch 'spack/develop' into fi-nixpack
- Loading branch information
Showing
47 changed files
with
1,962 additions
and
278 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
# Copyright 2013-2023 Lawrence Livermore National Security, LLC and other | ||
# Spack Project Developers. See the top-level COPYRIGHT file for details. | ||
# | ||
# SPDX-License-Identifier: (Apache-2.0 OR MIT) | ||
"""Path primitives that just require Python standard library.""" | ||
import functools | ||
import sys | ||
from typing import List, Optional | ||
from urllib.parse import urlparse | ||
|
||
|
||
class Path: | ||
"""Enum to identify the path-style.""" | ||
|
||
unix: int = 0 | ||
windows: int = 1 | ||
platform_path: int = windows if sys.platform == "win32" else unix | ||
|
||
|
||
def format_os_path(path: str, mode: int = Path.unix) -> str: | ||
"""Formats the input path to use consistent, platform specific separators. | ||
Absolute paths are converted between drive letters and a prepended '/' as per platform | ||
requirement. | ||
Parameters: | ||
path: the path to be normalized, must be a string or expose the replace method. | ||
mode: the path file separator style to normalize the passed path to. | ||
Default is unix style, i.e. '/' | ||
""" | ||
if not path: | ||
return path | ||
if mode == Path.windows: | ||
path = path.replace("/", "\\") | ||
else: | ||
path = path.replace("\\", "/") | ||
return path | ||
|
||
|
||
def convert_to_posix_path(path: str) -> str: | ||
"""Converts the input path to POSIX style.""" | ||
return format_os_path(path, mode=Path.unix) | ||
|
||
|
||
def convert_to_windows_path(path: str) -> str: | ||
"""Converts the input path to Windows style.""" | ||
return format_os_path(path, mode=Path.windows) | ||
|
||
|
||
def convert_to_platform_path(path: str) -> str: | ||
"""Converts the input path to the current platform's native style.""" | ||
return format_os_path(path, mode=Path.platform_path) | ||
|
||
|
||
def path_to_os_path(*parameters: str) -> List[str]: | ||
"""Takes an arbitrary number of positional parameters, converts each argument of type | ||
string to use a normalized filepath separator, and returns a list of all values. | ||
""" | ||
|
||
def _is_url(path_or_url: str) -> bool: | ||
if "\\" in path_or_url: | ||
return False | ||
url_tuple = urlparse(path_or_url) | ||
return bool(url_tuple.scheme) and len(url_tuple.scheme) > 1 | ||
|
||
result = [] | ||
for item in parameters: | ||
if isinstance(item, str) and not _is_url(item): | ||
item = convert_to_platform_path(item) | ||
result.append(item) | ||
return result | ||
|
||
|
||
def system_path_filter(_func=None, arg_slice: Optional[slice] = None): | ||
"""Filters function arguments to account for platform path separators. | ||
Optional slicing range can be specified to select specific arguments | ||
This decorator takes all (or a slice) of a method's positional arguments | ||
and normalizes usage of filepath separators on a per platform basis. | ||
Note: `**kwargs`, urls, and any type that is not a string are ignored | ||
so in such cases where path normalization is required, that should be | ||
handled by calling path_to_os_path directly as needed. | ||
Parameters: | ||
arg_slice: a slice object specifying the slice of arguments | ||
in the decorated method over which filepath separators are | ||
normalized | ||
""" | ||
|
||
def holder_func(func): | ||
@functools.wraps(func) | ||
def path_filter_caller(*args, **kwargs): | ||
args = list(args) | ||
if arg_slice: | ||
args[arg_slice] = path_to_os_path(*args[arg_slice]) | ||
else: | ||
args = path_to_os_path(*args) | ||
return func(*args, **kwargs) | ||
|
||
return path_filter_caller | ||
|
||
if _func: | ||
return holder_func(_func) | ||
return holder_func |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
# Copyright 2013-2023 Lawrence Livermore National Security, LLC and other | ||
# Spack Project Developers. See the top-level COPYRIGHT file for details. | ||
# | ||
# SPDX-License-Identifier: (Apache-2.0 OR MIT) | ||
"""String manipulation functions that do not have other dependencies than Python | ||
standard library | ||
""" | ||
from typing import List, Optional | ||
|
||
|
||
def comma_list(sequence: List[str], article: str = "") -> str: | ||
if type(sequence) is not list: | ||
sequence = list(sequence) | ||
|
||
if not sequence: | ||
return "" | ||
if len(sequence) == 1: | ||
return sequence[0] | ||
|
||
out = ", ".join(str(s) for s in sequence[:-1]) | ||
if len(sequence) != 2: | ||
out += "," # oxford comma | ||
out += " " | ||
if article: | ||
out += article + " " | ||
out += str(sequence[-1]) | ||
return out | ||
|
||
|
||
def comma_or(sequence: List[str]) -> str: | ||
"""Return a string with all the elements of the input joined by comma, but the last | ||
one (which is joined by 'or'). | ||
""" | ||
return comma_list(sequence, "or") | ||
|
||
|
||
def comma_and(sequence: List[str]) -> str: | ||
"""Return a string with all the elements of the input joined by comma, but the last | ||
one (which is joined by 'and'). | ||
""" | ||
return comma_list(sequence, "and") | ||
|
||
|
||
def quote(sequence: List[str], q: str = "'") -> List[str]: | ||
"""Quotes each item in the input list with the quote character passed as second argument.""" | ||
return [f"{q}{e}{q}" for e in sequence] | ||
|
||
|
||
def plural(n: int, singular: str, plural: Optional[str] = None, show_n: bool = True) -> str: | ||
"""Pluralize <singular> word by adding an s if n != 1. | ||
Arguments: | ||
n: number of things there are | ||
singular: singular form of word | ||
plural: optional plural form, for when it's not just singular + 's' | ||
show_n: whether to include n in the result string (default True) | ||
Returns: | ||
"1 thing" if n == 1 or "n things" if n != 1 | ||
""" | ||
number = f"{n} " if show_n else "" | ||
if n == 1: | ||
return f"{number}{singular}" | ||
elif plural is not None: | ||
return f"{number}{plural}" | ||
else: | ||
return f"{number}{singular}s" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.