Utils
feu.utils ¶
Contain the utility functions.
feu.utils.command ¶
Contain utility functions to run commands.
feu.utils.command.run_bash_command ¶
run_bash_command(cmd: str) -> None
Execute a command.
On Windows, the command is tokenized using non-POSIX rules so
that backslashes (e.g. in paths like C:\Users\foo) are kept
literal instead of being interpreted as POSIX escape characters.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cmd
|
str
|
The command to run. |
required |
Example
>>> from feu.utils.command import run_bash_command
>>> run_bash_command("ls -l") # doctest: +SKIP
feu.utils.http ¶
Contain utility functions to manage HTTP requests.
feu.utils.http.fetch_data ¶
fetch_data(
url: str, timeout: float = 10.0, **kwargs: Any
) -> dict[str, Any]
Retrieve the JSON data for a given URL.
This function performs an HTTP GET request and parses the response body as JSON. It configures a retry policy for transient errors (e.g., 429, 500, 502, 503, 504), handles network and timeout failures, validates the HTTP response, and returns the parsed JSON payload. Any unrecoverable error is raised as a RuntimeError with a clear message.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
url
|
str
|
The URL. |
required |
timeout
|
float
|
The number of seconds to wait for the server to send data before giving up. |
10.0
|
**kwargs
|
Any
|
Optional arguments that |
{}
|
Returns:
| Type | Description |
|---|---|
dict[str, Any]
|
The parsed JSON object returned. |
Raises:
| Type | Description |
|---|---|
RuntimeError
|
If the request times out, if a network or HTTP error occurs,
if the response body contains invalid JSON, or if
|
Example
>>> from feu.utils.http import fetch_data
>>> data = fetch_data("https://pypi.org/pypi/requests/json") # doctest: +SKIP
feu.utils.http.fetch_response ¶
fetch_response(
url: str, timeout: float = 10.0, **kwargs: Any
) -> Response
Retrieve data from a given URL with automatic retry logic.
This function performs an HTTP GET request with a configured retry policy for transient errors (429, 500, 502, 503, 504). If urllib3 is available, it applies exponential backoff with up to 5 retry attempts. The function validates the HTTP response and raises detailed errors for failures.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
url
|
str
|
The URL to fetch. |
required |
timeout
|
float
|
The number of seconds to wait for the server to send data before giving up. Defaults to 10.0. |
10.0
|
**kwargs
|
Any
|
Optional arguments that |
{}
|
Returns:
| Type | Description |
|---|---|
Response
|
A |
Raises:
| Type | Description |
|---|---|
RuntimeError
|
If the request times out, if a network/HTTP error occurs,
or if |
Example
>>> from feu.utils.http import fetch_response
>>> response = fetch_response("https://pypi.org/pypi/requests/json") # doctest: +SKIP
>>> response.json() # doctest: +SKIP
feu.utils.installer ¶
Contain utility functions to manage installers.
feu.utils.installer.InstallerSpec
dataclass
¶
Define a dataclass to represent an installer specification.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
The installer name. |
required |
arguments
|
str
|
A string containing optional installer arguments. |
''
|
Example
>>> from feu.utils.installer import InstallerSpec
>>> installer1 = InstallerSpec("pip")
>>> installer1
InstallerSpec(name='pip', arguments='')
>>> installer2 = InstallerSpec("pip", arguments="-U")
>>> installer2
InstallerSpec(name='pip', arguments='-U')
feu.utils.io ¶
Contain utility functions to load and save data in JSON format.
feu.utils.io.generate_unique_tmp_path ¶
generate_unique_tmp_path(path: Path) -> Path
Return a unique temporary path given a path.
This function adds a UUID to the file name, before the extensions,
e.g. data.json becomes data-<uuid>.json.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
Path
|
The input path. |
required |
Returns:
| Type | Description |
|---|---|
Path
|
The unique path, in the same directory as |
Example
>>> import tempfile
>>> from pathlib import Path
>>> from feu.utils.io import generate_unique_tmp_path
>>> with tempfile.TemporaryDirectory() as tmpdir:
... path = generate_unique_tmp_path(Path(tmpdir).joinpath("data.json"))
... path
...
PosixPath('/.../data-....json')
feu.utils.io.load_json ¶
load_json(path: Path) -> Any
Load the data from a given JSON file.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
Path
|
The path to the JSON file. |
required |
Returns:
| Type | Description |
|---|---|
Any
|
The data from the JSON file. |
Raises:
| Type | Description |
|---|---|
FileNotFoundError
|
if the file does not exist. |
JSONDecodeError
|
if the file does not contain valid JSON. |
Example
>>> import tempfile
>>> from pathlib import Path
>>> from feu.utils.io import save_json, load_json
>>> with tempfile.TemporaryDirectory() as tmpdir:
... path = Path(tmpdir).joinpath("data.json")
... save_json({"key1": [1, 2, 3], "key2": "abc"}, path)
... data = load_json(path)
... data
...
{'key1': [1, 2, 3], 'key2': 'abc'}
feu.utils.io.save_json ¶
save_json(
to_save: Any, path: Path, *, exist_ok: bool = False
) -> None
Save the given data in a JSON file.
The parent directories are created if needed. The data is first
written to a unique temporary file, which is then moved to
path, so an interrupted write does not corrupt an existing
file.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
to_save
|
Any
|
The data to write in a JSON file. It must be
serializable by |
required |
path
|
Path
|
The path where to write the JSON file. |
required |
exist_ok
|
bool
|
If |
False
|
Raises:
| Type | Description |
|---|---|
FileExistsError
|
if the file already exists and
|
IsADirectoryError
|
if |
TypeError
|
if |
Example
>>> import tempfile
>>> from pathlib import Path
>>> from feu.utils.io import load_json, save_json
>>> with tempfile.TemporaryDirectory() as tmpdir:
... path = Path(tmpdir).joinpath("data.json")
... save_json({"key1": [1, 2, 3], "key2": "abc"}, path)
... data = load_json(path)
... data
...
{'key1': [1, 2, 3], 'key2': 'abc'}
feu.utils.mapping ¶
Contain utility functions for mappings.
feu.utils.mapping.sort_by_keys ¶
sort_by_keys(mapping: Mapping[Any, Any]) -> dict[Any, Any]
Sort a dictionary by keys.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
mapping
|
Mapping[Any, Any]
|
The dictionary to sort. |
required |
Returns:
| Type | Description |
|---|---|
dict[Any, Any]
|
A new dictionary sorted by keys in ascending order. |
Raises:
| Type | Description |
|---|---|
TypeError
|
if the keys cannot be compared. |
Example
>>> from feu.utils.mapping import sort_by_keys
>>> sort_by_keys({"dog": 1, "cat": 5, "fish": 2})
{'cat': 5, 'dog': 1, 'fish': 2}
feu.utils.mapping.sort_by_values ¶
sort_by_values(
mapping: Mapping[Any, Any],
) -> dict[Any, Any]
Sort a dictionary by values.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
mapping
|
Mapping[Any, Any]
|
The dictionary to sort. |
required |
Returns:
| Type | Description |
|---|---|
dict[Any, Any]
|
A new dictionary sorted by values in ascending order. The order of the items with equal values is preserved. |
Raises:
| Type | Description |
|---|---|
TypeError
|
if the values cannot be compared. |
Example
>>> from feu.utils.mapping import sort_by_values
>>> sort_by_values({"dog": 1, "cat": 5, "fish": 2})
{'dog': 1, 'fish': 2, 'cat': 5}
feu.utils.package ¶
Contain utility functions to manage packages.
feu.utils.package.PackageDependency
dataclass
¶
Define a dataclass to represent a package dependency.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
The package name. |
required |
version_specifiers
|
list[str] | None
|
Optional package version specifiers,
e.g. |
None
|
extras
|
list[str] | None
|
Optional package extra dependencies. |
None
|
Example
>>> from feu.utils.package import PackageDependency
>>> pkg1 = PackageDependency("my_package")
>>> pkg1
PackageDependency(name='my_package', version_specifiers=None, extras=None)
>>> pkg2 = PackageDependency("my_package", version_specifiers=["==1.2.3"])
>>> pkg2
PackageDependency(name='my_package', version_specifiers=['==1.2.3'], extras=None)
>>> pkg3 = PackageDependency(
... "my_package", version_specifiers=["==1.2.3"], extras=["security", "socks"]
... )
>>> pkg3
PackageDependency(name='my_package', version_specifiers=['==1.2.3'], extras=['security', 'socks'])
feu.utils.package.PackageSpec
dataclass
¶
Define a dataclass to represent a package specification.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
The package name. |
required |
version
|
str | None
|
An optional package version. If set, the string
representation pins it with |
None
|
extras
|
list[str] | None
|
Optional package extra dependencies. |
None
|
Example
>>> from feu.utils.package import PackageSpec
>>> pkg1 = PackageSpec("my_package")
>>> pkg1
PackageSpec(name='my_package', version=None, extras=None)
>>> pkg2 = PackageSpec("my_package", version="1.2.3")
>>> pkg2
PackageSpec(name='my_package', version='1.2.3', extras=None)
>>> pkg3 = PackageSpec("my_package", version="1.2.3", extras=["security", "socks"])
>>> pkg3
PackageSpec(name='my_package', version='1.2.3', extras=['security', 'socks'])
feu.utils.package.PackageSpec.to_package_dependency ¶
to_package_dependency() -> PackageDependency
Convert to a PackageDependency.
Returns:
| Type | Description |
|---|---|
PackageDependency
|
The current package as a package dependency. |
Example
>>> from feu.utils.package import PackageSpec
>>> pkg = PackageSpec("my_package")
>>> dep = pkg.to_package_dependency()
>>> dep
PackageDependency(name='my_package', version_specifiers=None, extras=None)
feu.utils.package.PackageSpec.with_version ¶
with_version(version: str | None) -> PackageSpec
Create a new PackageSpec instance with the given version.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
version
|
str | None
|
The new version to apply. |
required |
Returns:
| Type | Description |
|---|---|
PackageSpec
|
A new instance of PackageSpec with the updated version. |
Example
>>> from feu.utils.package import PackageSpec
>>> pkg = PackageSpec("my_package", version="1.2.0")
>>> pkg
PackageSpec(name='my_package', version='1.2.0', extras=None)
>>> pkg2 = pkg.with_version("1.2.3")
>>> pkg2
PackageSpec(name='my_package', version='1.2.3', extras=None)
feu.utils.package.extract_package_extras ¶
extract_package_extras(requirement: str) -> list[str]
Extract the optional extras from a requirement string.
The requirement string may include extras in square brackets, e.g., 'package[extra1,extra2]'. This function returns the list of extras.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
requirement
|
str
|
The requirement string containing the package name and optionally extra dependencies. |
required |
Returns:
| Type | Description |
|---|---|
list[str]
|
A list of extra requirements, or an empty list if none exist. |
Example
>>> from feu.utils.package import extract_package_extras
>>> extract_package_extras("numpy")
[]
>>> extract_package_extras("pandas[performance]")
['performance']
>>> extract_package_extras("requests[security,socks]")
['security', 'socks']
feu.utils.package.extract_package_name ¶
extract_package_name(requirement: str) -> str
Extract the base package name from a requirement string.
The requirement string may include optional dependencies in square brackets, such as 'package[extra1,extra2]'. This function returns only the base package name without the extras and without the version specifiers.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
requirement
|
str
|
The requirement string containing the package name and optionally extra dependencies. |
required |
Returns:
| Type | Description |
|---|---|
str
|
The base package name without extras. |
Raises:
| Type | Description |
|---|---|
ValueError
|
if |
Example
>>> from feu.utils.package import extract_package_name
>>> extract_package_name("numpy")
'numpy'
>>> extract_package_name("pandas[performance]")
'pandas'
>>> extract_package_name("requests[security,socks]")
'requests'
feu.utils.package.generate_extras_string ¶
generate_extras_string(extras: Sequence[str]) -> str
Generate a string with the package extras i.e. optional dependencies.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
extras
|
Sequence[str]
|
The package optional dependencies. |
required |
Returns:
| Type | Description |
|---|---|
str
|
A string with the package extras in square brackets separated by commas, or an empty string if there is no extra. |
Example
>>> from feu.utils.package import generate_extras_string
>>> generate_extras_string(["security"])
'[security]'
>>> generate_extras_string(["security", "socks"])
'[security,socks]'
>>> generate_extras_string([])
''
feu.utils.package.is_wildcard_version ¶
is_wildcard_version(version: str | None) -> bool
Indicate if a version string contains a wildcard.
Wildcard versions such as '2.12.*' are used to let the
installer pick any matching version, and cannot be parsed as a
concrete packaging.version.Version.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
version
|
str | None
|
The version string to check, or |
required |
Returns:
| Type | Description |
|---|---|
bool
|
|
Example
>>> from feu.utils.package import is_wildcard_version
>>> is_wildcard_version("2.12.*")
True
>>> is_wildcard_version("2.12.0")
False
feu.utils.platform ¶
Contain platform utilities.
feu.utils.platform.get_current_arch ¶
get_current_arch() -> str | None
Return the current CPU architecture using the registry's vocabulary.
The value returned by platform.machine() is mapped to one of
"x86_64" or "arm64".
Returns:
| Type | Description |
|---|---|
str | None
|
The architecture name, or |
Example
>>> from feu.utils.platform import get_current_arch
>>> get_current_arch() # doctest: +SKIP
'x86_64'
feu.utils.platform.get_current_os ¶
get_current_os() -> str | None
Return the current OS name using the registry's vocabulary.
The value returned by platform.system() is mapped to one of
"linux", "macos", or "windows".
Returns:
| Type | Description |
|---|---|
str | None
|
The OS name, or |
Example
>>> from feu.utils.platform import get_current_os
>>> get_current_os() # doctest: +SKIP
'linux'
feu.utils.platform.get_python_version ¶
get_python_version() -> str
Return the current Python version as a "major.minor" string.
Returns:
| Type | Description |
|---|---|
str
|
The current Python version. |
Example
>>> from feu.utils.platform import get_python_version
>>> get_python_version() # doctest: +SKIP
'3.11'
feu.utils.platform.is_free_threaded ¶
is_free_threaded() -> bool
Indicate whether the running Python interpreter is a free- threaded build with the GIL disabled.
Free-threaded builds (PEP 703 <https://peps.python.org/pep-0703/>_)
expose sys._is_gil_enabled, which is only present starting from
Python 3.13 free-threaded builds. On any other build, or when the
GIL has been re-enabled at runtime, this returns False.
Returns:
| Type | Description |
|---|---|
bool
|
|
Example
>>> from feu.utils.platform import is_free_threaded
>>> is_free_threaded() # doctest: +SKIP
False