Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 47 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,27 @@ Please visit the project's documentation [page](https://reframe-hpc.readthedocs.

ReFrame is fairly easy to install as PyPI package.

### Installing using `pip`

```bash
pip install reframe-hpc
```

This will also install the manpages and the shell completions under your pip's virtual environment:

| | |
|---|---|
| `reframe` executable | `${VIRTUAL_ENV}/bin` |
| Man pages | `${VIRTUAL_ENV}/share/man` |
| Bash/Zsh completions | `${VIRTUAL_ENV}/share/bash-completion/completions/reframe` |
| Fish completions | `${VIRTUAL_ENV}/share/fish/vendor_completions.d/reframe.fish` |


### Installing using `uv`

You can use any package manager that understands `pyproject.toml`-based Python projects to install ReFrame.
In this section we describe in more detail handling an installation using `uv`.

```bash
# Fetch uv
curl -LsSf https://astral.sh/uv/install.sh | sh
Expand All @@ -52,7 +73,7 @@ reframe -V
This will place the `reframe` executable under `$HOME/.local/bin` and the package under `$HOME/.local/share/uv/tools/reframe-hpc`.
To make available the manpage and the shell completions add the following lines in your shell's profile script:

### Bash/Zsh
#### Bash/Zsh

Add the following lines to your `$HOME/.profile`:

Expand All @@ -61,7 +82,7 @@ export MANPATH=${HOME}/.local/share/uv/tools/reframe-hpc/share/man:${MANPATH}:
source ${HOME}/.local/share/uv/tools/reframe-hpc/share/bash-completion/completions/reframe
```

### Fish
#### Fish

Add the following lines to your `$HOME/.config/fish/config.fish`:

Expand All @@ -70,10 +91,7 @@ set -apgx MANPATH ${HOME}/.local/share/uv/tools/reframe-hpc/share/man ""
source ${HOME}/.local/share/uv/tools/reframe-hpc/share/fish/vendor_completions.d/reframe.fish
```

> NOTE: Using `uv` is not required to install ReFrame.
> You can use any modern Python build system that recognizes the `pyproject.toml` file.

### Multi-architecture installations on shared filesystem
#### Multi-architecture installations on shared filesystem

If you plan to install ReFrame for multiple platforms in a shared installation, you should make sure each installation resides in a different prefix.
You can achieve this with `uv` as follows:
Expand All @@ -97,6 +115,29 @@ It also caches them, so that the next time you invoke it, it will not download a
The only "downside" of this method is that you have to always invoke ReFrame through `uvx`, as opposed to the `uv tool install` method, where the `reframe` executable is installed in a standard path.


### Installation extras

When installing ReFrame you can opt-in or opt-out from certain features.
For example, using `pip` you can use the brackets syntax:

```bash
# Opt-in for an extra
pip install reframe-hpc[extra]

# Opt-out from a feature
pip install reframe-hpc[no-feature]
```

With `uv` you can either use the brackets notation or use the `--extra` option.

Here is a list of the available extras during installation:

| Extra | Description |
|---|---|
| `graylog` | Install Graylog bindings |
| `no-analytics` | Do not install the analytics layers; this will disable results storage feature but will make the installation more compact. |


## Running from source

If you want to run the latest ReFrame directly from the repo, you can simply clone the repo and `uv run` ReFrame:
Expand Down
2 changes: 1 addition & 1 deletion ci-scripts/dockerfiles/reframe-envmodules.dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,4 @@ RUN uv sync --group dev && \
echo ". $BASH_ENV" >> /home/rfmuser/.profile
ENV BASH_ENV=/home/rfmuser/.profile

CMD ["/bin/bash", "-c", "uv run coverage run --source=reframe ./test_reframe.py --rfm-user-config=ci-scripts/configs/envmod.py; uv run coverage xml -o coverage.xml"]
CMD ["/bin/bash", "-c", "uv run coverage run --source=reframe ./test_reframe.py --rfm-user-config=ci-scripts/configs/envmod.py; rv=$?; uv run coverage xml -o coverage.xml; exit $rv"]
2 changes: 1 addition & 1 deletion ci-scripts/dockerfiles/reframe-lmod.dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,4 @@ RUN uv sync --group dev && \
echo ". $BASH_ENV" >> /home/rfmuser/.profile
ENV BASH_ENV=/home/rfmuser/.profile

CMD ["/bin/bash", "-c", "uv run coverage run --source=reframe ./test_reframe.py -v --rfm-user-config=ci-scripts/configs/lmod.py; uv run coverage xml -o coverage.xml"]
CMD ["/bin/bash", "-c", "uv run coverage run --source=reframe ./test_reframe.py -v --rfm-user-config=ci-scripts/configs/lmod.py; rv=$?; uv run coverage xml -o coverage.xml; exit $rv"]
2 changes: 1 addition & 1 deletion ci-scripts/dockerfiles/reframe-spack.dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,4 @@ RUN uv sync --group dev && \
echo '. /home/rfmuser/spack/share/spack/setup-env.sh' >> /home/rfmuser/.profile
ENV BASH_ENV=/home/rfmuser/.profile

CMD ["/bin/bash", "-c", "uv run coverage run --source=reframe ./test_reframe.py -v --rfm-user-config=ci-scripts/configs/spack.py; uv run coverage xml -o coverage.xml"]
CMD ["/bin/bash", "-c", "uv run coverage run --source=reframe ./test_reframe.py -v --rfm-user-config=ci-scripts/configs/spack.py; rv=$?; uv run coverage xml -o coverage.xml; exit $rv"]
30 changes: 30 additions & 0 deletions docs/started.rst
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,36 @@ This will install the man pages as well as the `Graylog <https://docs.graylog.or
This is maintained by the EasyBuild community and it may not be up to date with the latest ReFrame releases.


-------------------
Installation extras
-------------------

When installing ReFrame you can opt-in or opt-out from certain features.
Using ``pip`` you can do this as follows:

.. code-block:: bash

# Opt-in for an extra
pip instal reframe-hpc[extra]

# Opt-out from a feature
pip install reframe-hpc[no-extra]

Check your preferred package manager on how it treats optional dependencies.

Here is a list of the available extras during installation:

.. table::
:align: center

================ ====================
Extra Description
================ ====================
``graylog`` Install Graylog bindings
``no-analytics`` Do not install the analytics layers; this will disable results storage feature but will make the installation more compact.
================ ====================


Enabling auto-completion
------------------------

Expand Down
4 changes: 3 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ dependencies = [
"jinja2 ~= 3.1",
"jsonschema ~= 4.26",
"lxml ~= 6.0",
"polars ~= 1.39",
"polars ~= 1.39; extra != 'no-analytics'",
"PyYAML ~= 6.0",
"requests ~= 2.33",
"semver ~= 3.0",
Expand All @@ -57,10 +57,12 @@ reframe = "reframe.frontend.cli:main"

[project.optional-dependencies]
graylog = ["pygelf ~= 0.4"]
no-analytics = []

[dependency-groups]
dev = [
"coverage ~= 7.13",
"polars ~= 1.39",
"pytest ~= 9.0",
"pytest-forked ~= 1.6",
"pytest-rerunfailures ~= 16.1"
Expand Down
26 changes: 19 additions & 7 deletions reframe/frontend/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -274,13 +274,25 @@ def validate_storage_options(namespace, cmd_options):
storage_enabled = runtime.runtime().get_option('storage/0/enable')
for arg in cmd_options:
attr = arg[2:].replace('-', '_')
if not storage_enabled and getattr(namespace, attr, None):
logging.getlogger().error(
f'option `{arg}` requires results storage; '
'either set `RFM_ENABLE_RESULTS_STORAGE=1` or set '
'`"storage": [{"enable": True}]` in the configuration file'
)
return False
if getattr(namespace, attr, None):
if not storage_enabled:
logging.getlogger().error(
f'option `{arg}` requires results storage; '
'either set `RFM_ENABLE_RESULTS_STORAGE=1` or set '
'`"storage": [{"enable": True}]` in the configuration file'
)
return False

# Results storage is enable; try to import polars to make sure the
# installation is sane
try:
import polars # noqa: F401
except ImportError:
logging.getlogger().error(
'results storage requires polars to be installed; '
'reinstall reframe-hpc with analytics turned on'
)
return False

return True

Expand Down
5 changes: 4 additions & 1 deletion reframe/frontend/reporting/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
import lxml.etree as etree
import math
import os
import polars as pl
import re
import socket
import time
Expand Down Expand Up @@ -608,6 +607,8 @@ def _job_nodelist():

@time_function
def _create_dataframe(testcases, groups, columns):
import polars as pl

record_cols = list(OrderedSet(groups) | OrderedSet(columns))
data = []
for tc in map(_TCProxy, testcases):
Expand Down Expand Up @@ -653,6 +654,8 @@ def _aggregate_data(testcases, query):

@time_function
def compare_testcase_data(base_testcases, target_testcases, query):
import polars as pl

df_base = _aggregate_data(base_testcases, query).with_columns(
pl.col(query.aggregated_columns).name.suffix(query.lhs_column_suffix)
)
Expand Down
5 changes: 3 additions & 2 deletions reframe/frontend/reporting/utility.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
#
# SPDX-License-Identifier: BSD-3-Clause

import polars as pl
import re
from datetime import datetime, timedelta, timezone
from numbers import Number
Expand Down Expand Up @@ -69,9 +68,11 @@ def strip_suffix(self, col: str) -> str:
'''Strip aggregation suffix from column'''
return self._agg_names.get(col, col)

def col_spec(self, extra_cols: List[str]) -> List[pl.Expr]:
def col_spec(self, extra_cols: List[str]):
'''Return a list of polars expressions for this aggregation'''

import polars as pl

def _expr_from_op(col, op):
if op == 'min':
return pl.col(col).min().alias(f'{col} (min)')
Expand Down
Loading