Compare commits
176 Commits
develop-20
...
45339-on_p
Author | SHA1 | Date | |
---|---|---|---|
![]() |
af81387e6f | ||
![]() |
5ef222d62f | ||
![]() |
6810e9ed2e | ||
![]() |
a6c638d0fa | ||
![]() |
fa8a512945 | ||
![]() |
24b73da9e6 | ||
![]() |
4447d3339c | ||
![]() |
d82c9e7f2a | ||
![]() |
6828a7402a | ||
![]() |
a0d62a40dd | ||
![]() |
712dcf6b8d | ||
![]() |
ad1fc34199 | ||
![]() |
ab723b25d0 | ||
![]() |
016673f419 | ||
![]() |
7bc6d62e9b | ||
![]() |
fca9cc3e0e | ||
![]() |
2a178bfbb0 | ||
![]() |
3381879358 | ||
![]() |
ed9058618a | ||
![]() |
a4c99bad6a | ||
![]() |
f31f58ff26 | ||
![]() |
f84918da4b | ||
![]() |
80a237e250 | ||
![]() |
f52d3b26c3 | ||
![]() |
2029d714a0 | ||
![]() |
31ef1df74f | ||
![]() |
00ae96a7cb | ||
![]() |
8d2a6d6744 | ||
![]() |
9443e31b1e | ||
![]() |
2d8ca8af69 | ||
![]() |
de4d4695c4 | ||
![]() |
c8cf85223f | ||
![]() |
b869538544 | ||
![]() |
4710cbb281 | ||
![]() |
9ae1014e55 | ||
![]() |
813c0dd031 | ||
![]() |
91071933d0 | ||
![]() |
df5bac3e6c | ||
![]() |
7b9f8abce5 | ||
![]() |
a2f9d4b6a1 | ||
![]() |
77e16d55c1 | ||
![]() |
ecb2442566 | ||
![]() |
89c0b4accf | ||
![]() |
8e5b51395a | ||
![]() |
c2ada0f15a | ||
![]() |
6d3541c5fd | ||
![]() |
31e4149067 | ||
![]() |
c9fba9ec79 | ||
![]() |
282627714e | ||
![]() |
714dd783f9 | ||
![]() |
40b390903d | ||
![]() |
ce1b569b69 | ||
![]() |
b539eb5aab | ||
![]() |
e992e1efbd | ||
![]() |
33a52dd836 | ||
![]() |
b5f06fb3bc | ||
![]() |
494817b616 | ||
![]() |
02470a5aae | ||
![]() |
42232a8ab6 | ||
![]() |
cb64df45c8 | ||
![]() |
a11da7bdb9 | ||
![]() |
9a22ae11c6 | ||
![]() |
318a7e0e30 | ||
![]() |
e976f351f8 | ||
![]() |
437341d40e | ||
![]() |
9d7ea1a28b | ||
![]() |
d85668f096 | ||
![]() |
5c3a23a481 | ||
![]() |
8be1f26ac6 | ||
![]() |
35bd21fc64 | ||
![]() |
652170fb54 | ||
![]() |
d4e6c29f25 | ||
![]() |
c12772e73f | ||
![]() |
a26ac1dbcc | ||
![]() |
2afaeba292 | ||
![]() |
a14e76b98d | ||
![]() |
9a3a759ed3 | ||
![]() |
72f17d6961 | ||
![]() |
1b967a9d98 | ||
![]() |
bb954390ec | ||
![]() |
bf9b6940c9 | ||
![]() |
22980b9e65 | ||
![]() |
483426f771 | ||
![]() |
1e5b976eb7 | ||
![]() |
2aa6939b96 | ||
![]() |
f7e601d352 | ||
![]() |
c4082931e3 | ||
![]() |
cee3e5436b | ||
![]() |
613fa56bfc | ||
![]() |
0752d94bbf | ||
![]() |
3bf1a03760 | ||
![]() |
e2844e2fef | ||
![]() |
2ca733bbc1 | ||
![]() |
e2b6eca420 | ||
![]() |
67cb19614e | ||
![]() |
e464461c19 | ||
![]() |
6efe88f7a1 | ||
![]() |
0ce35dafe1 | ||
![]() |
49e419b2df | ||
![]() |
d9033d8dac | ||
![]() |
517b7fb0c9 | ||
![]() |
568e79a1e3 | ||
![]() |
9c8846b37b | ||
![]() |
737b70cbbf | ||
![]() |
03d2212881 | ||
![]() |
b8d10916af | ||
![]() |
4fe5f35c2f | ||
![]() |
cea1d8b935 | ||
![]() |
e7946a3a41 | ||
![]() |
5c53973220 | ||
![]() |
278a38f4af | ||
![]() |
39bbedf517 | ||
![]() |
2153f6056d | ||
![]() |
2be9b41362 | ||
![]() |
f9fa024fc5 | ||
![]() |
7c7ac27900 | ||
![]() |
253e8b1f2a | ||
![]() |
60e75c9234 | ||
![]() |
fb89337b04 | ||
![]() |
53f71fc4a7 | ||
![]() |
12e7c1569c | ||
![]() |
2eb566b884 | ||
![]() |
a7444873b9 | ||
![]() |
397ff11d6d | ||
![]() |
285563ad01 | ||
![]() |
c3111ac0b4 | ||
![]() |
6505e7e02a | ||
![]() |
c82889058c | ||
![]() |
2f4c20567c | ||
![]() |
a7d6a1188b | ||
![]() |
4f5244920f | ||
![]() |
feecb60b9e | ||
![]() |
4f18cab8d2 | ||
![]() |
e6f1b4e63a | ||
![]() |
c458e985af | ||
![]() |
5f234e16d0 | ||
![]() |
9001e9328a | ||
![]() |
b237ee3689 | ||
![]() |
aa911eca40 | ||
![]() |
6362c615f5 | ||
![]() |
544be90469 | ||
![]() |
56a1663cd9 | ||
![]() |
f9a46d61fa | ||
![]() |
a81451ba1f | ||
![]() |
b11e370888 | ||
![]() |
54ee7d4165 | ||
![]() |
15efcbe042 | ||
![]() |
7c5fbee327 | ||
![]() |
b19c4cdcf6 | ||
![]() |
3212cf86f4 | ||
![]() |
fbceae7773 | ||
![]() |
b921d1a920 | ||
![]() |
8128b549a5 | ||
![]() |
7405d95035 | ||
![]() |
a04b12a3ef | ||
![]() |
cbf8f2326d | ||
![]() |
297874bfed | ||
![]() |
74398d74ac | ||
![]() |
cef9c36183 | ||
![]() |
5e7430975a | ||
![]() |
1456f6dba1 | ||
![]() |
daf74a60ca | ||
![]() |
87df95c097 | ||
![]() |
9b49576875 | ||
![]() |
065cbf79fc | ||
![]() |
09b89e87a4 | ||
![]() |
ddab6156a6 | ||
![]() |
10cdfff0d1 | ||
![]() |
3328416976 | ||
![]() |
094a621f3c | ||
![]() |
87ce5d8ccb | ||
![]() |
bcdc92e25f | ||
![]() |
a323fab135 | ||
![]() |
d42031b075 | ||
![]() |
efbb18aa25 | ||
![]() |
8a430f89b3 |
3
.github/dependabot.yml
vendored
3
.github/dependabot.yml
vendored
@@ -12,6 +12,7 @@ updates:
|
||||
interval: "daily"
|
||||
# Requirements to run style checks
|
||||
- package-ecosystem: "pip"
|
||||
directory: "/.github/workflows/style"
|
||||
directories:
|
||||
- "/.github/workflows/requirements/*"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
|
4
.github/workflows/audit.yaml
vendored
4
.github/workflows/audit.yaml
vendored
@@ -28,8 +28,8 @@ jobs:
|
||||
run:
|
||||
shell: ${{ matrix.system.shell }}
|
||||
steps:
|
||||
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29
|
||||
- uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
|
||||
- uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f
|
||||
with:
|
||||
python-version: ${{inputs.python_version}}
|
||||
- name: Install Python packages
|
||||
|
17
.github/workflows/bootstrap.yml
vendored
17
.github/workflows/bootstrap.yml
vendored
@@ -37,7 +37,7 @@ jobs:
|
||||
make patch unzip which xz python3 python3-devel tree \
|
||||
cmake bison
|
||||
- name: Checkout
|
||||
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Bootstrap clingo
|
||||
@@ -60,10 +60,10 @@ jobs:
|
||||
run: |
|
||||
brew install cmake bison tree
|
||||
- name: Checkout
|
||||
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d
|
||||
- uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f
|
||||
with:
|
||||
python-version: "3.12"
|
||||
- name: Bootstrap clingo
|
||||
@@ -71,12 +71,14 @@ jobs:
|
||||
SETUP_SCRIPT_EXT: ${{ matrix.runner == 'windows-latest' && 'ps1' || 'sh' }}
|
||||
SETUP_SCRIPT_SOURCE: ${{ matrix.runner == 'windows-latest' && './' || 'source ' }}
|
||||
USER_SCOPE_PARENT_DIR: ${{ matrix.runner == 'windows-latest' && '$env:userprofile' || '$HOME' }}
|
||||
VALIDATE_LAST_EXIT: ${{ matrix.runner == 'windows-latest' && './share/spack/qa/validate_last_exit.ps1' || '' }}
|
||||
run: |
|
||||
${{ env.SETUP_SCRIPT_SOURCE }}share/spack/setup-env.${{ env.SETUP_SCRIPT_EXT }}
|
||||
spack bootstrap disable github-actions-v0.5
|
||||
spack bootstrap disable github-actions-v0.4
|
||||
spack external find --not-buildable cmake bison
|
||||
spack -d solve zlib
|
||||
${{ env.VALIDATE_LAST_EXIT }}
|
||||
tree ${{ env.USER_SCOPE_PARENT_DIR }}/.spack/bootstrap/store/
|
||||
|
||||
gnupg-sources:
|
||||
@@ -94,7 +96,7 @@ jobs:
|
||||
if: ${{ matrix.runner == 'ubuntu-latest' }}
|
||||
run: sudo rm -rf $(command -v gpg gpg2 patchelf)
|
||||
- name: Checkout
|
||||
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Bootstrap GnuPG
|
||||
@@ -123,10 +125,10 @@ jobs:
|
||||
run: |
|
||||
sudo rm -rf $(which gpg) $(which gpg2) $(which patchelf)
|
||||
- name: Checkout
|
||||
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d
|
||||
- uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f
|
||||
with:
|
||||
python-version: |
|
||||
3.8
|
||||
@@ -152,7 +154,7 @@ jobs:
|
||||
not_found=0
|
||||
old_path="$PATH"
|
||||
export PATH="$ver_dir:$PATH"
|
||||
./bin/spack-tmpconfig -b ./.github/workflows/bootstrap-test.sh
|
||||
./bin/spack-tmpconfig -b ./.github/workflows/bin/bootstrap-test.sh
|
||||
export PATH="$old_path"
|
||||
fi
|
||||
fi
|
||||
@@ -166,4 +168,3 @@ jobs:
|
||||
source share/spack/setup-env.sh
|
||||
spack -d gpg list
|
||||
tree ~/.spack/bootstrap/store/
|
||||
|
||||
|
10
.github/workflows/build-containers.yml
vendored
10
.github/workflows/build-containers.yml
vendored
@@ -55,7 +55,7 @@ jobs:
|
||||
if: github.repository == 'spack/spack'
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
|
||||
|
||||
- uses: docker/metadata-action@8e5442c4ef9f78752691e2d8f8d19755c6f78e81
|
||||
id: docker_meta
|
||||
@@ -76,7 +76,7 @@ jobs:
|
||||
env:
|
||||
SPACK_YAML_OS: "${{ matrix.dockerfile[2] }}"
|
||||
run: |
|
||||
.github/workflows/generate_spack_yaml_containerize.sh
|
||||
.github/workflows/bin/generate_spack_yaml_containerize.sh
|
||||
. share/spack/setup-env.sh
|
||||
mkdir -p dockerfiles/${{ matrix.dockerfile[0] }}
|
||||
spack containerize --last-stage=bootstrap | tee dockerfiles/${{ matrix.dockerfile[0] }}/Dockerfile
|
||||
@@ -99,7 +99,7 @@ jobs:
|
||||
uses: docker/setup-buildx-action@4fd812986e6c8c2a69e18311145f9371337f27d4
|
||||
|
||||
- name: Log in to GitHub Container Registry
|
||||
uses: docker/login-action@e92390c5fb421da1463c202d546fed0ec5c39f20
|
||||
uses: docker/login-action@0d4c9c5ea7693da7b068278f7b52bda2a190a446
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
@@ -107,13 +107,13 @@ jobs:
|
||||
|
||||
- name: Log in to DockerHub
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: docker/login-action@e92390c5fb421da1463c202d546fed0ec5c39f20
|
||||
uses: docker/login-action@0d4c9c5ea7693da7b068278f7b52bda2a190a446
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Build & Deploy ${{ matrix.dockerfile[0] }}
|
||||
uses: docker/build-push-action@1a162644f9a7e87d8f4b053101d1d9a712edc18c
|
||||
uses: docker/build-push-action@1ca370b3a9802c92e886402e0dd88098a2533b12
|
||||
with:
|
||||
context: dockerfiles/${{ matrix.dockerfile[0] }}
|
||||
platforms: ${{ matrix.dockerfile[1] }}
|
||||
|
2
.github/workflows/ci.yaml
vendored
2
.github/workflows/ci.yaml
vendored
@@ -36,7 +36,7 @@ jobs:
|
||||
core: ${{ steps.filter.outputs.core }}
|
||||
packages: ${{ steps.filter.outputs.packages }}
|
||||
steps:
|
||||
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
|
||||
if: ${{ github.event_name == 'push' }}
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
8
.github/workflows/install_spack.sh
vendored
8
.github/workflows/install_spack.sh
vendored
@@ -1,8 +0,0 @@
|
||||
#!/usr/bin/env sh
|
||||
. share/spack/setup-env.sh
|
||||
echo -e "config:\n build_jobs: 2" > etc/spack/config.yaml
|
||||
spack config add "packages:all:target:[x86_64]"
|
||||
spack compiler find
|
||||
spack compiler info apple-clang
|
||||
spack debug report
|
||||
spack solve zlib
|
4
.github/workflows/nightly-win-builds.yml
vendored
4
.github/workflows/nightly-win-builds.yml
vendored
@@ -14,10 +14,10 @@ jobs:
|
||||
build-paraview-deps:
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d
|
||||
- uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f
|
||||
with:
|
||||
python-version: 3.9
|
||||
- name: Install Python packages
|
||||
|
34
.github/workflows/unit_tests.yaml
vendored
34
.github/workflows/unit_tests.yaml
vendored
@@ -51,10 +51,10 @@ jobs:
|
||||
on_develop: false
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d
|
||||
- uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
- name: Install System packages
|
||||
@@ -72,7 +72,7 @@ jobs:
|
||||
run: |
|
||||
# Need this for the git tests to succeed.
|
||||
git --version
|
||||
. .github/workflows/setup_git.sh
|
||||
. .github/workflows/bin/setup_git.sh
|
||||
- name: Bootstrap clingo
|
||||
if: ${{ matrix.concretizer == 'clingo' }}
|
||||
env:
|
||||
@@ -100,10 +100,10 @@ jobs:
|
||||
shell:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d
|
||||
- uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f
|
||||
with:
|
||||
python-version: '3.11'
|
||||
- name: Install System packages
|
||||
@@ -118,7 +118,7 @@ jobs:
|
||||
run: |
|
||||
# Need this for the git tests to succeed.
|
||||
git --version
|
||||
. .github/workflows/setup_git.sh
|
||||
. .github/workflows/bin/setup_git.sh
|
||||
- name: Run shell tests
|
||||
env:
|
||||
COVERAGE: true
|
||||
@@ -141,13 +141,13 @@ jobs:
|
||||
dnf install -y \
|
||||
bzip2 curl file gcc-c++ gcc gcc-gfortran git gnupg2 gzip \
|
||||
make patch tcl unzip which xz
|
||||
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
|
||||
- name: Setup repo and non-root user
|
||||
run: |
|
||||
git --version
|
||||
git config --global --add safe.directory /__w/spack/spack
|
||||
git fetch --unshallow
|
||||
. .github/workflows/setup_git.sh
|
||||
. .github/workflows/bin/setup_git.sh
|
||||
useradd spack-test
|
||||
chown -R spack-test .
|
||||
- name: Run unit tests
|
||||
@@ -160,10 +160,10 @@ jobs:
|
||||
clingo-cffi:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d
|
||||
- uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f
|
||||
with:
|
||||
python-version: '3.11'
|
||||
- name: Install System packages
|
||||
@@ -178,7 +178,7 @@ jobs:
|
||||
run: |
|
||||
# Need this for the git tests to succeed.
|
||||
git --version
|
||||
. .github/workflows/setup_git.sh
|
||||
. .github/workflows/bin/setup_git.sh
|
||||
- name: Run unit tests (full suite with coverage)
|
||||
env:
|
||||
COVERAGE: true
|
||||
@@ -198,10 +198,10 @@ jobs:
|
||||
os: [macos-13, macos-14]
|
||||
python-version: ["3.11"]
|
||||
steps:
|
||||
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d
|
||||
- uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
- name: Install Python packages
|
||||
@@ -217,7 +217,7 @@ jobs:
|
||||
SPACK_TEST_PARALLEL: 4
|
||||
run: |
|
||||
git --version
|
||||
. .github/workflows/setup_git.sh
|
||||
. .github/workflows/bin/setup_git.sh
|
||||
. share/spack/setup-env.sh
|
||||
$(which spack) bootstrap disable spack-install
|
||||
$(which spack) solve zlib
|
||||
@@ -236,10 +236,10 @@ jobs:
|
||||
powershell Invoke-Expression -Command "./share/spack/qa/windows_test_setup.ps1"; {0}
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d
|
||||
- uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f
|
||||
with:
|
||||
python-version: 3.9
|
||||
- name: Install Python packages
|
||||
@@ -247,7 +247,7 @@ jobs:
|
||||
python -m pip install --upgrade pip pywin32 setuptools pytest-cov clingo
|
||||
- name: Create local develop
|
||||
run: |
|
||||
./.github/workflows/setup_git.ps1
|
||||
./.github/workflows/bin/setup_git.ps1
|
||||
- name: Unit Test
|
||||
run: |
|
||||
spack unit-test -x --verbose --cov --cov-config=pyproject.toml
|
||||
|
18
.github/workflows/valid-style.yml
vendored
18
.github/workflows/valid-style.yml
vendored
@@ -18,15 +18,15 @@ jobs:
|
||||
validate:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29
|
||||
- uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
|
||||
- uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f
|
||||
with:
|
||||
python-version: '3.11'
|
||||
cache: 'pip'
|
||||
- name: Install Python Packages
|
||||
run: |
|
||||
pip install --upgrade pip setuptools
|
||||
pip install -r .github/workflows/style/requirements.txt
|
||||
pip install -r .github/workflows/requirements/style/requirements.txt
|
||||
- name: vermin (Spack's Core)
|
||||
run: vermin --backport importlib --backport argparse --violations --backport typing -t=3.6- -vvv lib/spack/spack/ lib/spack/llnl/ bin/
|
||||
- name: vermin (Repositories)
|
||||
@@ -35,22 +35,22 @@ jobs:
|
||||
style:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d
|
||||
- uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f
|
||||
with:
|
||||
python-version: '3.11'
|
||||
cache: 'pip'
|
||||
- name: Install Python packages
|
||||
run: |
|
||||
pip install --upgrade pip setuptools
|
||||
pip install -r .github/workflows/style/requirements.txt
|
||||
pip install -r .github/workflows/requirements/style/requirements.txt
|
||||
- name: Setup git configuration
|
||||
run: |
|
||||
# Need this for the git tests to succeed.
|
||||
git --version
|
||||
. .github/workflows/setup_git.sh
|
||||
. .github/workflows/bin/setup_git.sh
|
||||
- name: Run style tests
|
||||
run: |
|
||||
share/spack/qa/run-style-tests
|
||||
@@ -70,13 +70,13 @@ jobs:
|
||||
dnf install -y \
|
||||
bzip2 curl file gcc-c++ gcc gcc-gfortran git gnupg2 gzip \
|
||||
make patch tcl unzip which xz
|
||||
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29
|
||||
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
|
||||
- name: Setup repo and non-root user
|
||||
run: |
|
||||
git --version
|
||||
git config --global --add safe.directory /__w/spack/spack
|
||||
git fetch --unshallow
|
||||
. .github/workflows/setup_git.sh
|
||||
. .github/workflows/bin/setup_git.sh
|
||||
useradd spack-test
|
||||
chown -R spack-test .
|
||||
- name: Bootstrap Spack development environment
|
||||
|
@@ -1,3 +0,0 @@
|
||||
packages:
|
||||
iconv:
|
||||
require: [libiconv]
|
@@ -931,32 +931,84 @@ This allows for a much-needed reduction in redundancy between packages
|
||||
and constraints.
|
||||
|
||||
|
||||
----------------
|
||||
Filesystem Views
|
||||
----------------
|
||||
-----------------
|
||||
Environment Views
|
||||
-----------------
|
||||
|
||||
Spack Environments can define filesystem views, which provide a direct access point
|
||||
for software similar to the directory hierarchy that might exist under ``/usr/local``.
|
||||
Filesystem views are updated every time the environment is written out to the lock
|
||||
file ``spack.lock``, so the concrete environment and the view are always compatible.
|
||||
The files of the view's installed packages are brought into the view by symbolic or
|
||||
hard links, referencing the original Spack installation, or by copy.
|
||||
Spack Environments can have an associated filesystem view, which is a directory
|
||||
with a more traditional structure ``<view>/bin``, ``<view>/lib``, ``<view>/include``
|
||||
in which all files of the installed packages are linked.
|
||||
|
||||
By default a view is created for each environment, thanks to the ``view: true``
|
||||
option in the ``spack.yaml`` manifest file:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
spack:
|
||||
specs: [perl, python]
|
||||
view: true
|
||||
|
||||
The view is created in a hidden directory ``.spack-env/view`` relative to the environment.
|
||||
If you've used ``spack env activate``, you may have already interacted with this view. Spack
|
||||
prepends its ``<view>/bin`` dir to ``PATH`` when the environment is activated, so that
|
||||
you can directly run executables from all installed packages in the environment.
|
||||
|
||||
Views are highly customizable: you can control where they are put, modify their structure,
|
||||
include and exclude specs, change how files are linked, and you can even generate multiple
|
||||
views for a single environment.
|
||||
|
||||
.. _configuring_environment_views:
|
||||
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
Configuration in ``spack.yaml``
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
Minimal view configuration
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The Spack Environment manifest file has a top-level keyword
|
||||
``view``. Each entry under that heading is a **view descriptor**, headed
|
||||
by a name. Any number of views may be defined under the ``view`` heading.
|
||||
The view descriptor contains the root of the view, and
|
||||
optionally the projections for the view, ``select`` and
|
||||
``exclude`` lists for the view and link information via ``link`` and
|
||||
The minimal configuration
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
spack:
|
||||
# ...
|
||||
view: true
|
||||
|
||||
lets Spack generate a single view with default settings under the
|
||||
``.spack-env/view`` directory of the environment.
|
||||
|
||||
Another short way to configure a view is to specify just where to put it:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
spack:
|
||||
# ...
|
||||
view: /path/to/view
|
||||
|
||||
Views can also be disabled by setting ``view: false``.
|
||||
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
Advanced view configuration
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
One or more **view descriptors** can be defined under ``view``, keyed by a name.
|
||||
The example from the previous section with ``view: /path/to/view`` is equivalent
|
||||
to defining a view descriptor named ``default`` with a ``root`` attribute:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
spack:
|
||||
# ...
|
||||
view:
|
||||
default: # name of the view
|
||||
root: /path/to/view # view descriptor attribute
|
||||
|
||||
The ``default`` view descriptor name is special: when you ``spack env activate`` your
|
||||
environment, this view will be used to update (among other things) your ``PATH``
|
||||
variable.
|
||||
|
||||
View descriptors must contain the root of the view, and optionally projections,
|
||||
``select`` and ``exclude`` lists and link information via ``link`` and
|
||||
``link_type``.
|
||||
|
||||
For example, in the following manifest
|
||||
As a more advanced example, in the following manifest
|
||||
file snippet we define a view named ``mpis``, rooted at
|
||||
``/path/to/view`` in which all projections use the package name,
|
||||
version, and compiler name to determine the path for a given
|
||||
@@ -1001,59 +1053,10 @@ of ``hardlink`` or ``copy``.
|
||||
when the environment is not activated, and linked libraries will be located
|
||||
*outside* of the view thanks to rpaths.
|
||||
|
||||
|
||||
There are two shorthands for environments with a single view. If the
|
||||
environment at ``/path/to/env`` has a single view, with a root at
|
||||
``/path/to/env/.spack-env/view``, with default selection and exclusion
|
||||
and the default projection, we can put ``view: True`` in the
|
||||
environment manifest. Similarly, if the environment has a view with a
|
||||
different root, but default selection, exclusion, and projections, the
|
||||
manifest can say ``view: /path/to/view``. These views are
|
||||
automatically named ``default``, so that
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
spack:
|
||||
# ...
|
||||
view: True
|
||||
|
||||
is equivalent to
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
spack:
|
||||
# ...
|
||||
view:
|
||||
default:
|
||||
root: .spack-env/view
|
||||
|
||||
and
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
spack:
|
||||
# ...
|
||||
view: /path/to/view
|
||||
|
||||
is equivalent to
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
spack:
|
||||
# ...
|
||||
view:
|
||||
default:
|
||||
root: /path/to/view
|
||||
|
||||
By default, Spack environments are configured with ``view: True`` in
|
||||
the manifest. Environments can be configured without views using
|
||||
``view: False``. For backwards compatibility reasons, environments
|
||||
with no ``view`` key are treated the same as ``view: True``.
|
||||
|
||||
From the command line, the ``spack env create`` command takes an
|
||||
argument ``--with-view [PATH]`` that sets the path for a single, default
|
||||
view. If no path is specified, the default path is used (``view:
|
||||
True``). The argument ``--without-view`` can be used to create an
|
||||
true``). The argument ``--without-view`` can be used to create an
|
||||
environment without any view configured.
|
||||
|
||||
The ``spack env view`` command can be used to change the manage views
|
||||
@@ -1119,11 +1122,18 @@ the projection under ``all`` before reaching those entries.
|
||||
Activating environment views
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The ``spack env activate`` command will put the default view for the
|
||||
environment into the user's path, in addition to activating the
|
||||
environment for Spack commands. The arguments ``-v,--with-view`` and
|
||||
``-V,--without-view`` can be used to tune this behavior. The default
|
||||
behavior is to activate with the environment view if there is one.
|
||||
The ``spack env activate <env>`` has two effects:
|
||||
|
||||
1. It activates the environment so that further Spack commands such
|
||||
as ``spack install`` will run in the context of the environment.
|
||||
2. It activates the view so that environment variables such as
|
||||
``PATH`` are updated to include the view.
|
||||
|
||||
Without further arguments, the ``default`` view of the environment is
|
||||
activated. If a view with a different name has to be activated,
|
||||
``spack env activate --with-view <name> <env>`` can be
|
||||
used instead. You can also activate the environment without modifying
|
||||
further environment variables using ``--without-view``.
|
||||
|
||||
The environment variables affected by the ``spack env activate``
|
||||
command and the paths that are used to update them are determined by
|
||||
@@ -1146,8 +1156,8 @@ relevant variable if the path exists. For this reason, it is not
|
||||
recommended to use non-default projections with the default view of an
|
||||
environment.
|
||||
|
||||
The ``spack env deactivate`` command will remove the default view of
|
||||
the environment from the user's path.
|
||||
The ``spack env deactivate`` command will remove the active view of
|
||||
the Spack environment from the user's environment variables.
|
||||
|
||||
|
||||
.. _env-generate-depfile:
|
||||
@@ -1306,7 +1316,7 @@ index once every package is pushed. Note how this target uses the generated
|
||||
example/push/%: example/install/%
|
||||
@mkdir -p $(dir $@)
|
||||
$(info About to push $(SPEC) to a buildcache)
|
||||
$(SPACK) -e . buildcache push --allow-root --only=package $(BUILDCACHE_DIR) /$(HASH)
|
||||
$(SPACK) -e . buildcache push --only=package $(BUILDCACHE_DIR) /$(HASH)
|
||||
@touch $@
|
||||
|
||||
push: $(addprefix example/push/,$(example/SPACK_PACKAGE_IDS))
|
||||
|
@@ -1,4 +1,4 @@
|
||||
sphinx==7.2.6
|
||||
sphinx==7.4.6
|
||||
sphinxcontrib-programoutput==0.17
|
||||
sphinx_design==0.6.0
|
||||
sphinx-rtd-theme==2.0.0
|
||||
|
@@ -1473,7 +1473,7 @@ def long_message(self):
|
||||
out.write(" {0}\n".format(self.log_name))
|
||||
|
||||
# Also output the test log path IF it exists
|
||||
if self.context != "test":
|
||||
if self.context != "test" and have_log:
|
||||
test_log = join_path(os.path.dirname(self.log_name), spack_install_test_log)
|
||||
if os.path.isfile(test_log):
|
||||
out.write("\nSee test log for details:\n")
|
||||
|
@@ -124,6 +124,8 @@ def cuda_flags(arch_list):
|
||||
# minimum supported versions
|
||||
conflicts("%gcc@:4", when="+cuda ^cuda@11.0:")
|
||||
conflicts("%gcc@:5", when="+cuda ^cuda@11.4:")
|
||||
conflicts("%gcc@:7.2", when="+cuda ^cuda@12.4:")
|
||||
conflicts("%clang@:6", when="+cuda ^cuda@12.2:")
|
||||
|
||||
# maximum supported version
|
||||
# NOTE:
|
||||
@@ -211,12 +213,16 @@ def cuda_flags(arch_list):
|
||||
conflicts("%intel@19.0:", when="+cuda ^cuda@:10.0")
|
||||
conflicts("%intel@19.1:", when="+cuda ^cuda@:10.1")
|
||||
conflicts("%intel@19.2:", when="+cuda ^cuda@:11.1.0")
|
||||
conflicts("%intel@2021:", when="+cuda ^cuda@:11.4.0")
|
||||
|
||||
# XL is mostly relevant for ppc64le Linux
|
||||
conflicts("%xl@:12,14:", when="+cuda ^cuda@:9.1")
|
||||
conflicts("%xl@:12,14:15,17:", when="+cuda ^cuda@9.2")
|
||||
conflicts("%xl@:12,17:", when="+cuda ^cuda@:11.1.0")
|
||||
|
||||
# PowerPC.
|
||||
conflicts("target=ppc64le", when="+cuda ^cuda@12.5:")
|
||||
|
||||
# Darwin.
|
||||
# TODO: add missing conflicts for %apple-clang cuda@:10
|
||||
conflicts("platform=darwin", when="+cuda ^cuda@11.0.2: ")
|
||||
conflicts("platform=darwin", when="+cuda ^cuda@11.0.2:")
|
||||
|
@@ -336,6 +336,7 @@ def display_specs(specs, args=None, **kwargs):
|
||||
groups (bool): display specs grouped by arch/compiler (default True)
|
||||
decorator (typing.Callable): function to call to decorate specs
|
||||
all_headers (bool): show headers even when arch/compiler aren't defined
|
||||
status_fn (typing.Callable): if provided, prepend install-status info
|
||||
output (typing.IO): A file object to write to. Default is ``sys.stdout``
|
||||
|
||||
"""
|
||||
@@ -359,6 +360,7 @@ def get_arg(name, default=None):
|
||||
groups = get_arg("groups", True)
|
||||
all_headers = get_arg("all_headers", False)
|
||||
output = get_arg("output", sys.stdout)
|
||||
status_fn = get_arg("status_fn", None)
|
||||
|
||||
decorator = get_arg("decorator", None)
|
||||
if decorator is None:
|
||||
@@ -386,6 +388,13 @@ def get_arg(name, default=None):
|
||||
def fmt(s, depth=0):
|
||||
"""Formatter function for all output specs"""
|
||||
string = ""
|
||||
|
||||
if status_fn:
|
||||
# This was copied from spec.tree's colorization logic
|
||||
# then shortened because it seems like status_fn should
|
||||
# always return an InstallStatus
|
||||
string += colorize(status_fn(s).value)
|
||||
|
||||
if hashes:
|
||||
string += gray_hash(s, hlen) + " "
|
||||
string += depth * " "
|
||||
|
@@ -70,12 +70,6 @@ def setup_parser(subparser: argparse.ArgumentParser):
|
||||
|
||||
push = subparsers.add_parser("push", aliases=["create"], help=push_fn.__doc__)
|
||||
push.add_argument("-f", "--force", action="store_true", help="overwrite tarball if it exists")
|
||||
push.add_argument(
|
||||
"--allow-root",
|
||||
"-a",
|
||||
action="store_true",
|
||||
help="allow install root string in binary files after RPATH substitution",
|
||||
)
|
||||
push_sign = push.add_mutually_exclusive_group(required=False)
|
||||
push_sign.add_argument(
|
||||
"--unsigned",
|
||||
@@ -190,10 +184,6 @@ def setup_parser(subparser: argparse.ArgumentParser):
|
||||
keys.add_argument("-f", "--force", action="store_true", help="force new download of keys")
|
||||
keys.set_defaults(func=keys_fn)
|
||||
|
||||
preview = subparsers.add_parser("preview", help=preview_fn.__doc__)
|
||||
arguments.add_common_arguments(preview, ["installed_specs"])
|
||||
preview.set_defaults(func=preview_fn)
|
||||
|
||||
# Check if binaries need to be rebuilt on remote mirror
|
||||
check = subparsers.add_parser("check", help=check_fn.__doc__)
|
||||
check.add_argument(
|
||||
@@ -404,11 +394,6 @@ def push_fn(args):
|
||||
else:
|
||||
roots = spack.cmd.require_active_env(cmd_name="buildcache push").concrete_roots()
|
||||
|
||||
if args.allow_root:
|
||||
tty.warn(
|
||||
"The flag `--allow-root` is the default in Spack 0.21, will be removed in Spack 0.22"
|
||||
)
|
||||
|
||||
mirror: spack.mirror.Mirror = args.mirror
|
||||
|
||||
# Check if this is an OCI image.
|
||||
@@ -960,14 +945,6 @@ def keys_fn(args):
|
||||
bindist.get_keys(args.install, args.trust, args.force)
|
||||
|
||||
|
||||
def preview_fn(args):
|
||||
"""analyze an installed spec and reports whether executables and libraries are relocatable"""
|
||||
tty.warn(
|
||||
"`spack buildcache preview` is deprecated since `spack buildcache push --allow-root` is "
|
||||
"now the default. This command will be removed in Spack 0.22"
|
||||
)
|
||||
|
||||
|
||||
def check_fn(args: argparse.Namespace):
|
||||
"""check specs against remote binary mirror(s) to see if any need to be rebuilt
|
||||
|
||||
|
@@ -156,7 +156,7 @@ def print_flattened_configuration(*, blame: bool) -> None:
|
||||
"""
|
||||
env = ev.active_environment()
|
||||
if env is not None:
|
||||
pristine = env.manifest.pristine_yaml_content
|
||||
pristine = env.manifest.yaml_content
|
||||
flattened = pristine.copy()
|
||||
flattened[spack.schema.env.TOP_LEVEL_KEY] = pristine[spack.schema.env.TOP_LEVEL_KEY].copy()
|
||||
else:
|
||||
|
@@ -941,9 +941,7 @@ def get_repository(args, name):
|
||||
)
|
||||
else:
|
||||
if spec.namespace:
|
||||
repo = spack.repo.PATH.get_repo(spec.namespace, None)
|
||||
if not repo:
|
||||
tty.die("Unknown namespace: '{0}'".format(spec.namespace))
|
||||
repo = spack.repo.PATH.get_repo(spec.namespace)
|
||||
else:
|
||||
repo = spack.repo.PATH.first_repo()
|
||||
|
||||
|
@@ -47,16 +47,6 @@ def inverted_dependencies():
|
||||
dependents of, e.g., `mpi`, but virtuals are not included as
|
||||
actual dependents.
|
||||
"""
|
||||
dag = {}
|
||||
for pkg_cls in spack.repo.PATH.all_package_classes():
|
||||
dag.setdefault(pkg_cls.name, set())
|
||||
for dep in pkg_cls.dependencies_by_name():
|
||||
deps = [dep]
|
||||
|
||||
# expand virtuals if necessary
|
||||
if spack.repo.PATH.is_virtual(dep):
|
||||
deps += [s.name for s in spack.repo.PATH.providers_for(dep)]
|
||||
|
||||
dag = collections.defaultdict(set)
|
||||
for pkg_cls in spack.repo.PATH.all_package_classes():
|
||||
for _, deps_by_name in pkg_cls.dependencies.items():
|
||||
|
@@ -7,7 +7,7 @@
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
from typing import List, Optional
|
||||
from typing import List, Optional, Set
|
||||
|
||||
import llnl.util.tty as tty
|
||||
import llnl.util.tty.colify as colify
|
||||
@@ -19,6 +19,7 @@
|
||||
import spack.detection
|
||||
import spack.error
|
||||
import spack.repo
|
||||
import spack.spec
|
||||
import spack.util.environment
|
||||
from spack.cmd.common import arguments
|
||||
|
||||
@@ -138,14 +139,26 @@ def external_find(args):
|
||||
candidate_packages, path_hints=args.path, max_workers=args.jobs
|
||||
)
|
||||
|
||||
new_entries = spack.detection.update_configuration(
|
||||
new_specs = spack.detection.update_configuration(
|
||||
detected_packages, scope=args.scope, buildable=not args.not_buildable
|
||||
)
|
||||
if new_entries:
|
||||
|
||||
# If the user runs `spack external find --not-buildable mpich` we also mark `mpi` non-buildable
|
||||
# to avoid that the concretizer picks a different mpi provider.
|
||||
if new_specs and args.not_buildable:
|
||||
virtuals: Set[str] = {
|
||||
virtual.name
|
||||
for new_spec in new_specs
|
||||
for virtual_specs in spack.repo.PATH.get_pkg_class(new_spec.name).provided.values()
|
||||
for virtual in virtual_specs
|
||||
}
|
||||
new_virtuals = spack.detection.set_virtuals_nonbuildable(virtuals, scope=args.scope)
|
||||
new_specs.extend(spack.spec.Spec(name) for name in new_virtuals)
|
||||
|
||||
if new_specs:
|
||||
path = spack.config.CONFIG.get_config_filename(args.scope, "packages")
|
||||
msg = "The following specs have been detected on this system and added to {0}"
|
||||
tty.msg(msg.format(path))
|
||||
spack.cmd.display_specs(new_entries)
|
||||
tty.msg(f"The following specs have been detected on this system and added to {path}")
|
||||
spack.cmd.display_specs(new_specs)
|
||||
else:
|
||||
tty.msg("No new external packages detected")
|
||||
|
||||
|
@@ -46,6 +46,10 @@ def setup_parser(subparser):
|
||||
help="output specs as machine-readable json records",
|
||||
)
|
||||
|
||||
subparser.add_argument(
|
||||
"-I", "--install-status", action="store_true", help="show install status of packages"
|
||||
)
|
||||
|
||||
subparser.add_argument(
|
||||
"-d", "--deps", action="store_true", help="output dependencies along with found specs"
|
||||
)
|
||||
@@ -293,25 +297,24 @@ def root_decorator(spec, string):
|
||||
)
|
||||
print()
|
||||
|
||||
if args.show_concretized:
|
||||
tty.msg("Concretized roots")
|
||||
cmd.display_specs(env.specs_by_hash.values(), args, decorator=decorator)
|
||||
print()
|
||||
|
||||
# Display a header for the installed packages section IF there are installed
|
||||
# packages. If there aren't any, we'll just end up printing "0 installed packages"
|
||||
# later.
|
||||
if results and not args.only_roots:
|
||||
tty.msg("Installed packages")
|
||||
|
||||
|
||||
def find(parser, args):
|
||||
q_args = query_arguments(args)
|
||||
results = args.specs(**q_args)
|
||||
|
||||
env = ev.active_environment()
|
||||
|
||||
if not env and args.only_roots:
|
||||
tty.die("-r / --only-roots requires an active environment")
|
||||
if not env and args.show_concretized:
|
||||
tty.die("-c / --show-concretized requires an active environment")
|
||||
|
||||
if env:
|
||||
if args.constraint:
|
||||
init_specs = spack.cmd.parse_specs(args.constraint)
|
||||
results = env.all_matching_specs(*init_specs)
|
||||
else:
|
||||
results = env.all_specs()
|
||||
else:
|
||||
q_args = query_arguments(args)
|
||||
results = args.specs(**q_args)
|
||||
|
||||
decorator = make_env_decorator(env) if env else lambda s, f: f
|
||||
|
||||
@@ -332,6 +335,11 @@ def find(parser, args):
|
||||
if args.loaded:
|
||||
results = spack.cmd.filter_loaded_specs(results)
|
||||
|
||||
if args.install_status or args.show_concretized:
|
||||
status_fn = spack.spec.Spec.install_status
|
||||
else:
|
||||
status_fn = None
|
||||
|
||||
# Display the result
|
||||
if args.json:
|
||||
cmd.display_specs_as_json(results, deps=args.deps)
|
||||
@@ -340,12 +348,34 @@ def find(parser, args):
|
||||
if env:
|
||||
display_env(env, args, decorator, results)
|
||||
|
||||
count_suffix = " (not shown)"
|
||||
if not args.only_roots:
|
||||
cmd.display_specs(results, args, decorator=decorator, all_headers=True)
|
||||
count_suffix = ""
|
||||
display_results = results
|
||||
if not args.show_concretized:
|
||||
display_results = list(x for x in results if x.installed)
|
||||
cmd.display_specs(
|
||||
display_results, args, decorator=decorator, all_headers=True, status_fn=status_fn
|
||||
)
|
||||
|
||||
# print number of installed packages last (as the list may be long)
|
||||
if sys.stdout.isatty() and args.groups:
|
||||
installed_suffix = ""
|
||||
concretized_suffix = " to be installed"
|
||||
|
||||
if args.only_roots:
|
||||
installed_suffix += " (not shown)"
|
||||
concretized_suffix += " (not shown)"
|
||||
else:
|
||||
if env and not args.show_concretized:
|
||||
concretized_suffix += " (show with `spack find -c`)"
|
||||
|
||||
pkg_type = "loaded" if args.loaded else "installed"
|
||||
spack.cmd.print_how_many_pkgs(results, pkg_type, suffix=count_suffix)
|
||||
spack.cmd.print_how_many_pkgs(
|
||||
list(x for x in results if x.installed), pkg_type, suffix=installed_suffix
|
||||
)
|
||||
|
||||
if env:
|
||||
spack.cmd.print_how_many_pkgs(
|
||||
list(x for x in results if not x.installed),
|
||||
"concretized",
|
||||
suffix=concretized_suffix,
|
||||
)
|
||||
|
@@ -18,7 +18,6 @@
|
||||
import llnl.util.tty as tty
|
||||
from llnl.util.filesystem import path_contains_subdirectory, paths_containing_libs
|
||||
|
||||
import spack.compilers
|
||||
import spack.error
|
||||
import spack.schema.environment
|
||||
import spack.spec
|
||||
|
@@ -488,7 +488,7 @@ def supported_compilers_for_host_platform() -> List[str]:
|
||||
return supported_compilers_for_platform(host_plat)
|
||||
|
||||
|
||||
def supported_compilers_for_platform(platform: spack.platforms.Platform) -> List[str]:
|
||||
def supported_compilers_for_platform(platform: "spack.platforms.Platform") -> List[str]:
|
||||
"""Return a set of compiler class objects supported by Spack
|
||||
that are also supported by the provided platform
|
||||
|
||||
|
@@ -4,7 +4,7 @@
|
||||
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
||||
|
||||
import os
|
||||
from os.path import dirname
|
||||
from os.path import dirname, join
|
||||
|
||||
from llnl.util import tty
|
||||
|
||||
@@ -135,8 +135,12 @@ def setup_custom_environment(self, pkg, env):
|
||||
# It is located in the same directory as the driver. Error message:
|
||||
# clang++: error: unable to execute command:
|
||||
# Executable "sycl-post-link" doesn't exist!
|
||||
if self.cxx:
|
||||
# also ensures that shared objects and libraries required by the compiler,
|
||||
# e.g. libonnx, can be found succesfully
|
||||
# due to a fix, this is no longer required for OneAPI versions >= 2024.2
|
||||
if self.cxx and pkg.spec.satisfies("%oneapi@:2024.1"):
|
||||
env.prepend_path("PATH", dirname(self.cxx))
|
||||
env.prepend_path("LD_LIBRARY_PATH", join(dirname(dirname(self.cxx)), "lib"))
|
||||
|
||||
# 2024 release bumped the libsycl version because of an ABI
|
||||
# change, 2024 compilers are required. You will see this
|
||||
|
@@ -39,7 +39,6 @@
|
||||
|
||||
from llnl.util import filesystem, lang, tty
|
||||
|
||||
import spack.compilers
|
||||
import spack.paths
|
||||
import spack.platforms
|
||||
import spack.schema
|
||||
@@ -174,9 +173,7 @@ def _write_section(self, section: str) -> None:
|
||||
if data is None:
|
||||
return
|
||||
|
||||
# We copy data here to avoid adding defaults at write time
|
||||
validate_data = copy.deepcopy(data)
|
||||
validate(validate_data, SECTION_SCHEMAS[section])
|
||||
validate(data, SECTION_SCHEMAS[section])
|
||||
|
||||
try:
|
||||
filesystem.mkdirp(self.path)
|
||||
@@ -796,22 +793,27 @@ def config_paths_from_entry_points() -> List[Tuple[str, str]]:
|
||||
def _add_command_line_scopes(
|
||||
cfg: Union[Configuration, lang.Singleton], command_line_scopes: List[str]
|
||||
) -> None:
|
||||
"""Add additional scopes from the --config-scope argument.
|
||||
"""Add additional scopes from the --config-scope argument, either envs or dirs."""
|
||||
import spack.environment.environment as env # circular import
|
||||
|
||||
Command line scopes are named after their position in the arg list.
|
||||
"""
|
||||
for i, path in enumerate(command_line_scopes):
|
||||
# We ensure that these scopes exist and are readable, as they are
|
||||
# provided on the command line by the user.
|
||||
if not os.path.isdir(path):
|
||||
raise ConfigError(f"config scope is not a directory: '{path}'")
|
||||
elif not os.access(path, os.R_OK):
|
||||
raise ConfigError(f"config scope is not readable: '{path}'")
|
||||
name = f"cmd_scope_{i}"
|
||||
|
||||
# name based on order on the command line
|
||||
name = f"cmd_scope_{i:d}"
|
||||
cfg.push_scope(DirectoryConfigScope(name, path, writable=False))
|
||||
_add_platform_scope(cfg, name, path, writable=False)
|
||||
if env.exists(path): # managed environment
|
||||
manifest = env.EnvironmentManifestFile(env.root(path))
|
||||
elif env.is_env_dir(path): # anonymous environment
|
||||
manifest = env.EnvironmentManifestFile(path)
|
||||
elif os.path.isdir(path): # directory with config files
|
||||
cfg.push_scope(DirectoryConfigScope(name, path, writable=False))
|
||||
_add_platform_scope(cfg, name, path, writable=False)
|
||||
continue
|
||||
else:
|
||||
raise ConfigError(f"Invalid configuration scope: {path}")
|
||||
|
||||
for scope in manifest.env_config_scopes:
|
||||
scope.name = f"{name}:{scope.name}"
|
||||
scope.writable = False
|
||||
cfg.push_scope(scope)
|
||||
|
||||
|
||||
def create() -> Configuration:
|
||||
@@ -1075,11 +1077,8 @@ def validate(
|
||||
"""
|
||||
import jsonschema
|
||||
|
||||
# Validate a copy to avoid adding defaults
|
||||
# This allows us to round-trip data without adding to it.
|
||||
test_data = syaml.deepcopy(data)
|
||||
try:
|
||||
spack.schema.Validator(schema).validate(test_data)
|
||||
spack.schema.Validator(schema).validate(data)
|
||||
except jsonschema.ValidationError as e:
|
||||
if hasattr(e.instance, "lc"):
|
||||
line_number = e.instance.lc.line + 1
|
||||
@@ -1088,7 +1087,7 @@ def validate(
|
||||
raise ConfigFormatError(e, data, filename, line_number) from e
|
||||
# return the validated data so that we can access the raw data
|
||||
# mostly relevant for environments
|
||||
return test_data
|
||||
return data
|
||||
|
||||
|
||||
def read_config_file(
|
||||
|
@@ -2,7 +2,12 @@
|
||||
# Spack Project Developers. See the top-level COPYRIGHT file for details.
|
||||
#
|
||||
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
||||
from .common import DetectedPackage, executable_prefix, update_configuration
|
||||
from .common import (
|
||||
DetectedPackage,
|
||||
executable_prefix,
|
||||
set_virtuals_nonbuildable,
|
||||
update_configuration,
|
||||
)
|
||||
from .path import by_path, executables_in_path
|
||||
from .test import detection_tests
|
||||
|
||||
@@ -12,5 +17,6 @@
|
||||
"executables_in_path",
|
||||
"executable_prefix",
|
||||
"update_configuration",
|
||||
"set_virtuals_nonbuildable",
|
||||
"detection_tests",
|
||||
]
|
||||
|
@@ -252,6 +252,27 @@ def update_configuration(
|
||||
return all_new_specs
|
||||
|
||||
|
||||
def set_virtuals_nonbuildable(virtuals: Set[str], scope: Optional[str] = None) -> List[str]:
|
||||
"""Update packages:virtual:buildable:False for the provided virtual packages, if the property
|
||||
is not set by the user. Returns the list of virtual packages that have been updated."""
|
||||
packages = spack.config.get("packages")
|
||||
new_config = {}
|
||||
for virtual in virtuals:
|
||||
# If the user has set the buildable prop do not override it
|
||||
if virtual in packages and "buildable" in packages[virtual]:
|
||||
continue
|
||||
new_config[virtual] = {"buildable": False}
|
||||
|
||||
# Update the provided scope
|
||||
spack.config.set(
|
||||
"packages",
|
||||
spack.config.merge_yaml(spack.config.get("packages", scope=scope), new_config),
|
||||
scope=scope,
|
||||
)
|
||||
|
||||
return list(new_config.keys())
|
||||
|
||||
|
||||
def _windows_drive() -> str:
|
||||
"""Return Windows drive string extracted from the PROGRAMFILES environment variable,
|
||||
which is guaranteed to be defined for all logins.
|
||||
|
@@ -12,7 +12,7 @@
|
||||
import re
|
||||
import sys
|
||||
import warnings
|
||||
from typing import Dict, List, Optional, Set, Tuple
|
||||
from typing import Dict, List, Optional, Set, Tuple, Type
|
||||
|
||||
import llnl.util.filesystem
|
||||
import llnl.util.lang
|
||||
@@ -200,7 +200,7 @@ class Finder:
|
||||
def default_path_hints(self) -> List[str]:
|
||||
return []
|
||||
|
||||
def search_patterns(self, *, pkg: "spack.package_base.PackageBase") -> List[str]:
|
||||
def search_patterns(self, *, pkg: Type["spack.package_base.PackageBase"]) -> List[str]:
|
||||
"""Returns the list of patterns used to match candidate files.
|
||||
|
||||
Args:
|
||||
@@ -226,7 +226,7 @@ def prefix_from_path(self, *, path: str) -> str:
|
||||
raise NotImplementedError("must be implemented by derived classes")
|
||||
|
||||
def detect_specs(
|
||||
self, *, pkg: "spack.package_base.PackageBase", paths: List[str]
|
||||
self, *, pkg: Type["spack.package_base.PackageBase"], paths: List[str]
|
||||
) -> List[DetectedPackage]:
|
||||
"""Given a list of files matching the search patterns, returns a list of detected specs.
|
||||
|
||||
@@ -327,7 +327,7 @@ class ExecutablesFinder(Finder):
|
||||
def default_path_hints(self) -> List[str]:
|
||||
return spack.util.environment.get_path("PATH")
|
||||
|
||||
def search_patterns(self, *, pkg: "spack.package_base.PackageBase") -> List[str]:
|
||||
def search_patterns(self, *, pkg: Type["spack.package_base.PackageBase"]) -> List[str]:
|
||||
result = []
|
||||
if hasattr(pkg, "executables") and hasattr(pkg, "platform_executables"):
|
||||
result = pkg.platform_executables()
|
||||
@@ -356,7 +356,7 @@ class LibrariesFinder(Finder):
|
||||
DYLD_LIBRARY_PATH, DYLD_FALLBACK_LIBRARY_PATH, and standard system library paths
|
||||
"""
|
||||
|
||||
def search_patterns(self, *, pkg: "spack.package_base.PackageBase") -> List[str]:
|
||||
def search_patterns(self, *, pkg: Type["spack.package_base.PackageBase"]) -> List[str]:
|
||||
result = []
|
||||
if hasattr(pkg, "libraries"):
|
||||
result = pkg.libraries
|
||||
|
@@ -90,14 +90,14 @@ class OpenMpi(Package):
|
||||
_patch_order_index = 0
|
||||
|
||||
|
||||
SpecType = Union["spack.spec.Spec", str]
|
||||
SpecType = str
|
||||
DepType = Union[Tuple[str, ...], str]
|
||||
WhenType = Optional[Union["spack.spec.Spec", str, bool]]
|
||||
Patcher = Callable[[Union["spack.package_base.PackageBase", Dependency]], None]
|
||||
PatchesType = Optional[Union[Patcher, str, List[Union[Patcher, str]]]]
|
||||
|
||||
|
||||
SUPPORTED_LANGUAGES = ("fortran", "cxx")
|
||||
SUPPORTED_LANGUAGES = ("fortran", "cxx", "c")
|
||||
|
||||
|
||||
def _make_when_spec(value: WhenType) -> Optional["spack.spec.Spec"]:
|
||||
@@ -475,7 +475,7 @@ def _execute_version(pkg, ver, **kwargs):
|
||||
|
||||
def _depends_on(
|
||||
pkg: "spack.package_base.PackageBase",
|
||||
spec: SpecType,
|
||||
spec: "spack.spec.Spec",
|
||||
*,
|
||||
when: WhenType = None,
|
||||
type: DepType = dt.DEFAULT_TYPES,
|
||||
@@ -485,11 +485,10 @@ def _depends_on(
|
||||
if not when_spec:
|
||||
return
|
||||
|
||||
dep_spec = spack.spec.Spec(spec)
|
||||
if not dep_spec.name:
|
||||
raise DependencyError("Invalid dependency specification in package '%s':" % pkg.name, spec)
|
||||
if pkg.name == dep_spec.name:
|
||||
raise CircularReferenceError("Package '%s' cannot depend on itself." % pkg.name)
|
||||
if not spec.name:
|
||||
raise DependencyError(f"Invalid dependency specification in package '{pkg.name}':", spec)
|
||||
if pkg.name == spec.name:
|
||||
raise CircularReferenceError(f"Package '{pkg.name}' cannot depend on itself.")
|
||||
|
||||
depflag = dt.canonicalize(type)
|
||||
|
||||
@@ -505,7 +504,7 @@ def _depends_on(
|
||||
# ensure `Spec.virtual` is a valid thing to call in a directive.
|
||||
# For now, we comment out the following check to allow for virtual packages
|
||||
# with package files.
|
||||
# if patches and dep_spec.virtual:
|
||||
# if patches and spec.virtual:
|
||||
# raise DependencyPatchError("Cannot patch a virtual dependency.")
|
||||
|
||||
# ensure patches is a list
|
||||
@@ -520,13 +519,13 @@ def _depends_on(
|
||||
|
||||
# this is where we actually add the dependency to this package
|
||||
deps_by_name = pkg.dependencies.setdefault(when_spec, {})
|
||||
dependency = deps_by_name.get(dep_spec.name)
|
||||
dependency = deps_by_name.get(spec.name)
|
||||
|
||||
if not dependency:
|
||||
dependency = Dependency(pkg, dep_spec, depflag=depflag)
|
||||
deps_by_name[dep_spec.name] = dependency
|
||||
dependency = Dependency(pkg, spec, depflag=depflag)
|
||||
deps_by_name[spec.name] = dependency
|
||||
else:
|
||||
dependency.spec.constrain(dep_spec, deps=False)
|
||||
dependency.spec.constrain(spec, deps=False)
|
||||
dependency.depflag |= depflag
|
||||
|
||||
# apply patches to the dependency
|
||||
@@ -591,12 +590,13 @@ def depends_on(
|
||||
@see The section "Dependency specs" in the Spack Packaging Guide.
|
||||
|
||||
"""
|
||||
if spack.spec.Spec(spec).name in SUPPORTED_LANGUAGES:
|
||||
dep_spec = spack.spec.Spec(spec)
|
||||
if dep_spec.name in SUPPORTED_LANGUAGES:
|
||||
assert type == "build", "languages must be of 'build' type"
|
||||
return _language(lang_spec_str=spec, when=when)
|
||||
|
||||
def _execute_depends_on(pkg: "spack.package_base.PackageBase"):
|
||||
_depends_on(pkg, spec, when=when, type=type, patches=patches)
|
||||
_depends_on(pkg, dep_spec, when=when, type=type, patches=patches)
|
||||
|
||||
return _execute_depends_on
|
||||
|
||||
@@ -666,25 +666,24 @@ def extends(spec, when=None, type=("build", "run"), patches=None):
|
||||
|
||||
keyword arguments can be passed to extends() so that extension
|
||||
packages can pass parameters to the extendee's extension
|
||||
mechanism.
|
||||
|
||||
"""
|
||||
mechanism."""
|
||||
|
||||
def _execute_extends(pkg):
|
||||
when_spec = _make_when_spec(when)
|
||||
if not when_spec:
|
||||
return
|
||||
|
||||
_depends_on(pkg, spec, when=when, type=type, patches=patches)
|
||||
spec_obj = spack.spec.Spec(spec)
|
||||
dep_spec = spack.spec.Spec(spec)
|
||||
|
||||
_depends_on(pkg, dep_spec, when=when, type=type, patches=patches)
|
||||
|
||||
# When extending python, also add a dependency on python-venv. This is done so that
|
||||
# Spack environment views are Python virtual environments.
|
||||
if spec_obj.name == "python" and not pkg.name == "python-venv":
|
||||
_depends_on(pkg, "python-venv", when=when, type=("build", "run"))
|
||||
if dep_spec.name == "python" and not pkg.name == "python-venv":
|
||||
_depends_on(pkg, spack.spec.Spec("python-venv"), when=when, type=("build", "run"))
|
||||
|
||||
# TODO: the values of the extendees dictionary are not used. Remove in next refactor.
|
||||
pkg.extendees[spec_obj.name] = (spec_obj, None)
|
||||
pkg.extendees[dep_spec.name] = (dep_spec, None)
|
||||
|
||||
return _execute_extends
|
||||
|
||||
|
@@ -5,7 +5,7 @@
|
||||
import collections
|
||||
import collections.abc
|
||||
import contextlib
|
||||
import copy
|
||||
import errno
|
||||
import os
|
||||
import pathlib
|
||||
import re
|
||||
@@ -269,9 +269,7 @@ def root(name):
|
||||
|
||||
def exists(name):
|
||||
"""Whether an environment with this name exists or not."""
|
||||
if not valid_env_name(name):
|
||||
return False
|
||||
return os.path.isdir(root(name))
|
||||
return valid_env_name(name) and os.path.isdir(_root(name))
|
||||
|
||||
|
||||
def active(name):
|
||||
@@ -530,8 +528,8 @@ def _read_yaml(str_or_file):
|
||||
)
|
||||
|
||||
filename = getattr(str_or_file, "name", None)
|
||||
default_data = spack.config.validate(data, spack.schema.env.schema, filename)
|
||||
return data, default_data
|
||||
spack.config.validate(data, spack.schema.env.schema, filename)
|
||||
return data
|
||||
|
||||
|
||||
def _write_yaml(data, str_or_file):
|
||||
@@ -791,6 +789,23 @@ def regenerate(self, concrete_roots: List[Spec]) -> None:
|
||||
root_dirname = os.path.dirname(self.root)
|
||||
tmp_symlink_name = os.path.join(root_dirname, "._view_link")
|
||||
|
||||
# Remove self.root if is it an empty dir, since we need a symlink there. Note that rmdir
|
||||
# fails if self.root is a symlink.
|
||||
try:
|
||||
os.rmdir(self.root)
|
||||
except (FileNotFoundError, NotADirectoryError):
|
||||
pass
|
||||
except OSError as e:
|
||||
if e.errno == errno.ENOTEMPTY:
|
||||
msg = "it is a non-empty directory"
|
||||
elif e.errno == errno.EACCES:
|
||||
msg = "of insufficient permissions"
|
||||
else:
|
||||
raise
|
||||
raise SpackEnvironmentViewError(
|
||||
f"The environment view in {self.root} cannot not be created because {msg}."
|
||||
) from e
|
||||
|
||||
# Create a new view
|
||||
try:
|
||||
fs.mkdirp(new_root)
|
||||
@@ -922,7 +937,7 @@ def __init__(self, manifest_dir: Union[str, pathlib.Path]) -> None:
|
||||
def _load_manifest_file(self):
|
||||
"""Instantiate and load the manifest file contents into memory."""
|
||||
with lk.ReadTransaction(self.txlock):
|
||||
self.manifest = EnvironmentManifestFile(self.path)
|
||||
self.manifest = EnvironmentManifestFile(self.path, self.name)
|
||||
with self.manifest.use_config():
|
||||
self._read()
|
||||
|
||||
@@ -959,18 +974,25 @@ def write_transaction(self):
|
||||
"""Get a write lock context manager for use in a `with` block."""
|
||||
return lk.WriteTransaction(self.txlock, acquire=self._re_read)
|
||||
|
||||
def _process_definition(self, item):
|
||||
def _process_definition(self, entry):
|
||||
"""Process a single spec definition item."""
|
||||
entry = copy.deepcopy(item)
|
||||
when = _eval_conditional(entry.pop("when", "True"))
|
||||
assert len(entry) == 1
|
||||
when_string = entry.get("when")
|
||||
if when_string is not None:
|
||||
when = _eval_conditional(when_string)
|
||||
assert len([x for x in entry if x != "when"]) == 1
|
||||
else:
|
||||
when = True
|
||||
assert len(entry) == 1
|
||||
|
||||
if when:
|
||||
name, spec_list = next(iter(entry.items()))
|
||||
user_specs = SpecList(name, spec_list, self.spec_lists.copy())
|
||||
if name in self.spec_lists:
|
||||
self.spec_lists[name].extend(user_specs)
|
||||
else:
|
||||
self.spec_lists[name] = user_specs
|
||||
for name, spec_list in entry.items():
|
||||
if name == "when":
|
||||
continue
|
||||
user_specs = SpecList(name, spec_list, self.spec_lists.copy())
|
||||
if name in self.spec_lists:
|
||||
self.spec_lists[name].extend(user_specs)
|
||||
else:
|
||||
self.spec_lists[name] = user_specs
|
||||
|
||||
def _process_view(self, env_view: Optional[Union[bool, str, Dict]]):
|
||||
"""Process view option(s), which can be boolean, string, or None.
|
||||
@@ -2753,10 +2775,11 @@ def from_lockfile(manifest_dir: Union[pathlib.Path, str]) -> "EnvironmentManifes
|
||||
manifest.flush()
|
||||
return manifest
|
||||
|
||||
def __init__(self, manifest_dir: Union[pathlib.Path, str]) -> None:
|
||||
def __init__(self, manifest_dir: Union[pathlib.Path, str], name: Optional[str] = None) -> None:
|
||||
self.manifest_dir = pathlib.Path(manifest_dir)
|
||||
self.name = name or str(manifest_dir)
|
||||
self.manifest_file = self.manifest_dir / manifest_name
|
||||
self.scope_name = f"env:{environment_name(self.manifest_dir)}"
|
||||
self.scope_name = f"env:{self.name}"
|
||||
self.config_stage_dir = os.path.join(env_subdir_path(manifest_dir), "config")
|
||||
|
||||
#: Configuration scopes associated with this environment. Note that these are not
|
||||
@@ -2768,12 +2791,8 @@ def __init__(self, manifest_dir: Union[pathlib.Path, str]) -> None:
|
||||
raise SpackEnvironmentError(msg)
|
||||
|
||||
with self.manifest_file.open() as f:
|
||||
raw, with_defaults_added = _read_yaml(f)
|
||||
self.yaml_content = _read_yaml(f)
|
||||
|
||||
#: Pristine YAML content, without defaults being added
|
||||
self.pristine_yaml_content = raw
|
||||
#: YAML content with defaults added by Spack, if they're missing
|
||||
self.yaml_content = with_defaults_added
|
||||
self.changed = False
|
||||
|
||||
def _all_matches(self, user_spec: str) -> List[str]:
|
||||
@@ -2787,7 +2806,7 @@ def _all_matches(self, user_spec: str) -> List[str]:
|
||||
ValueError: if no equivalent match is found
|
||||
"""
|
||||
result = []
|
||||
for yaml_spec_str in self.pristine_configuration["specs"]:
|
||||
for yaml_spec_str in self.configuration["specs"]:
|
||||
if Spec(yaml_spec_str) == Spec(user_spec):
|
||||
result.append(yaml_spec_str)
|
||||
|
||||
@@ -2802,7 +2821,6 @@ def add_user_spec(self, user_spec: str) -> None:
|
||||
Args:
|
||||
user_spec: user spec to be appended
|
||||
"""
|
||||
self.pristine_configuration.setdefault("specs", []).append(user_spec)
|
||||
self.configuration.setdefault("specs", []).append(user_spec)
|
||||
self.changed = True
|
||||
|
||||
@@ -2817,7 +2835,6 @@ def remove_user_spec(self, user_spec: str) -> None:
|
||||
"""
|
||||
try:
|
||||
for key in self._all_matches(user_spec):
|
||||
self.pristine_configuration["specs"].remove(key)
|
||||
self.configuration["specs"].remove(key)
|
||||
except ValueError as e:
|
||||
msg = f"cannot remove {user_spec} from {self}, no such spec exists"
|
||||
@@ -2835,7 +2852,6 @@ def override_user_spec(self, user_spec: str, idx: int) -> None:
|
||||
SpackEnvironmentError: when the user spec cannot be overridden
|
||||
"""
|
||||
try:
|
||||
self.pristine_configuration["specs"][idx] = user_spec
|
||||
self.configuration["specs"][idx] = user_spec
|
||||
except ValueError as e:
|
||||
msg = f"cannot override {user_spec} from {self}"
|
||||
@@ -2848,10 +2864,10 @@ def set_include_concrete(self, include_concrete: List[str]) -> None:
|
||||
Args:
|
||||
include_concrete: list of already existing concrete environments to include
|
||||
"""
|
||||
self.pristine_configuration[included_concrete_name] = []
|
||||
self.configuration[included_concrete_name] = []
|
||||
|
||||
for env_path in include_concrete:
|
||||
self.pristine_configuration[included_concrete_name].append(env_path)
|
||||
self.configuration[included_concrete_name].append(env_path)
|
||||
|
||||
self.changed = True
|
||||
|
||||
@@ -2865,14 +2881,13 @@ def add_definition(self, user_spec: str, list_name: str) -> None:
|
||||
Raises:
|
||||
SpackEnvironmentError: is no valid definition exists already
|
||||
"""
|
||||
defs = self.pristine_configuration.get("definitions", [])
|
||||
defs = self.configuration.get("definitions", [])
|
||||
msg = f"cannot add {user_spec} to the '{list_name}' definition, no valid list exists"
|
||||
|
||||
for idx, item in self._iterate_on_definitions(defs, list_name=list_name, err_msg=msg):
|
||||
item[list_name].append(user_spec)
|
||||
break
|
||||
|
||||
self.configuration["definitions"][idx][list_name].append(user_spec)
|
||||
self.changed = True
|
||||
|
||||
def remove_definition(self, user_spec: str, list_name: str) -> None:
|
||||
@@ -2886,7 +2901,7 @@ def remove_definition(self, user_spec: str, list_name: str) -> None:
|
||||
SpackEnvironmentError: if the user spec cannot be removed from the list,
|
||||
or the list does not exist
|
||||
"""
|
||||
defs = self.pristine_configuration.get("definitions", [])
|
||||
defs = self.configuration.get("definitions", [])
|
||||
msg = (
|
||||
f"cannot remove {user_spec} from the '{list_name}' definition, "
|
||||
f"no valid list exists"
|
||||
@@ -2899,7 +2914,6 @@ def remove_definition(self, user_spec: str, list_name: str) -> None:
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
self.configuration["definitions"][idx][list_name].remove(user_spec)
|
||||
self.changed = True
|
||||
|
||||
def override_definition(self, user_spec: str, *, override: str, list_name: str) -> None:
|
||||
@@ -2914,7 +2928,7 @@ def override_definition(self, user_spec: str, *, override: str, list_name: str)
|
||||
Raises:
|
||||
SpackEnvironmentError: if the user spec cannot be overridden
|
||||
"""
|
||||
defs = self.pristine_configuration.get("definitions", [])
|
||||
defs = self.configuration.get("definitions", [])
|
||||
msg = f"cannot override {user_spec} with {override} in the '{list_name}' definition"
|
||||
|
||||
for idx, item in self._iterate_on_definitions(defs, list_name=list_name, err_msg=msg):
|
||||
@@ -2925,7 +2939,6 @@ def override_definition(self, user_spec: str, *, override: str, list_name: str)
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
self.configuration["definitions"][idx][list_name][sub_index] = override
|
||||
self.changed = True
|
||||
|
||||
def _iterate_on_definitions(self, definitions, *, list_name, err_msg):
|
||||
@@ -2957,7 +2970,6 @@ def set_default_view(self, view: Union[bool, str, pathlib.Path, Dict[str, str]])
|
||||
True the default view is used for the environment, if False there's no view.
|
||||
"""
|
||||
if isinstance(view, dict):
|
||||
self.pristine_configuration["view"][default_view_name].update(view)
|
||||
self.configuration["view"][default_view_name].update(view)
|
||||
self.changed = True
|
||||
return
|
||||
@@ -2965,15 +2977,13 @@ def set_default_view(self, view: Union[bool, str, pathlib.Path, Dict[str, str]])
|
||||
if not isinstance(view, bool):
|
||||
view = str(view)
|
||||
|
||||
self.pristine_configuration["view"] = view
|
||||
self.configuration["view"] = view
|
||||
self.changed = True
|
||||
|
||||
def remove_default_view(self) -> None:
|
||||
"""Removes the default view from the manifest file"""
|
||||
view_data = self.pristine_configuration.get("view")
|
||||
view_data = self.configuration.get("view")
|
||||
if isinstance(view_data, collections.abc.Mapping):
|
||||
self.pristine_configuration["view"].pop(default_view_name)
|
||||
self.configuration["view"].pop(default_view_name)
|
||||
self.changed = True
|
||||
return
|
||||
@@ -2986,17 +2996,12 @@ def flush(self) -> None:
|
||||
return
|
||||
|
||||
with fs.write_tmp_and_move(os.path.realpath(self.manifest_file)) as f:
|
||||
_write_yaml(self.pristine_yaml_content, f)
|
||||
_write_yaml(self.yaml_content, f)
|
||||
self.changed = False
|
||||
|
||||
@property
|
||||
def pristine_configuration(self):
|
||||
"""Return the dictionaries in the pristine YAML, without the top level attribute"""
|
||||
return self.pristine_yaml_content[TOP_LEVEL_KEY]
|
||||
|
||||
@property
|
||||
def configuration(self):
|
||||
"""Return the dictionaries in the YAML, without the top level attribute"""
|
||||
"""Return the dictionaries in the pristine YAML, without the top level attribute"""
|
||||
return self.yaml_content[TOP_LEVEL_KEY]
|
||||
|
||||
def __len__(self):
|
||||
@@ -3033,7 +3038,6 @@ def included_config_scopes(self) -> List[spack.config.ConfigScope]:
|
||||
# load config scopes added via 'include:', in reverse so that
|
||||
# highest-precedence scopes are last.
|
||||
includes = self[TOP_LEVEL_KEY].get("include", [])
|
||||
env_name = environment_name(self.manifest_dir)
|
||||
missing = []
|
||||
for i, config_path in enumerate(reversed(includes)):
|
||||
# allow paths to contain spack config/environment variables, etc.
|
||||
@@ -3096,12 +3100,12 @@ def included_config_scopes(self) -> List[spack.config.ConfigScope]:
|
||||
|
||||
if os.path.isdir(config_path):
|
||||
# directories are treated as regular ConfigScopes
|
||||
config_name = "env:%s:%s" % (env_name, os.path.basename(config_path))
|
||||
config_name = f"env:{self.name}:{os.path.basename(config_path)}"
|
||||
tty.debug(f"Creating DirectoryConfigScope {config_name} for '{config_path}'")
|
||||
scopes.append(spack.config.DirectoryConfigScope(config_name, config_path))
|
||||
elif os.path.exists(config_path):
|
||||
# files are assumed to be SingleFileScopes
|
||||
config_name = "env:%s:%s" % (env_name, config_path)
|
||||
config_name = f"env:{self.name}:{config_path}"
|
||||
tty.debug(f"Creating SingleFileScope {config_name} for '{config_path}'")
|
||||
scopes.append(
|
||||
spack.config.SingleFileScope(
|
||||
|
@@ -444,8 +444,9 @@ def make_argument_parser(**kwargs):
|
||||
"--config-scope",
|
||||
dest="config_scopes",
|
||||
action="append",
|
||||
metavar="DIR",
|
||||
help="add a custom configuration scope",
|
||||
metavar="DIR|ENV",
|
||||
help="add directory or environment as read-only configuration scope, without activating "
|
||||
"the environment.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-d",
|
||||
|
@@ -35,6 +35,7 @@
|
||||
|
||||
import spack.compilers
|
||||
import spack.config
|
||||
import spack.dependency
|
||||
import spack.deptypes as dt
|
||||
import spack.directives
|
||||
import spack.directory_layout
|
||||
@@ -199,10 +200,10 @@ def __init__(cls, name, bases, attr_dict):
|
||||
# assumed to be detectable
|
||||
if hasattr(cls, "executables") or hasattr(cls, "libraries"):
|
||||
# Append a tag to each detectable package, so that finding them is faster
|
||||
if hasattr(cls, "tags"):
|
||||
getattr(cls, "tags").append(DetectablePackageMeta.TAG)
|
||||
else:
|
||||
if not hasattr(cls, "tags"):
|
||||
setattr(cls, "tags", [DetectablePackageMeta.TAG])
|
||||
elif DetectablePackageMeta.TAG not in cls.tags:
|
||||
cls.tags.append(DetectablePackageMeta.TAG)
|
||||
|
||||
@classmethod
|
||||
def platform_executables(cls):
|
||||
@@ -357,12 +358,14 @@ def on_package_attributes(**attr_dict):
|
||||
def _execute_under_condition(func):
|
||||
@functools.wraps(func)
|
||||
def _wrapper(instance, *args, **kwargs):
|
||||
# Support both builders and packages
|
||||
pkg = instance.pkg if isinstance(instance, spack.builder.Builder) else instance
|
||||
# If all the attributes have the value we require, then execute
|
||||
has_all_attributes = all([hasattr(instance, key) for key in attr_dict])
|
||||
has_all_attributes = all([hasattr(pkg, key) for key in attr_dict])
|
||||
if has_all_attributes:
|
||||
has_the_right_values = all(
|
||||
[
|
||||
getattr(instance, key) == value for key, value in attr_dict.items()
|
||||
getattr(pkg, key) == value for key, value in attr_dict.items()
|
||||
] # NOQA: ignore=E501
|
||||
)
|
||||
if has_the_right_values:
|
||||
|
@@ -9,7 +9,7 @@
|
||||
import os.path
|
||||
import pathlib
|
||||
import sys
|
||||
from typing import Any, Dict, Optional, Tuple, Type
|
||||
from typing import Any, Dict, Optional, Tuple, Type, Union
|
||||
|
||||
import llnl.util.filesystem
|
||||
from llnl.url import allowed_archive
|
||||
@@ -65,6 +65,9 @@ def apply_patch(
|
||||
patch(*args)
|
||||
|
||||
|
||||
PatchPackageType = Union["spack.package_base.PackageBase", Type["spack.package_base.PackageBase"]]
|
||||
|
||||
|
||||
class Patch:
|
||||
"""Base class for patches.
|
||||
|
||||
@@ -77,7 +80,7 @@ class Patch:
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
pkg: "spack.package_base.PackageBase",
|
||||
pkg: PatchPackageType,
|
||||
path_or_url: str,
|
||||
level: int,
|
||||
working_dir: str,
|
||||
@@ -159,7 +162,7 @@ class FilePatch(Patch):
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
pkg: "spack.package_base.PackageBase",
|
||||
pkg: PatchPackageType,
|
||||
relative_path: str,
|
||||
level: int,
|
||||
working_dir: str,
|
||||
@@ -183,7 +186,7 @@ def __init__(
|
||||
abs_path: Optional[str] = None
|
||||
# At different times we call FilePatch on instances and classes
|
||||
pkg_cls = pkg if inspect.isclass(pkg) else pkg.__class__
|
||||
for cls in inspect.getmro(pkg_cls):
|
||||
for cls in inspect.getmro(pkg_cls): # type: ignore
|
||||
if not hasattr(cls, "module"):
|
||||
# We've gone too far up the MRO
|
||||
break
|
||||
@@ -242,7 +245,7 @@ class UrlPatch(Patch):
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
pkg: "spack.package_base.PackageBase",
|
||||
pkg: PatchPackageType,
|
||||
url: str,
|
||||
level: int = 1,
|
||||
*,
|
||||
@@ -361,8 +364,9 @@ def from_dict(
|
||||
"""
|
||||
repository = repository or spack.repo.PATH
|
||||
owner = dictionary.get("owner")
|
||||
if "owner" not in dictionary:
|
||||
raise ValueError("Invalid patch dictionary: %s" % dictionary)
|
||||
if owner is None:
|
||||
raise ValueError(f"Invalid patch dictionary: {dictionary}")
|
||||
assert isinstance(owner, str)
|
||||
pkg_cls = repository.get_pkg_class(owner)
|
||||
|
||||
if "url" in dictionary:
|
||||
|
@@ -590,7 +590,7 @@ def __init__(
|
||||
self,
|
||||
package_checker: FastPackageChecker,
|
||||
namespace: str,
|
||||
cache: spack.caches.FileCacheType,
|
||||
cache: "spack.caches.FileCacheType",
|
||||
):
|
||||
self.checker = package_checker
|
||||
self.packages_path = self.checker.packages_path
|
||||
@@ -675,15 +675,22 @@ class RepoPath:
|
||||
repository.
|
||||
|
||||
Args:
|
||||
repos (list): list Repo objects or paths to put in this RepoPath
|
||||
repos: list Repo objects or paths to put in this RepoPath
|
||||
cache: file cache associated with this repository
|
||||
overrides: dict mapping package name to class attribute overrides for that package
|
||||
"""
|
||||
|
||||
def __init__(self, *repos, cache, overrides=None):
|
||||
self.repos = []
|
||||
def __init__(
|
||||
self,
|
||||
*repos: Union[str, "Repo"],
|
||||
cache: "spack.caches.FileCacheType",
|
||||
overrides: Optional[Dict[str, Any]] = None,
|
||||
) -> None:
|
||||
self.repos: List[Repo] = []
|
||||
self.by_namespace = nm.NamespaceTrie()
|
||||
self._provider_index = None
|
||||
self._patch_index = None
|
||||
self._tag_index = None
|
||||
self._provider_index: Optional[spack.provider_index.ProviderIndex] = None
|
||||
self._patch_index: Optional[spack.patch.PatchCache] = None
|
||||
self._tag_index: Optional[spack.tag.TagIndex] = None
|
||||
|
||||
# Add each repo to this path.
|
||||
for repo in repos:
|
||||
@@ -694,13 +701,13 @@ def __init__(self, *repos, cache, overrides=None):
|
||||
self.put_last(repo)
|
||||
except RepoError as e:
|
||||
tty.warn(
|
||||
"Failed to initialize repository: '%s'." % repo,
|
||||
f"Failed to initialize repository: '{repo}'.",
|
||||
e.message,
|
||||
"To remove the bad repository, run this command:",
|
||||
" spack repo rm %s" % repo,
|
||||
f" spack repo rm {repo}",
|
||||
)
|
||||
|
||||
def put_first(self, repo):
|
||||
def put_first(self, repo: "Repo") -> None:
|
||||
"""Add repo first in the search path."""
|
||||
if isinstance(repo, RepoPath):
|
||||
for r in reversed(repo.repos):
|
||||
@@ -728,50 +735,34 @@ def remove(self, repo):
|
||||
if repo in self.repos:
|
||||
self.repos.remove(repo)
|
||||
|
||||
def get_repo(self, namespace, default=NOT_PROVIDED):
|
||||
"""Get a repository by namespace.
|
||||
|
||||
Arguments:
|
||||
|
||||
namespace:
|
||||
|
||||
Look up this namespace in the RepoPath, and return it if found.
|
||||
|
||||
Optional Arguments:
|
||||
|
||||
default:
|
||||
|
||||
If default is provided, return it when the namespace
|
||||
isn't found. If not, raise an UnknownNamespaceError.
|
||||
"""
|
||||
def get_repo(self, namespace: str) -> "Repo":
|
||||
"""Get a repository by namespace."""
|
||||
full_namespace = python_package_for_repo(namespace)
|
||||
if full_namespace not in self.by_namespace:
|
||||
if default == NOT_PROVIDED:
|
||||
raise UnknownNamespaceError(namespace)
|
||||
return default
|
||||
raise UnknownNamespaceError(namespace)
|
||||
return self.by_namespace[full_namespace]
|
||||
|
||||
def first_repo(self):
|
||||
def first_repo(self) -> Optional["Repo"]:
|
||||
"""Get the first repo in precedence order."""
|
||||
return self.repos[0] if self.repos else None
|
||||
|
||||
@llnl.util.lang.memoized
|
||||
def _all_package_names_set(self, include_virtuals):
|
||||
def _all_package_names_set(self, include_virtuals) -> Set[str]:
|
||||
return {name for repo in self.repos for name in repo.all_package_names(include_virtuals)}
|
||||
|
||||
@llnl.util.lang.memoized
|
||||
def _all_package_names(self, include_virtuals):
|
||||
def _all_package_names(self, include_virtuals: bool) -> List[str]:
|
||||
"""Return all unique package names in all repositories."""
|
||||
return sorted(self._all_package_names_set(include_virtuals), key=lambda n: n.lower())
|
||||
|
||||
def all_package_names(self, include_virtuals=False):
|
||||
def all_package_names(self, include_virtuals: bool = False) -> List[str]:
|
||||
return self._all_package_names(include_virtuals)
|
||||
|
||||
def package_path(self, name):
|
||||
def package_path(self, name: str) -> str:
|
||||
"""Get path to package.py file for this repo."""
|
||||
return self.repo_for_pkg(name).package_path(name)
|
||||
|
||||
def all_package_paths(self):
|
||||
def all_package_paths(self) -> Generator[str, None, None]:
|
||||
for name in self.all_package_names():
|
||||
yield self.package_path(name)
|
||||
|
||||
@@ -787,53 +778,52 @@ def packages_with_tags(self, *tags: str, full: bool = False) -> Set[str]:
|
||||
for pkg in repo.packages_with_tags(*tags)
|
||||
}
|
||||
|
||||
def all_package_classes(self):
|
||||
def all_package_classes(self) -> Generator[Type["spack.package_base.PackageBase"], None, None]:
|
||||
for name in self.all_package_names():
|
||||
yield self.get_pkg_class(name)
|
||||
|
||||
@property
|
||||
def provider_index(self):
|
||||
def provider_index(self) -> spack.provider_index.ProviderIndex:
|
||||
"""Merged ProviderIndex from all Repos in the RepoPath."""
|
||||
if self._provider_index is None:
|
||||
self._provider_index = spack.provider_index.ProviderIndex(repository=self)
|
||||
for repo in reversed(self.repos):
|
||||
self._provider_index.merge(repo.provider_index)
|
||||
|
||||
return self._provider_index
|
||||
|
||||
@property
|
||||
def tag_index(self):
|
||||
def tag_index(self) -> spack.tag.TagIndex:
|
||||
"""Merged TagIndex from all Repos in the RepoPath."""
|
||||
if self._tag_index is None:
|
||||
self._tag_index = spack.tag.TagIndex(repository=self)
|
||||
for repo in reversed(self.repos):
|
||||
self._tag_index.merge(repo.tag_index)
|
||||
|
||||
return self._tag_index
|
||||
|
||||
@property
|
||||
def patch_index(self):
|
||||
def patch_index(self) -> spack.patch.PatchCache:
|
||||
"""Merged PatchIndex from all Repos in the RepoPath."""
|
||||
if self._patch_index is None:
|
||||
self._patch_index = spack.patch.PatchCache(repository=self)
|
||||
for repo in reversed(self.repos):
|
||||
self._patch_index.update(repo.patch_index)
|
||||
|
||||
return self._patch_index
|
||||
|
||||
@autospec
|
||||
def providers_for(self, vpkg_spec):
|
||||
def providers_for(self, virtual_spec: "spack.spec.Spec") -> List["spack.spec.Spec"]:
|
||||
providers = [
|
||||
spec
|
||||
for spec in self.provider_index.providers_for(vpkg_spec)
|
||||
for spec in self.provider_index.providers_for(virtual_spec)
|
||||
if spec.name in self._all_package_names_set(include_virtuals=False)
|
||||
]
|
||||
if not providers:
|
||||
raise UnknownPackageError(vpkg_spec.fullname)
|
||||
raise UnknownPackageError(virtual_spec.fullname)
|
||||
return providers
|
||||
|
||||
@autospec
|
||||
def extensions_for(self, extendee_spec):
|
||||
def extensions_for(
|
||||
self, extendee_spec: "spack.spec.Spec"
|
||||
) -> List["spack.package_base.PackageBase"]:
|
||||
return [
|
||||
pkg_cls(spack.spec.Spec(pkg_cls.name))
|
||||
for pkg_cls in self.all_package_classes()
|
||||
@@ -844,7 +834,7 @@ def last_mtime(self):
|
||||
"""Time a package file in this repo was last updated."""
|
||||
return max(repo.last_mtime() for repo in self.repos)
|
||||
|
||||
def repo_for_pkg(self, spec):
|
||||
def repo_for_pkg(self, spec: Union[str, "spack.spec.Spec"]) -> "Repo":
|
||||
"""Given a spec, get the repository for its package."""
|
||||
# We don't @_autospec this function b/c it's called very frequently
|
||||
# and we want to avoid parsing str's into Specs unnecessarily.
|
||||
@@ -869,17 +859,20 @@ def repo_for_pkg(self, spec):
|
||||
return repo
|
||||
|
||||
# If the package isn't in any repo, return the one with
|
||||
# highest precedence. This is for commands like `spack edit`
|
||||
# highest precedence. This is for commands like `spack edit`
|
||||
# that can operate on packages that don't exist yet.
|
||||
return self.first_repo()
|
||||
selected = self.first_repo()
|
||||
if selected is None:
|
||||
raise UnknownPackageError(name)
|
||||
return selected
|
||||
|
||||
def get(self, spec):
|
||||
def get(self, spec: "spack.spec.Spec") -> "spack.package_base.PackageBase":
|
||||
"""Returns the package associated with the supplied spec."""
|
||||
msg = "RepoPath.get can only be called on concrete specs"
|
||||
assert isinstance(spec, spack.spec.Spec) and spec.concrete, msg
|
||||
return self.repo_for_pkg(spec).get(spec)
|
||||
|
||||
def get_pkg_class(self, pkg_name):
|
||||
def get_pkg_class(self, pkg_name: str) -> Type["spack.package_base.PackageBase"]:
|
||||
"""Find a class for the spec's package and return the class object."""
|
||||
return self.repo_for_pkg(pkg_name).get_pkg_class(pkg_name)
|
||||
|
||||
@@ -892,26 +885,26 @@ def dump_provenance(self, spec, path):
|
||||
"""
|
||||
return self.repo_for_pkg(spec).dump_provenance(spec, path)
|
||||
|
||||
def dirname_for_package_name(self, pkg_name):
|
||||
def dirname_for_package_name(self, pkg_name: str) -> str:
|
||||
return self.repo_for_pkg(pkg_name).dirname_for_package_name(pkg_name)
|
||||
|
||||
def filename_for_package_name(self, pkg_name):
|
||||
def filename_for_package_name(self, pkg_name: str) -> str:
|
||||
return self.repo_for_pkg(pkg_name).filename_for_package_name(pkg_name)
|
||||
|
||||
def exists(self, pkg_name):
|
||||
def exists(self, pkg_name: str) -> bool:
|
||||
"""Whether package with the give name exists in the path's repos.
|
||||
|
||||
Note that virtual packages do not "exist".
|
||||
"""
|
||||
return any(repo.exists(pkg_name) for repo in self.repos)
|
||||
|
||||
def _have_name(self, pkg_name):
|
||||
def _have_name(self, pkg_name: str) -> bool:
|
||||
have_name = pkg_name is not None
|
||||
if have_name and not isinstance(pkg_name, str):
|
||||
raise ValueError("is_virtual(): expected package name, got %s" % type(pkg_name))
|
||||
raise ValueError(f"is_virtual(): expected package name, got {type(pkg_name)}")
|
||||
return have_name
|
||||
|
||||
def is_virtual(self, pkg_name):
|
||||
def is_virtual(self, pkg_name: str) -> bool:
|
||||
"""Return True if the package with this name is virtual, False otherwise.
|
||||
|
||||
This function use the provider index. If calling from a code block that
|
||||
@@ -923,7 +916,7 @@ def is_virtual(self, pkg_name):
|
||||
have_name = self._have_name(pkg_name)
|
||||
return have_name and pkg_name in self.provider_index
|
||||
|
||||
def is_virtual_safe(self, pkg_name):
|
||||
def is_virtual_safe(self, pkg_name: str) -> bool:
|
||||
"""Return True if the package with this name is virtual, False otherwise.
|
||||
|
||||
This function doesn't use the provider index.
|
||||
@@ -957,7 +950,7 @@ def __init__(
|
||||
self,
|
||||
root: str,
|
||||
*,
|
||||
cache: spack.caches.FileCacheType,
|
||||
cache: "spack.caches.FileCacheType",
|
||||
overrides: Optional[Dict[str, Any]] = None,
|
||||
) -> None:
|
||||
"""Instantiate a package repository from a filesystem path.
|
||||
@@ -1418,7 +1411,9 @@ def _path(configuration=None):
|
||||
return create(configuration=configuration)
|
||||
|
||||
|
||||
def create(configuration):
|
||||
def create(
|
||||
configuration: Union["spack.config.Configuration", llnl.util.lang.Singleton]
|
||||
) -> RepoPath:
|
||||
"""Create a RepoPath from a configuration object.
|
||||
|
||||
Args:
|
||||
@@ -1454,20 +1449,20 @@ def all_package_names(include_virtuals=False):
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def use_repositories(*paths_and_repos, **kwargs):
|
||||
def use_repositories(
|
||||
*paths_and_repos: Union[str, Repo], override: bool = True
|
||||
) -> Generator[RepoPath, None, None]:
|
||||
"""Use the repositories passed as arguments within the context manager.
|
||||
|
||||
Args:
|
||||
*paths_and_repos: paths to the repositories to be used, or
|
||||
already constructed Repo objects
|
||||
override (bool): if True use only the repositories passed as input,
|
||||
override: if True use only the repositories passed as input,
|
||||
if False add them to the top of the list of current repositories.
|
||||
Returns:
|
||||
Corresponding RepoPath object
|
||||
"""
|
||||
global PATH
|
||||
# TODO (Python 2.7): remove this kwargs on deprecation of Python 2.7 support
|
||||
override = kwargs.get("override", True)
|
||||
paths = [getattr(x, "root", x) for x in paths_and_repos]
|
||||
scope_name = "use-repo-{}".format(uuid.uuid4())
|
||||
repos_key = "repos:" if override else "repos"
|
||||
@@ -1476,7 +1471,8 @@ def use_repositories(*paths_and_repos, **kwargs):
|
||||
)
|
||||
PATH, saved = create(configuration=spack.config.CONFIG), PATH
|
||||
try:
|
||||
yield PATH
|
||||
with REPOS_FINDER.switch_repo(PATH): # type: ignore
|
||||
yield PATH
|
||||
finally:
|
||||
spack.config.CONFIG.remove_scope(scope_name=scope_name)
|
||||
PATH = saved
|
||||
@@ -1576,10 +1572,9 @@ class UnknownNamespaceError(UnknownEntityError):
|
||||
"""Raised when we encounter an unknown namespace"""
|
||||
|
||||
def __init__(self, namespace, name=None):
|
||||
msg, long_msg = "Unknown namespace: {}".format(namespace), None
|
||||
msg, long_msg = f"Unknown namespace: {namespace}", None
|
||||
if name == "yaml":
|
||||
long_msg = "Did you mean to specify a filename with './{}.{}'?"
|
||||
long_msg = long_msg.format(namespace, name)
|
||||
long_msg = f"Did you mean to specify a filename with './{namespace}.{name}'?"
|
||||
super().__init__(msg, long_msg)
|
||||
|
||||
|
||||
|
@@ -23,6 +23,7 @@
|
||||
|
||||
import llnl.util.lang
|
||||
import llnl.util.tty as tty
|
||||
from llnl.util.lang import elide_list
|
||||
|
||||
import spack
|
||||
import spack.binary_distribution
|
||||
@@ -621,8 +622,9 @@ def _external_config_with_implicit_externals(configuration):
|
||||
|
||||
|
||||
class ErrorHandler:
|
||||
def __init__(self, model):
|
||||
def __init__(self, model, input_specs: List[spack.spec.Spec]):
|
||||
self.model = model
|
||||
self.input_specs = input_specs
|
||||
self.full_model = None
|
||||
|
||||
def multiple_values_error(self, attribute, pkg):
|
||||
@@ -709,12 +711,13 @@ def handle_error(self, msg, *args):
|
||||
return msg
|
||||
|
||||
def message(self, errors) -> str:
|
||||
messages = [
|
||||
f" {idx+1: 2}. {self.handle_error(msg, *args)}"
|
||||
input_specs = ", ".join(elide_list([f"`{s}`" for s in self.input_specs], 5))
|
||||
header = f"failed to concretize {input_specs} for the following reasons:"
|
||||
messages = (
|
||||
f" {idx+1:2}. {self.handle_error(msg, *args)}"
|
||||
for idx, (_, msg, args) in enumerate(errors)
|
||||
]
|
||||
header = "concretization failed for the following reasons:\n"
|
||||
return "\n".join([header] + messages)
|
||||
)
|
||||
return "\n".join((header, *messages))
|
||||
|
||||
def raise_if_errors(self):
|
||||
initial_error_args = extract_args(self.model, "error")
|
||||
@@ -750,7 +753,7 @@ def on_model(model):
|
||||
f"unexpected error during concretization [{str(e)}]. "
|
||||
f"Please report a bug at https://github.com/spack/spack/issues"
|
||||
)
|
||||
raise spack.error.SpackError(msg)
|
||||
raise spack.error.SpackError(msg) from e
|
||||
raise UnsatisfiableSpecError(msg)
|
||||
|
||||
|
||||
@@ -894,7 +897,7 @@ def on_model(model):
|
||||
min_cost, best_model = min(models)
|
||||
|
||||
# first check for errors
|
||||
error_handler = ErrorHandler(best_model)
|
||||
error_handler = ErrorHandler(best_model, specs)
|
||||
error_handler.raise_if_errors()
|
||||
|
||||
# build specs from spec attributes in the model
|
||||
|
@@ -611,25 +611,18 @@ do_not_impose(EffectID, node(X, Package))
|
||||
% Virtual dependency weights
|
||||
%-----------------------------------------------------------------------------
|
||||
|
||||
% A provider may have different possible weights depending on whether it's an external
|
||||
% or not, or on preferences expressed in packages.yaml etc. This rule ensures that
|
||||
% A provider has different possible weights depending on its preference. This rule ensures that
|
||||
% we select the weight, among the possible ones, that minimizes the overall objective function.
|
||||
1 { provider_weight(DependencyNode, VirtualNode, Weight) :
|
||||
possible_provider_weight(DependencyNode, VirtualNode, Weight, _) } 1
|
||||
:- provider(DependencyNode, VirtualNode), internal_error("Package provider weights must be unique").
|
||||
|
||||
% A provider that is an external can use a weight of 0
|
||||
possible_provider_weight(DependencyNode, VirtualNode, 0, "external")
|
||||
:- provider(DependencyNode, VirtualNode),
|
||||
external(DependencyNode).
|
||||
|
||||
% A provider mentioned in the default configuration can use a weight
|
||||
% according to its priority in the list of providers
|
||||
% Any configured provider has a weight based on index in the preference list
|
||||
possible_provider_weight(node(ProviderID, Provider), node(VirtualID, Virtual), Weight, "default")
|
||||
:- provider(node(ProviderID, Provider), node(VirtualID, Virtual)),
|
||||
default_provider_preference(Virtual, Provider, Weight).
|
||||
|
||||
% Any provider can use 100 as a weight, which is very high and discourage its use
|
||||
% Any non-configured provider has a default weight of 100
|
||||
possible_provider_weight(node(ProviderID, Provider), VirtualNode, 100, "fallback")
|
||||
:- provider(node(ProviderID, Provider), VirtualNode).
|
||||
|
||||
@@ -1162,8 +1155,11 @@ target_weight(Target, 0)
|
||||
node_target_weight(PackageNode, MinWeight)
|
||||
:- attr("node", PackageNode),
|
||||
attr("node_target", PackageNode, Target),
|
||||
target(Target),
|
||||
MinWeight = #min { Weight : target_weight(Target, Weight) }.
|
||||
|
||||
:- attr("node_target", PackageNode, Target), not node_target_weight(PackageNode, _).
|
||||
|
||||
% compatibility rules for targets among nodes
|
||||
node_target_match(ParentNode, DependencyNode)
|
||||
:- attr("depends_on", ParentNode, DependencyNode, Type), Type != "build",
|
||||
|
@@ -12,6 +12,7 @@
|
||||
%=============================================================================
|
||||
|
||||
% macOS
|
||||
os_compatible("sequoia", "sonoma").
|
||||
os_compatible("sonoma", "ventura").
|
||||
os_compatible("ventura", "monterey").
|
||||
os_compatible("monterey", "bigsur").
|
||||
|
@@ -1332,6 +1332,12 @@ def tree(
|
||||
if color is None:
|
||||
color = clr.get_color_when()
|
||||
|
||||
# reduce deptypes over all in-edges when covering nodes
|
||||
if show_types and cover == "nodes":
|
||||
deptype_lookup: Dict[str, dt.DepFlag] = collections.defaultdict(dt.DepFlag)
|
||||
for edge in traverse.traverse_edges(specs, cover="edges", deptype=deptypes, root=False):
|
||||
deptype_lookup[edge.spec.dag_hash()] |= edge.depflag
|
||||
|
||||
for d, dep_spec in traverse.traverse_tree(
|
||||
sorted(specs), cover=cover, deptype=deptypes, depth_first=depth_first, key=key
|
||||
):
|
||||
@@ -1358,11 +1364,7 @@ def tree(
|
||||
|
||||
if show_types:
|
||||
if cover == "nodes":
|
||||
# when only covering nodes, we merge dependency types
|
||||
# from all dependents before showing them.
|
||||
depflag = 0
|
||||
for ds in node.edges_from_dependents():
|
||||
depflag |= ds.depflag
|
||||
depflag = deptype_lookup[dep_spec.spec.dag_hash()]
|
||||
else:
|
||||
# when covering edges or paths, we show dependency
|
||||
# types only for the edge through which we visited
|
||||
@@ -4258,29 +4260,21 @@ def __getitem__(self, name: str):
|
||||
csv = query_parameters.pop().strip()
|
||||
query_parameters = re.split(r"\s*,\s*", csv)
|
||||
|
||||
# In some cases a package appears multiple times in the same DAG for *distinct*
|
||||
# specs. For example, a build-type dependency may itself depend on a package
|
||||
# the current spec depends on, but their specs may differ. Therefore we iterate
|
||||
# in an order here that prioritizes the build, test and runtime dependencies;
|
||||
# only when we don't find the package do we consider the full DAG.
|
||||
order = lambda: itertools.chain(
|
||||
self.traverse(deptype="link"),
|
||||
self.dependencies(deptype=dt.BUILD | dt.RUN | dt.TEST),
|
||||
self.traverse(), # fall back to a full search
|
||||
self.traverse_edges(deptype=dt.LINK, order="breadth", cover="edges"),
|
||||
self.edges_to_dependencies(depflag=dt.BUILD | dt.RUN | dt.TEST),
|
||||
self.traverse_edges(deptype=dt.ALL, order="breadth", cover="edges"),
|
||||
)
|
||||
|
||||
# Consider runtime dependencies and direct build/test deps before transitive dependencies,
|
||||
# and prefer matches closest to the root.
|
||||
try:
|
||||
child: Spec = next(
|
||||
itertools.chain(
|
||||
# Regular specs
|
||||
(x for x in order() if x.name == name),
|
||||
(
|
||||
x
|
||||
for x in order()
|
||||
if (not x.virtual)
|
||||
and any(name in edge.virtuals for edge in x.edges_from_dependents())
|
||||
),
|
||||
(x for x in order() if (not x.virtual) and x.package.provides(name)),
|
||||
e.spec
|
||||
for e in itertools.chain(
|
||||
(e for e in order() if e.spec.name == name or name in e.virtuals),
|
||||
# for historical reasons
|
||||
(e for e in order() if e.spec.concrete and e.spec.package.provides(name)),
|
||||
)
|
||||
)
|
||||
except StopIteration:
|
||||
@@ -4656,7 +4650,7 @@ def colored_str(self):
|
||||
spec_str = " ^".join(root_str + sorted_dependencies)
|
||||
return spec_str.strip()
|
||||
|
||||
def install_status(self):
|
||||
def install_status(self) -> InstallStatus:
|
||||
"""Helper for tree to print DB install status."""
|
||||
if not self.concrete:
|
||||
return InstallStatus.absent
|
||||
|
@@ -371,7 +371,6 @@ def use_store(
|
||||
data.update(extra_data)
|
||||
|
||||
# Swap the store with the one just constructed and return it
|
||||
ensure_singleton_created()
|
||||
spack.config.CONFIG.push_scope(
|
||||
spack.config.InternalConfigScope(name=scope_name, data={"config": {"install_tree": data}})
|
||||
)
|
||||
|
@@ -79,9 +79,11 @@ def restore(self):
|
||||
self.test_state.restore()
|
||||
spack.main.spack_working_dir = self.spack_working_dir
|
||||
env = pickle.load(self.serialized_env) if _SERIALIZE else self.env
|
||||
pkg = pickle.load(self.serialized_pkg) if _SERIALIZE else self.pkg
|
||||
if env:
|
||||
spack.environment.activate(env)
|
||||
# Order of operation is important, since the package might be retrieved
|
||||
# from a repo defined within the environment configuration
|
||||
pkg = pickle.load(self.serialized_pkg) if _SERIALIZE else self.pkg
|
||||
return pkg
|
||||
|
||||
|
||||
|
@@ -213,7 +213,9 @@ def test_satisfy_strict_constraint_when_not_concrete(architecture_tuple, constra
|
||||
str(archspec.cpu.host().family) != "x86_64", reason="tests are for x86_64 uarch ranges"
|
||||
)
|
||||
def test_concretize_target_ranges(root_target_range, dep_target_range, result, monkeypatch):
|
||||
spec = Spec(f"a %gcc@10 foobar=bar target={root_target_range} ^b target={dep_target_range}")
|
||||
spec = Spec(
|
||||
f"pkg-a %gcc@10 foobar=bar target={root_target_range} ^pkg-b target={dep_target_range}"
|
||||
)
|
||||
with spack.concretize.disable_compiler_existence_check():
|
||||
spec.concretize()
|
||||
assert spec.target == spec["b"].target == result
|
||||
assert spec.target == spec["pkg-b"].target == result
|
||||
|
@@ -105,11 +105,11 @@ def config_directory(tmpdir_factory):
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def default_config(tmpdir, config_directory, monkeypatch, install_mockery_mutable_config):
|
||||
# This fixture depends on install_mockery_mutable_config to ensure
|
||||
def default_config(tmpdir, config_directory, monkeypatch, install_mockery):
|
||||
# This fixture depends on install_mockery to ensure
|
||||
# there is a clear order of initialization. The substitution of the
|
||||
# config scopes here is done on top of the substitution that comes with
|
||||
# install_mockery_mutable_config
|
||||
# install_mockery
|
||||
mutable_dir = tmpdir.mkdir("mutable_config").join("tmp")
|
||||
config_directory.copy(mutable_dir)
|
||||
|
||||
@@ -398,9 +398,7 @@ def fake_dag_hash(spec, length=None):
|
||||
return "tal4c7h4z0gqmixb1eqa92mjoybxn5l6"[:length]
|
||||
|
||||
|
||||
@pytest.mark.usefixtures(
|
||||
"install_mockery_mutable_config", "mock_packages", "mock_fetch", "test_mirror"
|
||||
)
|
||||
@pytest.mark.usefixtures("install_mockery", "mock_packages", "mock_fetch", "test_mirror")
|
||||
def test_spec_needs_rebuild(monkeypatch, tmpdir):
|
||||
"""Make sure needs_rebuild properly compares remote hash
|
||||
against locally computed one, avoiding unnecessary rebuilds"""
|
||||
@@ -429,7 +427,7 @@ def test_spec_needs_rebuild(monkeypatch, tmpdir):
|
||||
assert rebuild
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("install_mockery_mutable_config", "mock_packages", "mock_fetch")
|
||||
@pytest.mark.usefixtures("install_mockery", "mock_packages", "mock_fetch")
|
||||
def test_generate_index_missing(monkeypatch, tmpdir, mutable_config):
|
||||
"""Ensure spack buildcache index only reports available packages"""
|
||||
|
||||
@@ -587,9 +585,7 @@ def test_update_sbang(tmpdir, test_mirror):
|
||||
str(archspec.cpu.host().family) != "x86_64",
|
||||
reason="test data uses gcc 4.5.0 which does not support aarch64",
|
||||
)
|
||||
def test_install_legacy_buildcache_layout(
|
||||
mutable_config, compiler_factory, install_mockery_mutable_config
|
||||
):
|
||||
def test_install_legacy_buildcache_layout(mutable_config, compiler_factory, install_mockery):
|
||||
"""Legacy buildcache layout involved a nested archive structure
|
||||
where the .spack file contained a repeated spec.json and another
|
||||
compressed archive file containing the install tree. This test
|
||||
|
@@ -228,3 +228,25 @@ def test_source_is_disabled(mutable_config):
|
||||
spack.config.add("bootstrap:trusted:{0}:{1}".format(conf["name"], False))
|
||||
with pytest.raises(ValueError):
|
||||
spack.bootstrap.core.source_is_enabled_or_raise(conf)
|
||||
|
||||
|
||||
@pytest.mark.regression("45247")
|
||||
def test_use_store_does_not_try_writing_outside_root(tmp_path, monkeypatch, mutable_config):
|
||||
"""Tests that when we use the 'use_store' context manager, there is no attempt at creating
|
||||
a Store outside the given root.
|
||||
"""
|
||||
initial_store = mutable_config.get("config:install_tree:root")
|
||||
user_store = tmp_path / "store"
|
||||
|
||||
fn = spack.store.Store.__init__
|
||||
|
||||
def _checked_init(self, root, *args, **kwargs):
|
||||
fn(self, root, *args, **kwargs)
|
||||
assert self.root == str(user_store)
|
||||
|
||||
monkeypatch.setattr(spack.store.Store, "__init__", _checked_init)
|
||||
|
||||
spack.store.reinitialize()
|
||||
with spack.store.use_store(user_store):
|
||||
assert spack.config.CONFIG.get("config:install_tree:root") == str(user_store)
|
||||
assert spack.config.CONFIG.get("config:install_tree:root") == initial_store
|
||||
|
@@ -177,7 +177,7 @@ def _set_wrong_cc(x):
|
||||
|
||||
|
||||
def test_setup_dependent_package_inherited_modules(
|
||||
config, working_env, mock_packages, install_mockery, mock_fetch
|
||||
working_env, mock_packages, install_mockery, mock_fetch
|
||||
):
|
||||
# This will raise on regression
|
||||
s = spack.spec.Spec("cmake-client-inheritor").concretized()
|
||||
@@ -457,14 +457,14 @@ def test_parallel_false_is_not_propagating(default_mock_concretization):
|
||||
# a foobar=bar (parallel = False)
|
||||
# |
|
||||
# b (parallel =True)
|
||||
s = default_mock_concretization("a foobar=bar")
|
||||
s = default_mock_concretization("pkg-a foobar=bar")
|
||||
|
||||
spack.build_environment.set_package_py_globals(s.package, context=Context.BUILD)
|
||||
assert s["a"].package.module.make_jobs == 1
|
||||
assert s["pkg-a"].package.module.make_jobs == 1
|
||||
|
||||
spack.build_environment.set_package_py_globals(s["b"].package, context=Context.BUILD)
|
||||
assert s["b"].package.module.make_jobs == spack.build_environment.determine_number_of_jobs(
|
||||
parallel=s["b"].package.parallel
|
||||
spack.build_environment.set_package_py_globals(s["pkg-b"].package, context=Context.BUILD)
|
||||
assert s["pkg-b"].package.module.make_jobs == spack.build_environment.determine_number_of_jobs(
|
||||
parallel=s["pkg-b"].package.parallel
|
||||
)
|
||||
|
||||
|
||||
|
@@ -94,10 +94,10 @@ def test_negative_ninja_check(self, input_dir, test_dir, concretize_and_setup):
|
||||
|
||||
|
||||
@pytest.mark.not_on_windows("autotools not available on windows")
|
||||
@pytest.mark.usefixtures("config", "mock_packages")
|
||||
@pytest.mark.usefixtures("mock_packages")
|
||||
class TestAutotoolsPackage:
|
||||
def test_with_or_without(self, default_mock_concretization):
|
||||
s = default_mock_concretization("a")
|
||||
s = default_mock_concretization("pkg-a")
|
||||
options = s.package.with_or_without("foo")
|
||||
|
||||
# Ensure that values that are not representing a feature
|
||||
@@ -129,7 +129,7 @@ def activate(value):
|
||||
assert "--without-lorem-ipsum" in options
|
||||
|
||||
def test_none_is_allowed(self, default_mock_concretization):
|
||||
s = default_mock_concretization("a foo=none")
|
||||
s = default_mock_concretization("pkg-a foo=none")
|
||||
options = s.package.with_or_without("foo")
|
||||
|
||||
# Ensure that values that are not representing a feature
|
||||
@@ -139,11 +139,9 @@ def test_none_is_allowed(self, default_mock_concretization):
|
||||
assert "--without-baz" in options
|
||||
assert "--no-fee" in options
|
||||
|
||||
def test_libtool_archive_files_are_deleted_by_default(
|
||||
self, default_mock_concretization, mutable_database
|
||||
):
|
||||
def test_libtool_archive_files_are_deleted_by_default(self, mutable_database):
|
||||
# Install a package that creates a mock libtool archive
|
||||
s = default_mock_concretization("libtool-deletion")
|
||||
s = Spec("libtool-deletion").concretized()
|
||||
s.package.do_install(explicit=True)
|
||||
|
||||
# Assert the libtool archive is not there and we have
|
||||
@@ -154,25 +152,23 @@ def test_libtool_archive_files_are_deleted_by_default(
|
||||
assert libtool_deletion_log
|
||||
|
||||
def test_libtool_archive_files_might_be_installed_on_demand(
|
||||
self, mutable_database, monkeypatch, default_mock_concretization
|
||||
self, mutable_database, monkeypatch
|
||||
):
|
||||
# Install a package that creates a mock libtool archive,
|
||||
# patch its package to preserve the installation
|
||||
s = default_mock_concretization("libtool-deletion")
|
||||
s = Spec("libtool-deletion").concretized()
|
||||
monkeypatch.setattr(type(s.package.builder), "install_libtool_archives", True)
|
||||
s.package.do_install(explicit=True)
|
||||
|
||||
# Assert libtool archives are installed
|
||||
assert os.path.exists(s.package.builder.libtool_archive_file)
|
||||
|
||||
def test_autotools_gnuconfig_replacement(self, default_mock_concretization, mutable_database):
|
||||
def test_autotools_gnuconfig_replacement(self, mutable_database):
|
||||
"""
|
||||
Tests whether only broken config.sub and config.guess are replaced with
|
||||
files from working alternatives from the gnuconfig package.
|
||||
"""
|
||||
s = default_mock_concretization(
|
||||
"autotools-config-replacement +patch_config_files +gnuconfig"
|
||||
)
|
||||
s = Spec("autotools-config-replacement +patch_config_files +gnuconfig").concretized()
|
||||
s.package.do_install()
|
||||
|
||||
with open(os.path.join(s.prefix.broken, "config.sub")) as f:
|
||||
@@ -187,15 +183,11 @@ def test_autotools_gnuconfig_replacement(self, default_mock_concretization, muta
|
||||
with open(os.path.join(s.prefix.working, "config.guess")) as f:
|
||||
assert "gnuconfig version of config.guess" not in f.read()
|
||||
|
||||
def test_autotools_gnuconfig_replacement_disabled(
|
||||
self, default_mock_concretization, mutable_database
|
||||
):
|
||||
def test_autotools_gnuconfig_replacement_disabled(self, mutable_database):
|
||||
"""
|
||||
Tests whether disabling patch_config_files
|
||||
"""
|
||||
s = default_mock_concretization(
|
||||
"autotools-config-replacement ~patch_config_files +gnuconfig"
|
||||
)
|
||||
s = Spec("autotools-config-replacement ~patch_config_files +gnuconfig").concretized()
|
||||
s.package.do_install()
|
||||
|
||||
with open(os.path.join(s.prefix.broken, "config.sub")) as f:
|
||||
|
@@ -199,7 +199,7 @@ def __call__(self, *args, **kwargs):
|
||||
assert "Unable to merge {0}".format(c1) in err
|
||||
|
||||
|
||||
def test_get_spec_filter_list(mutable_mock_env_path, config, mutable_mock_repo):
|
||||
def test_get_spec_filter_list(mutable_mock_env_path, mutable_mock_repo):
|
||||
"""Test that given an active environment and list of touched pkgs,
|
||||
we get the right list of possibly-changed env specs"""
|
||||
e1 = ev.create("test")
|
||||
@@ -253,7 +253,7 @@ def test_get_spec_filter_list(mutable_mock_env_path, config, mutable_mock_repo):
|
||||
|
||||
|
||||
@pytest.mark.regression("29947")
|
||||
def test_affected_specs_on_first_concretization(mutable_mock_env_path, mock_packages, config):
|
||||
def test_affected_specs_on_first_concretization(mutable_mock_env_path, mock_packages):
|
||||
e = ev.create("first_concretization")
|
||||
e.add("mpileaks~shared")
|
||||
e.add("mpileaks+shared")
|
||||
@@ -322,12 +322,12 @@ def test_ci_run_standalone_tests_missing_requirements(
|
||||
|
||||
@pytest.mark.not_on_windows("Reliance on bash script not supported on Windows")
|
||||
def test_ci_run_standalone_tests_not_installed_junit(
|
||||
tmp_path, repro_dir, working_env, default_mock_concretization, mock_test_stage, capfd
|
||||
tmp_path, repro_dir, working_env, mock_test_stage, capfd, mock_packages
|
||||
):
|
||||
log_file = tmp_path / "junit.xml"
|
||||
args = {
|
||||
"log_file": str(log_file),
|
||||
"job_spec": default_mock_concretization("printing-package"),
|
||||
"job_spec": spack.spec.Spec("printing-package").concretized(),
|
||||
"repro_dir": str(repro_dir),
|
||||
"fail_fast": True,
|
||||
}
|
||||
@@ -340,13 +340,13 @@ def test_ci_run_standalone_tests_not_installed_junit(
|
||||
|
||||
@pytest.mark.not_on_windows("Reliance on bash script not supported on Windows")
|
||||
def test_ci_run_standalone_tests_not_installed_cdash(
|
||||
tmp_path, repro_dir, working_env, default_mock_concretization, mock_test_stage, capfd
|
||||
tmp_path, repro_dir, working_env, mock_test_stage, capfd, mock_packages
|
||||
):
|
||||
"""Test run_standalone_tests with cdash and related options."""
|
||||
log_file = tmp_path / "junit.xml"
|
||||
args = {
|
||||
"log_file": str(log_file),
|
||||
"job_spec": default_mock_concretization("printing-package"),
|
||||
"job_spec": spack.spec.Spec("printing-package").concretized(),
|
||||
"repro_dir": str(repro_dir),
|
||||
}
|
||||
|
||||
|
@@ -48,11 +48,6 @@ def mock_get_specs_multiarch(database, monkeypatch):
|
||||
monkeypatch.setattr(spack.binary_distribution, "update_cache_and_get_specs", lambda: specs)
|
||||
|
||||
|
||||
def test_buildcache_preview_just_runs():
|
||||
# TODO: remove in Spack 0.21
|
||||
buildcache("preview", "mpileaks")
|
||||
|
||||
|
||||
@pytest.mark.db
|
||||
@pytest.mark.regression("13757")
|
||||
def test_buildcache_list_duplicates(mock_get_specs, capsys):
|
||||
@@ -189,12 +184,7 @@ def test_buildcache_autopush(tmp_path, install_mockery, mock_fetch):
|
||||
|
||||
|
||||
def test_buildcache_sync(
|
||||
mutable_mock_env_path,
|
||||
install_mockery_mutable_config,
|
||||
mock_packages,
|
||||
mock_fetch,
|
||||
mock_stage,
|
||||
tmpdir,
|
||||
mutable_mock_env_path, install_mockery, mock_packages, mock_fetch, mock_stage, tmpdir
|
||||
):
|
||||
"""
|
||||
Make sure buildcache sync works in an environment-aware manner, ignoring
|
||||
@@ -323,7 +313,7 @@ def manifest_insert(manifest, spec, dest_url):
|
||||
|
||||
def test_buildcache_create_install(
|
||||
mutable_mock_env_path,
|
||||
install_mockery_mutable_config,
|
||||
install_mockery,
|
||||
mock_packages,
|
||||
mock_fetch,
|
||||
mock_stage,
|
||||
|
@@ -83,7 +83,6 @@ def test_checksum_args(arguments, expected):
|
||||
assert check == expected
|
||||
|
||||
|
||||
@pytest.mark.not_on_windows("Not supported on Windows (yet)")
|
||||
@pytest.mark.parametrize(
|
||||
"arguments,expected",
|
||||
[
|
||||
|
@@ -106,24 +106,24 @@ def test_specs_staging(config, tmpdir):
|
||||
|
||||
"""
|
||||
builder = repo.MockRepositoryBuilder(tmpdir)
|
||||
builder.add_package("g")
|
||||
builder.add_package("f")
|
||||
builder.add_package("e")
|
||||
builder.add_package("d", dependencies=[("f", None, None), ("g", None, None)])
|
||||
builder.add_package("c")
|
||||
builder.add_package("b", dependencies=[("d", None, None), ("e", None, None)])
|
||||
builder.add_package("a", dependencies=[("b", None, None), ("c", None, None)])
|
||||
builder.add_package("pkg-g")
|
||||
builder.add_package("pkg-f")
|
||||
builder.add_package("pkg-e")
|
||||
builder.add_package("pkg-d", dependencies=[("pkg-f", None, None), ("pkg-g", None, None)])
|
||||
builder.add_package("pkg-c")
|
||||
builder.add_package("pkg-b", dependencies=[("pkg-d", None, None), ("pkg-e", None, None)])
|
||||
builder.add_package("pkg-a", dependencies=[("pkg-b", None, None), ("pkg-c", None, None)])
|
||||
|
||||
with repo.use_repositories(builder.root):
|
||||
spec_a = Spec("a").concretized()
|
||||
spec_a = Spec("pkg-a").concretized()
|
||||
|
||||
spec_a_label = ci._spec_ci_label(spec_a)
|
||||
spec_b_label = ci._spec_ci_label(spec_a["b"])
|
||||
spec_c_label = ci._spec_ci_label(spec_a["c"])
|
||||
spec_d_label = ci._spec_ci_label(spec_a["d"])
|
||||
spec_e_label = ci._spec_ci_label(spec_a["e"])
|
||||
spec_f_label = ci._spec_ci_label(spec_a["f"])
|
||||
spec_g_label = ci._spec_ci_label(spec_a["g"])
|
||||
spec_b_label = ci._spec_ci_label(spec_a["pkg-b"])
|
||||
spec_c_label = ci._spec_ci_label(spec_a["pkg-c"])
|
||||
spec_d_label = ci._spec_ci_label(spec_a["pkg-d"])
|
||||
spec_e_label = ci._spec_ci_label(spec_a["pkg-e"])
|
||||
spec_f_label = ci._spec_ci_label(spec_a["pkg-f"])
|
||||
spec_g_label = ci._spec_ci_label(spec_a["pkg-g"])
|
||||
|
||||
spec_labels, dependencies, stages = ci.stage_spec_jobs([spec_a])
|
||||
|
||||
@@ -748,7 +748,7 @@ def test_ci_rebuild_mock_success(
|
||||
tmpdir,
|
||||
working_env,
|
||||
mutable_mock_env_path,
|
||||
install_mockery_mutable_config,
|
||||
install_mockery,
|
||||
mock_gnupghome,
|
||||
mock_stage,
|
||||
mock_fetch,
|
||||
@@ -782,7 +782,7 @@ def test_ci_rebuild_mock_failure_to_push(
|
||||
tmpdir,
|
||||
working_env,
|
||||
mutable_mock_env_path,
|
||||
install_mockery_mutable_config,
|
||||
install_mockery,
|
||||
mock_gnupghome,
|
||||
mock_stage,
|
||||
mock_fetch,
|
||||
@@ -820,7 +820,7 @@ def test_ci_rebuild(
|
||||
tmpdir,
|
||||
working_env,
|
||||
mutable_mock_env_path,
|
||||
install_mockery_mutable_config,
|
||||
install_mockery,
|
||||
mock_packages,
|
||||
monkeypatch,
|
||||
mock_gnupghome,
|
||||
@@ -1019,7 +1019,7 @@ def fake_dl_method(spec, *args, **kwargs):
|
||||
def test_ci_generate_mirror_override(
|
||||
tmpdir,
|
||||
mutable_mock_env_path,
|
||||
install_mockery_mutable_config,
|
||||
install_mockery,
|
||||
mock_packages,
|
||||
mock_fetch,
|
||||
mock_stage,
|
||||
@@ -1104,7 +1104,7 @@ def test_ci_generate_mirror_override(
|
||||
def test_push_to_build_cache(
|
||||
tmpdir,
|
||||
mutable_mock_env_path,
|
||||
install_mockery_mutable_config,
|
||||
install_mockery,
|
||||
mock_packages,
|
||||
mock_fetch,
|
||||
mock_stage,
|
||||
@@ -1290,7 +1290,7 @@ def test_ci_generate_override_runner_attrs(
|
||||
spack:
|
||||
specs:
|
||||
- flatten-deps
|
||||
- a
|
||||
- pkg-a
|
||||
mirrors:
|
||||
some-mirror: https://my.fake.mirror
|
||||
ci:
|
||||
@@ -1307,12 +1307,12 @@ def test_ci_generate_override_runner_attrs(
|
||||
- match:
|
||||
- dependency-install
|
||||
- match:
|
||||
- a
|
||||
- pkg-a
|
||||
build-job:
|
||||
tags:
|
||||
- specific-a-2
|
||||
- match:
|
||||
- a
|
||||
- pkg-a
|
||||
build-job-remove:
|
||||
tags:
|
||||
- toplevel2
|
||||
@@ -1372,8 +1372,8 @@ def test_ci_generate_override_runner_attrs(
|
||||
assert global_vars["SPACK_CHECKOUT_VERSION"] == git_version or "v0.20.0.test0"
|
||||
|
||||
for ci_key in yaml_contents.keys():
|
||||
if ci_key.startswith("a"):
|
||||
# Make sure a's attributes override variables, and all the
|
||||
if ci_key.startswith("pkg-a"):
|
||||
# Make sure pkg-a's attributes override variables, and all the
|
||||
# scripts. Also, make sure the 'toplevel' tag doesn't
|
||||
# appear twice, but that a's specific extra tag does appear
|
||||
the_elt = yaml_contents[ci_key]
|
||||
@@ -1781,7 +1781,7 @@ def test_ci_generate_read_broken_specs_url(
|
||||
tmpdir, mutable_mock_env_path, install_mockery, mock_packages, monkeypatch, ci_base_environment
|
||||
):
|
||||
"""Verify that `broken-specs-url` works as intended"""
|
||||
spec_a = Spec("a")
|
||||
spec_a = Spec("pkg-a")
|
||||
spec_a.concretize()
|
||||
a_dag_hash = spec_a.dag_hash()
|
||||
|
||||
@@ -1807,7 +1807,7 @@ def test_ci_generate_read_broken_specs_url(
|
||||
spack:
|
||||
specs:
|
||||
- flatten-deps
|
||||
- a
|
||||
- pkg-a
|
||||
mirrors:
|
||||
some-mirror: https://my.fake.mirror
|
||||
ci:
|
||||
@@ -1815,9 +1815,9 @@ def test_ci_generate_read_broken_specs_url(
|
||||
pipeline-gen:
|
||||
- submapping:
|
||||
- match:
|
||||
- a
|
||||
- pkg-a
|
||||
- flatten-deps
|
||||
- b
|
||||
- pkg-b
|
||||
- dependency-install
|
||||
build-job:
|
||||
tags:
|
||||
|
@@ -72,7 +72,6 @@ def test_parse_spec_flags_with_spaces(specs, cflags, propagation, negated_varian
|
||||
assert "~{0}".format(v) in s
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("config")
|
||||
def test_match_spec_env(mock_packages, mutable_mock_env_path):
|
||||
"""
|
||||
Concretize a spec with non-default options in an environment. Make
|
||||
@@ -81,44 +80,42 @@ def test_match_spec_env(mock_packages, mutable_mock_env_path):
|
||||
"""
|
||||
# Initial sanity check: we are planning on choosing a non-default
|
||||
# value, so make sure that is in fact not the default.
|
||||
check_defaults = spack.cmd.parse_specs(["a"], concretize=True)[0]
|
||||
check_defaults = spack.cmd.parse_specs(["pkg-a"], concretize=True)[0]
|
||||
assert not check_defaults.satisfies("foobar=baz")
|
||||
|
||||
e = ev.create("test")
|
||||
e.add("a foobar=baz")
|
||||
e.add("pkg-a foobar=baz")
|
||||
e.concretize()
|
||||
with e:
|
||||
env_spec = spack.cmd.matching_spec_from_env(spack.cmd.parse_specs(["a"])[0])
|
||||
env_spec = spack.cmd.matching_spec_from_env(spack.cmd.parse_specs(["pkg-a"])[0])
|
||||
assert env_spec.satisfies("foobar=baz")
|
||||
assert env_spec.concrete
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("config")
|
||||
def test_multiple_env_match_raises_error(mock_packages, mutable_mock_env_path):
|
||||
e = ev.create("test")
|
||||
e.add("a foobar=baz")
|
||||
e.add("a foobar=fee")
|
||||
e.add("pkg-a foobar=baz")
|
||||
e.add("pkg-a foobar=fee")
|
||||
e.concretize()
|
||||
with e:
|
||||
with pytest.raises(ev.SpackEnvironmentError) as exc_info:
|
||||
spack.cmd.matching_spec_from_env(spack.cmd.parse_specs(["a"])[0])
|
||||
spack.cmd.matching_spec_from_env(spack.cmd.parse_specs(["pkg-a"])[0])
|
||||
|
||||
assert "matches multiple specs" in exc_info.value.message
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("config")
|
||||
def test_root_and_dep_match_returns_root(mock_packages, mutable_mock_env_path):
|
||||
e = ev.create("test")
|
||||
e.add("b@0.9")
|
||||
e.add("a foobar=bar") # Depends on b, should choose b@1.0
|
||||
e.add("pkg-b@0.9")
|
||||
e.add("pkg-a foobar=bar") # Depends on b, should choose b@1.0
|
||||
e.concretize()
|
||||
with e:
|
||||
# This query matches the root b and b as a dependency of a. In that
|
||||
# case the root instance should be preferred.
|
||||
env_spec1 = spack.cmd.matching_spec_from_env(spack.cmd.parse_specs(["b"])[0])
|
||||
env_spec1 = spack.cmd.matching_spec_from_env(spack.cmd.parse_specs(["pkg-b"])[0])
|
||||
assert env_spec1.satisfies("@0.9")
|
||||
|
||||
env_spec2 = spack.cmd.matching_spec_from_env(spack.cmd.parse_specs(["b@1.0"])[0])
|
||||
env_spec2 = spack.cmd.matching_spec_from_env(spack.cmd.parse_specs(["pkg-b@1.0"])[0])
|
||||
assert env_spec2
|
||||
|
||||
|
||||
|
@@ -10,7 +10,7 @@
|
||||
from spack import spack_version
|
||||
from spack.main import SpackCommand
|
||||
|
||||
pytestmark = pytest.mark.usefixtures("config", "mutable_mock_repo")
|
||||
pytestmark = pytest.mark.usefixtures("mutable_config", "mutable_mock_repo")
|
||||
|
||||
env = SpackCommand("env")
|
||||
add = SpackCommand("add")
|
||||
@@ -51,8 +51,8 @@ def test_concretize_root_test_dependencies_are_concretized(unify, mutable_mock_e
|
||||
|
||||
with ev.read("test") as e:
|
||||
e.unify = unify
|
||||
add("a")
|
||||
add("b")
|
||||
add("pkg-a")
|
||||
add("pkg-b")
|
||||
concretize("--test", "root")
|
||||
assert e.matching_spec("test-dependency")
|
||||
|
||||
|
@@ -640,4 +640,4 @@ def update_config(data):
|
||||
config("update", "-y", "config")
|
||||
|
||||
with ev.Environment(str(tmpdir)) as e:
|
||||
assert not e.manifest.pristine_yaml_content["spack"]["config"]["ccache"]
|
||||
assert not e.manifest.yaml_content["spack"]["config"]["ccache"]
|
||||
|
@@ -12,29 +12,29 @@
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def test_env(mutable_mock_env_path, config, mock_packages):
|
||||
def test_env(mutable_mock_env_path, mock_packages):
|
||||
ev.create("test")
|
||||
with ev.read("test") as e:
|
||||
e.add("a@2.0 foobar=bar ^b@1.0")
|
||||
e.add("a@1.0 foobar=bar ^b@0.9")
|
||||
e.add("pkg-a@2.0 foobar=bar ^pkg-b@1.0")
|
||||
e.add("pkg-a@1.0 foobar=bar ^pkg-b@0.9")
|
||||
e.concretize()
|
||||
e.write()
|
||||
|
||||
|
||||
def test_deconcretize_dep(test_env):
|
||||
with ev.read("test") as e:
|
||||
deconcretize("-y", "b@1.0")
|
||||
deconcretize("-y", "pkg-b@1.0")
|
||||
specs = [s for s, _ in e.concretized_specs()]
|
||||
|
||||
assert len(specs) == 1
|
||||
assert specs[0].satisfies("a@1.0")
|
||||
assert specs[0].satisfies("pkg-a@1.0")
|
||||
|
||||
|
||||
def test_deconcretize_all_dep(test_env):
|
||||
with ev.read("test") as e:
|
||||
with pytest.raises(SpackCommandError):
|
||||
deconcretize("-y", "b")
|
||||
deconcretize("-y", "--all", "b")
|
||||
deconcretize("-y", "pkg-b")
|
||||
deconcretize("-y", "--all", "pkg-b")
|
||||
specs = [s for s, _ in e.concretized_specs()]
|
||||
|
||||
assert len(specs) == 0
|
||||
@@ -42,27 +42,27 @@ def test_deconcretize_all_dep(test_env):
|
||||
|
||||
def test_deconcretize_root(test_env):
|
||||
with ev.read("test") as e:
|
||||
output = deconcretize("-y", "--root", "b@1.0")
|
||||
output = deconcretize("-y", "--root", "pkg-b@1.0")
|
||||
assert "No matching specs to deconcretize" in output
|
||||
assert len(e.concretized_order) == 2
|
||||
|
||||
deconcretize("-y", "--root", "a@2.0")
|
||||
deconcretize("-y", "--root", "pkg-a@2.0")
|
||||
specs = [s for s, _ in e.concretized_specs()]
|
||||
|
||||
assert len(specs) == 1
|
||||
assert specs[0].satisfies("a@1.0")
|
||||
assert specs[0].satisfies("pkg-a@1.0")
|
||||
|
||||
|
||||
def test_deconcretize_all_root(test_env):
|
||||
with ev.read("test") as e:
|
||||
with pytest.raises(SpackCommandError):
|
||||
deconcretize("-y", "--root", "a")
|
||||
deconcretize("-y", "--root", "pkg-a")
|
||||
|
||||
output = deconcretize("-y", "--root", "--all", "b")
|
||||
output = deconcretize("-y", "--root", "--all", "pkg-b")
|
||||
assert "No matching specs to deconcretize" in output
|
||||
assert len(e.concretized_order) == 2
|
||||
|
||||
deconcretize("-y", "--root", "--all", "a")
|
||||
deconcretize("-y", "--root", "--all", "pkg-a")
|
||||
specs = [s for s, _ in e.concretized_specs()]
|
||||
|
||||
assert len(specs) == 0
|
||||
|
@@ -14,8 +14,6 @@
|
||||
deprecate = SpackCommand("deprecate")
|
||||
find = SpackCommand("find")
|
||||
|
||||
pytestmark = pytest.mark.not_on_windows("does not run on windows")
|
||||
|
||||
|
||||
def test_deprecate(mock_packages, mock_archive, mock_fetch, install_mockery):
|
||||
install("libelf@0.8.13")
|
||||
|
@@ -20,10 +20,7 @@
|
||||
install = SpackCommand("install")
|
||||
env = SpackCommand("env")
|
||||
|
||||
pytestmark = [
|
||||
pytest.mark.not_on_windows("does not run on windows"),
|
||||
pytest.mark.disable_clean_stage_check,
|
||||
]
|
||||
pytestmark = [pytest.mark.disable_clean_stage_check]
|
||||
|
||||
|
||||
def test_dev_build_basics(tmpdir, install_mockery):
|
||||
@@ -96,7 +93,7 @@ def test_dev_build_until_last_phase(tmpdir, install_mockery):
|
||||
assert os.path.exists(str(tmpdir))
|
||||
|
||||
|
||||
def test_dev_build_before_until(tmpdir, install_mockery, capsys):
|
||||
def test_dev_build_before_until(tmpdir, install_mockery):
|
||||
spec = spack.spec.Spec(f"dev-build-test-install@0.0.0 dev_path={tmpdir}").concretized()
|
||||
|
||||
with tmpdir.as_cwd():
|
||||
@@ -129,7 +126,7 @@ def test_dev_build_drop_in(tmpdir, mock_packages, monkeypatch, install_mockery,
|
||||
monkeypatch.setattr(os, "execvp", print_spack_cc)
|
||||
with tmpdir.as_cwd():
|
||||
output = dev_build("-b", "edit", "--drop-in", "sh", "dev-build-test-install@0.0.0")
|
||||
assert "lib/spack/env" in output
|
||||
assert os.path.join("lib", "spack", "env") in output
|
||||
|
||||
|
||||
def test_dev_build_fails_already_installed(tmpdir, install_mockery):
|
||||
|
@@ -181,7 +181,6 @@ def test_diff_cmd(install_mockery, mock_fetch, mock_archive, mock_packages):
|
||||
assert ["hash", "mpileaks %s" % specB.dag_hash()] in c["b_not_a"]
|
||||
|
||||
|
||||
@pytest.mark.not_on_windows("Not supported on Windows (yet)")
|
||||
def test_load_first(install_mockery, mock_fetch, mock_archive, mock_packages):
|
||||
"""Test with and without the --first option"""
|
||||
install_cmd("mpileaks")
|
||||
|
@@ -15,9 +15,9 @@
|
||||
|
||||
|
||||
def test_edit_packages(monkeypatch, mock_packages: spack.repo.RepoPath):
|
||||
"""Test spack edit a b"""
|
||||
path_a = mock_packages.filename_for_package_name("a")
|
||||
path_b = mock_packages.filename_for_package_name("b")
|
||||
"""Test spack edit pkg-a pkg-b"""
|
||||
path_a = mock_packages.filename_for_package_name("pkg-a")
|
||||
path_b = mock_packages.filename_for_package_name("pkg-b")
|
||||
called = False
|
||||
|
||||
def editor(*args: str, **kwargs):
|
||||
@@ -27,7 +27,7 @@ def editor(*args: str, **kwargs):
|
||||
assert args[1] == path_b
|
||||
|
||||
monkeypatch.setattr(spack.util.editor, "editor", editor)
|
||||
edit("a", "b")
|
||||
edit("pkg-a", "pkg-b")
|
||||
assert called
|
||||
|
||||
|
||||
|
@@ -28,7 +28,9 @@
|
||||
import spack.package_base
|
||||
import spack.paths
|
||||
import spack.repo
|
||||
import spack.store
|
||||
import spack.util.spack_json as sjson
|
||||
import spack.util.spack_yaml
|
||||
from spack.cmd.env import _env_create
|
||||
from spack.main import SpackCommand, SpackCommandError
|
||||
from spack.spec import Spec
|
||||
@@ -40,7 +42,7 @@
|
||||
# TODO-27021
|
||||
# everything here uses the mock_env_path
|
||||
pytestmark = [
|
||||
pytest.mark.usefixtures("mutable_mock_env_path", "config", "mutable_mock_repo"),
|
||||
pytest.mark.usefixtures("mutable_config", "mutable_mock_env_path", "mutable_mock_repo"),
|
||||
pytest.mark.maybeslow,
|
||||
pytest.mark.not_on_windows("Envs unsupported on Window"),
|
||||
]
|
||||
@@ -501,7 +503,7 @@ def test_env_install_two_specs_same_dep(install_mockery, mock_fetch, tmpdir, cap
|
||||
"""\
|
||||
spack:
|
||||
specs:
|
||||
- a
|
||||
- pkg-a
|
||||
- depb
|
||||
"""
|
||||
)
|
||||
@@ -520,8 +522,8 @@ def test_env_install_two_specs_same_dep(install_mockery, mock_fetch, tmpdir, cap
|
||||
depb = spack.store.STORE.db.query_one("depb", installed=True)
|
||||
assert depb, "Expected depb to be installed"
|
||||
|
||||
a = spack.store.STORE.db.query_one("a", installed=True)
|
||||
assert a, "Expected a to be installed"
|
||||
a = spack.store.STORE.db.query_one("pkg-a", installed=True)
|
||||
assert a, "Expected pkg-a to be installed"
|
||||
|
||||
|
||||
def test_remove_after_concretize():
|
||||
@@ -812,7 +814,6 @@ def test_init_from_yaml(environment_from_manifest):
|
||||
assert not e2.specs_by_hash
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("config")
|
||||
def test_env_view_external_prefix(tmp_path, mutable_database, mock_packages):
|
||||
fake_prefix = tmp_path / "a-prefix"
|
||||
fake_bin = fake_prefix / "bin"
|
||||
@@ -825,7 +826,7 @@ def test_env_view_external_prefix(tmp_path, mutable_database, mock_packages):
|
||||
"""\
|
||||
spack:
|
||||
specs:
|
||||
- a
|
||||
- pkg-a
|
||||
view: true
|
||||
"""
|
||||
)
|
||||
@@ -833,9 +834,9 @@ def test_env_view_external_prefix(tmp_path, mutable_database, mock_packages):
|
||||
external_config = io.StringIO(
|
||||
"""\
|
||||
packages:
|
||||
a:
|
||||
pkg-a:
|
||||
externals:
|
||||
- spec: a@2.0
|
||||
- spec: pkg-a@2.0
|
||||
prefix: {a_prefix}
|
||||
buildable: false
|
||||
""".format(
|
||||
@@ -1559,7 +1560,6 @@ def test_uninstall_removes_from_env(mock_stage, mock_fetch, install_mockery):
|
||||
assert not test.user_specs
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("config")
|
||||
def test_indirect_build_dep(tmp_path):
|
||||
"""Simple case of X->Y->Z where Y is a build/link dep and Z is a
|
||||
build-only dep. Make sure this concrete DAG is preserved when writing the
|
||||
@@ -1587,7 +1587,6 @@ def test_indirect_build_dep(tmp_path):
|
||||
assert x_env_spec == x_concretized
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("config")
|
||||
def test_store_different_build_deps(tmp_path):
|
||||
r"""Ensure that an environment can store two instances of a build-only
|
||||
dependency::
|
||||
@@ -2328,7 +2327,7 @@ def test_stack_yaml_force_remove_from_matrix(tmpdir):
|
||||
assert mpileaks_spec not in after_conc
|
||||
|
||||
|
||||
def test_stack_concretize_extraneous_deps(tmpdir, config, mock_packages):
|
||||
def test_stack_concretize_extraneous_deps(tmpdir, mock_packages):
|
||||
# FIXME: The new concretizer doesn't handle yet soft
|
||||
# FIXME: constraints for stacks
|
||||
# FIXME: This now works for statically-determinable invalid deps
|
||||
@@ -2367,7 +2366,7 @@ def test_stack_concretize_extraneous_deps(tmpdir, config, mock_packages):
|
||||
assert concrete.satisfies("^mpi")
|
||||
|
||||
|
||||
def test_stack_concretize_extraneous_variants(tmpdir, config, mock_packages):
|
||||
def test_stack_concretize_extraneous_variants(tmpdir, mock_packages):
|
||||
filename = str(tmpdir.join("spack.yaml"))
|
||||
with open(filename, "w") as f:
|
||||
f.write(
|
||||
@@ -2399,7 +2398,7 @@ def test_stack_concretize_extraneous_variants(tmpdir, config, mock_packages):
|
||||
assert concrete.variants["shared"].value == user.variants["shared"].value
|
||||
|
||||
|
||||
def test_stack_concretize_extraneous_variants_with_dash(tmpdir, config, mock_packages):
|
||||
def test_stack_concretize_extraneous_variants_with_dash(tmpdir, mock_packages):
|
||||
filename = str(tmpdir.join("spack.yaml"))
|
||||
with open(filename, "w") as f:
|
||||
f.write(
|
||||
@@ -3750,7 +3749,7 @@ def test_environment_query_spec_by_hash(mock_stage, mock_fetch, install_mockery)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("lockfile", ["v1", "v2", "v3"])
|
||||
def test_read_old_lock_and_write_new(config, tmpdir, lockfile):
|
||||
def test_read_old_lock_and_write_new(tmpdir, lockfile):
|
||||
# v1 lockfiles stored by a coarse DAG hash that did not include build deps.
|
||||
# They could not represent multiple build deps with different build hashes.
|
||||
#
|
||||
@@ -3816,7 +3815,7 @@ def test_read_old_lock_and_write_new(config, tmpdir, lockfile):
|
||||
assert old_hashes == hashes
|
||||
|
||||
|
||||
def test_read_v1_lock_creates_backup(config, tmp_path):
|
||||
def test_read_v1_lock_creates_backup(tmp_path):
|
||||
"""When reading a version-1 lockfile, make sure that a backup of that file
|
||||
is created.
|
||||
"""
|
||||
@@ -4199,7 +4198,7 @@ def test_env_include_packages_url(
|
||||
assert "openmpi" in cfg["all"]["providers"]["mpi"]
|
||||
|
||||
|
||||
def test_relative_view_path_on_command_line_is_made_absolute(tmp_path, config):
|
||||
def test_relative_view_path_on_command_line_is_made_absolute(tmp_path):
|
||||
with fs.working_dir(str(tmp_path)):
|
||||
env("create", "--with-view", "view", "--dir", "env")
|
||||
environment = ev.Environment(os.path.join(".", "env"))
|
||||
|
@@ -24,7 +24,7 @@ def python_database(mock_packages, mutable_database):
|
||||
|
||||
@pytest.mark.not_on_windows("All Fetchers Failed")
|
||||
@pytest.mark.db
|
||||
def test_extensions(mock_packages, python_database, config, capsys):
|
||||
def test_extensions(mock_packages, python_database, capsys):
|
||||
ext2 = Spec("py-extension2").concretized()
|
||||
|
||||
def check_output(ni):
|
||||
|
@@ -11,6 +11,7 @@
|
||||
from llnl.util.filesystem import getuid, touch
|
||||
|
||||
import spack
|
||||
import spack.cmd.external
|
||||
import spack.detection
|
||||
import spack.detection.path
|
||||
from spack.main import SpackCommand
|
||||
@@ -311,3 +312,29 @@ def test_failures_in_scanning_do_not_result_in_an_error(
|
||||
assert "cmake" in output
|
||||
assert "3.23.3" in output
|
||||
assert "3.19.1" not in output
|
||||
|
||||
|
||||
def test_detect_virtuals(mock_executable, mutable_config, monkeypatch):
|
||||
"""Test whether external find --not-buildable sets virtuals as non-buildable (unless user
|
||||
config sets them to buildable)"""
|
||||
mpich = mock_executable("mpichversion", output="echo MPICH Version: 4.0.2")
|
||||
prefix = os.path.dirname(mpich)
|
||||
external("find", "--path", prefix, "--not-buildable", "mpich")
|
||||
|
||||
# Check that mpich was correctly detected
|
||||
mpich = mutable_config.get("packages:mpich")
|
||||
assert mpich["buildable"] is False
|
||||
assert Spec(mpich["externals"][0]["spec"]).satisfies("mpich@4.0.2")
|
||||
|
||||
# Check that the virtual package mpi was marked as non-buildable
|
||||
assert mutable_config.get("packages:mpi:buildable") is False
|
||||
|
||||
# Delete the mpich entry, and set mpi explicitly to buildable
|
||||
mutable_config.set("packages:mpich", {})
|
||||
mutable_config.set("packages:mpi:buildable", True)
|
||||
|
||||
# Run the detection again
|
||||
external("find", "--path", prefix, "--not-buildable", "mpich")
|
||||
|
||||
# Check that the mpi:buildable entry was not overwritten
|
||||
assert mutable_config.get("packages:mpi:buildable") is True
|
||||
|
@@ -9,7 +9,9 @@
|
||||
from spack.main import SpackCommand, SpackCommandError
|
||||
|
||||
# everything here uses the mock_env_path
|
||||
pytestmark = pytest.mark.usefixtures("mutable_mock_env_path", "config", "mutable_mock_repo")
|
||||
pytestmark = pytest.mark.usefixtures(
|
||||
"mutable_mock_env_path", "mutable_config", "mutable_mock_repo"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.disable_clean_stage_check
|
||||
|
@@ -337,7 +337,7 @@ def test_find_command_basic_usage(database):
|
||||
@pytest.mark.not_on_windows("envirnment is not yet supported on windows")
|
||||
@pytest.mark.regression("9875")
|
||||
def test_find_prefix_in_env(
|
||||
mutable_mock_env_path, install_mockery, mock_fetch, mock_packages, mock_archive, config
|
||||
mutable_mock_env_path, install_mockery, mock_fetch, mock_packages, mock_archive
|
||||
):
|
||||
"""Test `find` formats requiring concrete specs work in environments."""
|
||||
env("create", "test")
|
||||
@@ -349,7 +349,7 @@ def test_find_prefix_in_env(
|
||||
# Would throw error on regression
|
||||
|
||||
|
||||
def test_find_specs_include_concrete_env(mutable_mock_env_path, config, mutable_mock_repo, tmpdir):
|
||||
def test_find_specs_include_concrete_env(mutable_mock_env_path, mutable_mock_repo, tmpdir):
|
||||
path = tmpdir.join("spack.yaml")
|
||||
|
||||
with tmpdir.as_cwd():
|
||||
@@ -393,9 +393,7 @@ def test_find_specs_include_concrete_env(mutable_mock_env_path, config, mutable_
|
||||
assert "libelf" in output
|
||||
|
||||
|
||||
def test_find_specs_nested_include_concrete_env(
|
||||
mutable_mock_env_path, config, mutable_mock_repo, tmpdir
|
||||
):
|
||||
def test_find_specs_nested_include_concrete_env(mutable_mock_env_path, mutable_mock_repo, tmpdir):
|
||||
path = tmpdir.join("spack.yaml")
|
||||
|
||||
with tmpdir.as_cwd():
|
||||
|
@@ -20,13 +20,13 @@
|
||||
|
||||
|
||||
@pytest.mark.db
|
||||
def test_gc_without_build_dependency(config, mutable_database):
|
||||
def test_gc_without_build_dependency(mutable_database):
|
||||
assert "There are no unused specs." in gc("-yb")
|
||||
assert "There are no unused specs." in gc("-y")
|
||||
|
||||
|
||||
@pytest.mark.db
|
||||
def test_gc_with_build_dependency(config, mutable_database):
|
||||
def test_gc_with_build_dependency(mutable_database):
|
||||
s = spack.spec.Spec("simple-inheritance")
|
||||
s.concretize()
|
||||
s.package.do_install(fake=True, explicit=True)
|
||||
@@ -37,7 +37,7 @@ def test_gc_with_build_dependency(config, mutable_database):
|
||||
|
||||
|
||||
@pytest.mark.db
|
||||
def test_gc_with_environment(config, mutable_database, mutable_mock_env_path):
|
||||
def test_gc_with_environment(mutable_database, mutable_mock_env_path):
|
||||
s = spack.spec.Spec("simple-inheritance")
|
||||
s.concretize()
|
||||
s.package.do_install(fake=True, explicit=True)
|
||||
@@ -53,7 +53,7 @@ def test_gc_with_environment(config, mutable_database, mutable_mock_env_path):
|
||||
|
||||
|
||||
@pytest.mark.db
|
||||
def test_gc_with_build_dependency_in_environment(config, mutable_database, mutable_mock_env_path):
|
||||
def test_gc_with_build_dependency_in_environment(mutable_database, mutable_mock_env_path):
|
||||
s = spack.spec.Spec("simple-inheritance")
|
||||
s.concretize()
|
||||
s.package.do_install(fake=True, explicit=True)
|
||||
@@ -78,7 +78,7 @@ def test_gc_with_build_dependency_in_environment(config, mutable_database, mutab
|
||||
|
||||
|
||||
@pytest.mark.db
|
||||
def test_gc_except_any_environments(config, mutable_database, mutable_mock_env_path):
|
||||
def test_gc_except_any_environments(mutable_database, mutable_mock_env_path):
|
||||
"""Tests whether the garbage collector can remove all specs except those still needed in some
|
||||
environment (needed in the sense of roots + link/run deps)."""
|
||||
assert mutable_database.query_local("zmpi")
|
||||
@@ -105,7 +105,7 @@ def test_gc_except_any_environments(config, mutable_database, mutable_mock_env_p
|
||||
|
||||
|
||||
@pytest.mark.db
|
||||
def test_gc_except_specific_environments(config, mutable_database, mutable_mock_env_path):
|
||||
def test_gc_except_specific_environments(mutable_database, mutable_mock_env_path):
|
||||
s = spack.spec.Spec("simple-inheritance")
|
||||
s.concretize()
|
||||
s.package.do_install(fake=True, explicit=True)
|
||||
@@ -125,14 +125,14 @@ def test_gc_except_specific_environments(config, mutable_database, mutable_mock_
|
||||
|
||||
|
||||
@pytest.mark.db
|
||||
def test_gc_except_nonexisting_dir_env(config, mutable_database, mutable_mock_env_path, tmpdir):
|
||||
def test_gc_except_nonexisting_dir_env(mutable_database, mutable_mock_env_path, tmpdir):
|
||||
output = gc("-ye", tmpdir.strpath, fail_on_error=False)
|
||||
assert "No such environment" in output
|
||||
gc.returncode == 1
|
||||
|
||||
|
||||
@pytest.mark.db
|
||||
def test_gc_except_specific_dir_env(config, mutable_database, mutable_mock_env_path, tmpdir):
|
||||
def test_gc_except_specific_dir_env(mutable_database, mutable_mock_env_path, tmpdir):
|
||||
s = spack.spec.Spec("simple-inheritance")
|
||||
s.concretize()
|
||||
s.package.do_install(fake=True, explicit=True)
|
||||
|
@@ -49,7 +49,7 @@ def noop(*args, **kwargs):
|
||||
|
||||
|
||||
def test_install_package_and_dependency(
|
||||
tmpdir, mock_packages, mock_archive, mock_fetch, config, install_mockery
|
||||
tmpdir, mock_packages, mock_archive, mock_fetch, install_mockery
|
||||
):
|
||||
log = "test"
|
||||
with tmpdir.as_cwd():
|
||||
@@ -89,11 +89,11 @@ def check(pkg):
|
||||
assert pkg.run_tests
|
||||
|
||||
monkeypatch.setattr(spack.package_base.PackageBase, "unit_test_check", check)
|
||||
install("--test=all", "a")
|
||||
install("--test=all", "pkg-a")
|
||||
|
||||
|
||||
def test_install_package_already_installed(
|
||||
tmpdir, mock_packages, mock_archive, mock_fetch, config, install_mockery
|
||||
tmpdir, mock_packages, mock_archive, mock_fetch, install_mockery
|
||||
):
|
||||
with tmpdir.as_cwd():
|
||||
install("libdwarf")
|
||||
@@ -149,7 +149,7 @@ def test_package_output(tmpdir, capsys, install_mockery, mock_fetch):
|
||||
|
||||
@pytest.mark.disable_clean_stage_check
|
||||
def test_install_output_on_build_error(
|
||||
mock_packages, mock_archive, mock_fetch, config, install_mockery, capfd
|
||||
mock_packages, mock_archive, mock_fetch, install_mockery, capfd
|
||||
):
|
||||
"""
|
||||
This test used to assume receiving full output, but since we've updated
|
||||
@@ -163,9 +163,7 @@ def test_install_output_on_build_error(
|
||||
|
||||
|
||||
@pytest.mark.disable_clean_stage_check
|
||||
def test_install_output_on_python_error(
|
||||
mock_packages, mock_archive, mock_fetch, config, install_mockery
|
||||
):
|
||||
def test_install_output_on_python_error(mock_packages, mock_archive, mock_fetch, install_mockery):
|
||||
out = install("failing-build", fail_on_error=False)
|
||||
assert isinstance(install.error, spack.build_environment.ChildError)
|
||||
assert install.error.name == "InstallError"
|
||||
@@ -173,7 +171,7 @@ def test_install_output_on_python_error(
|
||||
|
||||
|
||||
@pytest.mark.disable_clean_stage_check
|
||||
def test_install_with_source(mock_packages, mock_archive, mock_fetch, config, install_mockery):
|
||||
def test_install_with_source(mock_packages, mock_archive, mock_fetch, install_mockery):
|
||||
"""Verify that source has been copied into place."""
|
||||
install("--source", "--keep-stage", "trivial-install-test-package")
|
||||
spec = Spec("trivial-install-test-package").concretized()
|
||||
@@ -183,7 +181,7 @@ def test_install_with_source(mock_packages, mock_archive, mock_fetch, config, in
|
||||
)
|
||||
|
||||
|
||||
def test_install_env_variables(mock_packages, mock_archive, mock_fetch, config, install_mockery):
|
||||
def test_install_env_variables(mock_packages, mock_archive, mock_fetch, install_mockery):
|
||||
spec = Spec("libdwarf")
|
||||
spec.concretize()
|
||||
install("libdwarf")
|
||||
@@ -191,9 +189,7 @@ def test_install_env_variables(mock_packages, mock_archive, mock_fetch, config,
|
||||
|
||||
|
||||
@pytest.mark.disable_clean_stage_check
|
||||
def test_show_log_on_error(
|
||||
mock_packages, mock_archive, mock_fetch, config, install_mockery, capfd
|
||||
):
|
||||
def test_show_log_on_error(mock_packages, mock_archive, mock_fetch, install_mockery, capfd):
|
||||
"""
|
||||
Make sure --show-log-on-error works.
|
||||
"""
|
||||
@@ -206,7 +202,7 @@ def test_show_log_on_error(
|
||||
assert "See build log for details:" in out
|
||||
|
||||
|
||||
def test_install_overwrite(mock_packages, mock_archive, mock_fetch, config, install_mockery):
|
||||
def test_install_overwrite(mock_packages, mock_archive, mock_fetch, install_mockery):
|
||||
# Try to install a spec and then to reinstall it.
|
||||
spec = Spec("libdwarf")
|
||||
spec.concretize()
|
||||
@@ -240,9 +236,7 @@ def test_install_overwrite(mock_packages, mock_archive, mock_fetch, config, inst
|
||||
assert fs.hash_directory(spec.prefix, ignore=ignores) != bad_md5
|
||||
|
||||
|
||||
def test_install_overwrite_not_installed(
|
||||
mock_packages, mock_archive, mock_fetch, config, install_mockery
|
||||
):
|
||||
def test_install_overwrite_not_installed(mock_packages, mock_archive, mock_fetch, install_mockery):
|
||||
# Try to install a spec and then to reinstall it.
|
||||
spec = Spec("libdwarf")
|
||||
spec.concretize()
|
||||
@@ -277,9 +271,7 @@ def test_install_commit(mock_git_version_info, install_mockery, mock_packages, m
|
||||
assert content == "[0]" # contents are weird for another test
|
||||
|
||||
|
||||
def test_install_overwrite_multiple(
|
||||
mock_packages, mock_archive, mock_fetch, config, install_mockery
|
||||
):
|
||||
def test_install_overwrite_multiple(mock_packages, mock_archive, mock_fetch, install_mockery):
|
||||
# Try to install a spec and then to reinstall it.
|
||||
libdwarf = Spec("libdwarf")
|
||||
libdwarf.concretize()
|
||||
@@ -337,18 +329,14 @@ def test_install_overwrite_multiple(
|
||||
assert cm_hash != bad_cmake_md5
|
||||
|
||||
|
||||
@pytest.mark.usefixtures(
|
||||
"mock_packages", "mock_archive", "mock_fetch", "config", "install_mockery"
|
||||
)
|
||||
@pytest.mark.usefixtures("mock_packages", "mock_archive", "mock_fetch", "install_mockery")
|
||||
def test_install_conflicts(conflict_spec):
|
||||
# Make sure that spec with conflicts raises a SpackError
|
||||
with pytest.raises(SpackError):
|
||||
install(conflict_spec)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures(
|
||||
"mock_packages", "mock_archive", "mock_fetch", "config", "install_mockery"
|
||||
)
|
||||
@pytest.mark.usefixtures("mock_packages", "mock_archive", "mock_fetch", "install_mockery")
|
||||
def test_install_invalid_spec(invalid_spec):
|
||||
# Make sure that invalid specs raise a SpackError
|
||||
with pytest.raises(SpecSyntaxError, match="unexpected tokens"):
|
||||
@@ -390,9 +378,7 @@ def test_install_from_file(spec, concretize, error_code, tmpdir):
|
||||
|
||||
|
||||
@pytest.mark.disable_clean_stage_check
|
||||
@pytest.mark.usefixtures(
|
||||
"mock_packages", "mock_archive", "mock_fetch", "config", "install_mockery"
|
||||
)
|
||||
@pytest.mark.usefixtures("mock_packages", "mock_archive", "mock_fetch", "install_mockery")
|
||||
@pytest.mark.parametrize(
|
||||
"exc_typename,msg",
|
||||
[("RuntimeError", "something weird happened"), ("ValueError", "spec is not concrete")],
|
||||
@@ -448,7 +434,6 @@ def test_junit_output_with_errors(
|
||||
mock_archive,
|
||||
mock_fetch,
|
||||
install_mockery,
|
||||
config,
|
||||
tmpdir,
|
||||
monkeypatch,
|
||||
):
|
||||
@@ -509,9 +494,7 @@ def test_install_mix_cli_and_files(clispecs, filespecs, tmpdir):
|
||||
assert install.returncode == 0
|
||||
|
||||
|
||||
def test_extra_files_are_archived(
|
||||
mock_packages, mock_archive, mock_fetch, config, install_mockery
|
||||
):
|
||||
def test_extra_files_are_archived(mock_packages, mock_archive, mock_fetch, install_mockery):
|
||||
s = Spec("archive-files")
|
||||
s.concretize()
|
||||
|
||||
@@ -570,100 +553,96 @@ def test_cdash_upload_build_error(tmpdir, mock_fetch, install_mockery, capfd):
|
||||
@pytest.mark.disable_clean_stage_check
|
||||
def test_cdash_upload_clean_build(tmpdir, mock_fetch, install_mockery, capfd):
|
||||
# capfd interferes with Spack's capturing of e.g., Build.xml output
|
||||
with capfd.disabled():
|
||||
with tmpdir.as_cwd():
|
||||
install("--log-file=cdash_reports", "--log-format=cdash", "a")
|
||||
report_dir = tmpdir.join("cdash_reports")
|
||||
assert report_dir in tmpdir.listdir()
|
||||
report_file = report_dir.join("a_Build.xml")
|
||||
assert report_file in report_dir.listdir()
|
||||
content = report_file.open().read()
|
||||
assert "</Build>" in content
|
||||
assert "<Text>" not in content
|
||||
with capfd.disabled(), tmpdir.as_cwd():
|
||||
install("--log-file=cdash_reports", "--log-format=cdash", "pkg-a")
|
||||
report_dir = tmpdir.join("cdash_reports")
|
||||
assert report_dir in tmpdir.listdir()
|
||||
report_file = report_dir.join("pkg-a_Build.xml")
|
||||
assert report_file in report_dir.listdir()
|
||||
content = report_file.open().read()
|
||||
assert "</Build>" in content
|
||||
assert "<Text>" not in content
|
||||
|
||||
|
||||
@pytest.mark.disable_clean_stage_check
|
||||
def test_cdash_upload_extra_params(tmpdir, mock_fetch, install_mockery, capfd):
|
||||
# capfd interferes with Spack's capture of e.g., Build.xml output
|
||||
with capfd.disabled():
|
||||
with tmpdir.as_cwd():
|
||||
install(
|
||||
"--log-file=cdash_reports",
|
||||
"--log-format=cdash",
|
||||
"--cdash-build=my_custom_build",
|
||||
"--cdash-site=my_custom_site",
|
||||
"--cdash-track=my_custom_track",
|
||||
"a",
|
||||
)
|
||||
report_dir = tmpdir.join("cdash_reports")
|
||||
assert report_dir in tmpdir.listdir()
|
||||
report_file = report_dir.join("a_Build.xml")
|
||||
assert report_file in report_dir.listdir()
|
||||
content = report_file.open().read()
|
||||
assert 'Site BuildName="my_custom_build - a"' in content
|
||||
assert 'Name="my_custom_site"' in content
|
||||
assert "-my_custom_track" in content
|
||||
with capfd.disabled(), tmpdir.as_cwd():
|
||||
install(
|
||||
"--log-file=cdash_reports",
|
||||
"--log-format=cdash",
|
||||
"--cdash-build=my_custom_build",
|
||||
"--cdash-site=my_custom_site",
|
||||
"--cdash-track=my_custom_track",
|
||||
"pkg-a",
|
||||
)
|
||||
report_dir = tmpdir.join("cdash_reports")
|
||||
assert report_dir in tmpdir.listdir()
|
||||
report_file = report_dir.join("pkg-a_Build.xml")
|
||||
assert report_file in report_dir.listdir()
|
||||
content = report_file.open().read()
|
||||
assert 'Site BuildName="my_custom_build - pkg-a"' in content
|
||||
assert 'Name="my_custom_site"' in content
|
||||
assert "-my_custom_track" in content
|
||||
|
||||
|
||||
@pytest.mark.disable_clean_stage_check
|
||||
def test_cdash_buildstamp_param(tmpdir, mock_fetch, install_mockery, capfd):
|
||||
# capfd interferes with Spack's capture of e.g., Build.xml output
|
||||
with capfd.disabled():
|
||||
with tmpdir.as_cwd():
|
||||
cdash_track = "some_mocked_track"
|
||||
buildstamp_format = "%Y%m%d-%H%M-{0}".format(cdash_track)
|
||||
buildstamp = time.strftime(buildstamp_format, time.localtime(int(time.time())))
|
||||
install(
|
||||
"--log-file=cdash_reports",
|
||||
"--log-format=cdash",
|
||||
"--cdash-buildstamp={0}".format(buildstamp),
|
||||
"a",
|
||||
)
|
||||
report_dir = tmpdir.join("cdash_reports")
|
||||
assert report_dir in tmpdir.listdir()
|
||||
report_file = report_dir.join("a_Build.xml")
|
||||
assert report_file in report_dir.listdir()
|
||||
content = report_file.open().read()
|
||||
assert buildstamp in content
|
||||
with capfd.disabled(), tmpdir.as_cwd():
|
||||
cdash_track = "some_mocked_track"
|
||||
buildstamp_format = "%Y%m%d-%H%M-{0}".format(cdash_track)
|
||||
buildstamp = time.strftime(buildstamp_format, time.localtime(int(time.time())))
|
||||
install(
|
||||
"--log-file=cdash_reports",
|
||||
"--log-format=cdash",
|
||||
"--cdash-buildstamp={0}".format(buildstamp),
|
||||
"pkg-a",
|
||||
)
|
||||
report_dir = tmpdir.join("cdash_reports")
|
||||
assert report_dir in tmpdir.listdir()
|
||||
report_file = report_dir.join("pkg-a_Build.xml")
|
||||
assert report_file in report_dir.listdir()
|
||||
content = report_file.open().read()
|
||||
assert buildstamp in content
|
||||
|
||||
|
||||
@pytest.mark.disable_clean_stage_check
|
||||
def test_cdash_install_from_spec_json(
|
||||
tmpdir, mock_fetch, install_mockery, capfd, mock_packages, mock_archive, config
|
||||
tmpdir, mock_fetch, install_mockery, capfd, mock_packages, mock_archive
|
||||
):
|
||||
# capfd interferes with Spack's capturing
|
||||
with capfd.disabled():
|
||||
with tmpdir.as_cwd():
|
||||
spec_json_path = str(tmpdir.join("spec.json"))
|
||||
with capfd.disabled(), tmpdir.as_cwd():
|
||||
spec_json_path = str(tmpdir.join("spec.json"))
|
||||
|
||||
pkg_spec = Spec("a")
|
||||
pkg_spec.concretize()
|
||||
pkg_spec = Spec("pkg-a")
|
||||
pkg_spec.concretize()
|
||||
|
||||
with open(spec_json_path, "w") as fd:
|
||||
fd.write(pkg_spec.to_json(hash=ht.dag_hash))
|
||||
with open(spec_json_path, "w") as fd:
|
||||
fd.write(pkg_spec.to_json(hash=ht.dag_hash))
|
||||
|
||||
install(
|
||||
"--log-format=cdash",
|
||||
"--log-file=cdash_reports",
|
||||
"--cdash-build=my_custom_build",
|
||||
"--cdash-site=my_custom_site",
|
||||
"--cdash-track=my_custom_track",
|
||||
"-f",
|
||||
spec_json_path,
|
||||
)
|
||||
install(
|
||||
"--log-format=cdash",
|
||||
"--log-file=cdash_reports",
|
||||
"--cdash-build=my_custom_build",
|
||||
"--cdash-site=my_custom_site",
|
||||
"--cdash-track=my_custom_track",
|
||||
"-f",
|
||||
spec_json_path,
|
||||
)
|
||||
|
||||
report_dir = tmpdir.join("cdash_reports")
|
||||
assert report_dir in tmpdir.listdir()
|
||||
report_file = report_dir.join("a_Configure.xml")
|
||||
assert report_file in report_dir.listdir()
|
||||
content = report_file.open().read()
|
||||
install_command_regex = re.compile(
|
||||
r"<ConfigureCommand>(.+)</ConfigureCommand>", re.MULTILINE | re.DOTALL
|
||||
)
|
||||
m = install_command_regex.search(content)
|
||||
assert m
|
||||
install_command = m.group(1)
|
||||
assert "a@" in install_command
|
||||
report_dir = tmpdir.join("cdash_reports")
|
||||
assert report_dir in tmpdir.listdir()
|
||||
report_file = report_dir.join("pkg-a_Configure.xml")
|
||||
assert report_file in report_dir.listdir()
|
||||
content = report_file.open().read()
|
||||
install_command_regex = re.compile(
|
||||
r"<ConfigureCommand>(.+)</ConfigureCommand>", re.MULTILINE | re.DOTALL
|
||||
)
|
||||
m = install_command_regex.search(content)
|
||||
assert m
|
||||
install_command = m.group(1)
|
||||
assert "pkg-a@" in install_command
|
||||
|
||||
|
||||
@pytest.mark.disable_clean_stage_check
|
||||
@@ -795,15 +774,15 @@ def test_install_no_add_in_env(tmpdir, mock_fetch, install_mockery, mutable_mock
|
||||
# ^libdwarf
|
||||
# ^mpich
|
||||
# libelf@0.8.10
|
||||
# a~bvv
|
||||
# ^b
|
||||
# a
|
||||
# ^b
|
||||
# pkg-a~bvv
|
||||
# ^pkg-b
|
||||
# pkg-a
|
||||
# ^pkg-b
|
||||
e = ev.create("test", with_view=False)
|
||||
e.add("mpileaks")
|
||||
e.add("libelf@0.8.10") # so env has both root and dep libelf specs
|
||||
e.add("a")
|
||||
e.add("a ~bvv")
|
||||
e.add("pkg-a")
|
||||
e.add("pkg-a ~bvv")
|
||||
e.concretize()
|
||||
e.write()
|
||||
env_specs = e.all_specs()
|
||||
@@ -814,9 +793,9 @@ def test_install_no_add_in_env(tmpdir, mock_fetch, install_mockery, mutable_mock
|
||||
|
||||
# First find and remember some target concrete specs in the environment
|
||||
for e_spec in env_specs:
|
||||
if e_spec.satisfies(Spec("a ~bvv")):
|
||||
if e_spec.satisfies(Spec("pkg-a ~bvv")):
|
||||
a_spec = e_spec
|
||||
elif e_spec.name == "b":
|
||||
elif e_spec.name == "pkg-b":
|
||||
b_spec = e_spec
|
||||
elif e_spec.satisfies(Spec("mpi")):
|
||||
mpi_spec = e_spec
|
||||
@@ -839,8 +818,8 @@ def test_install_no_add_in_env(tmpdir, mock_fetch, install_mockery, mutable_mock
|
||||
assert "You can add specs to the environment with 'spack add " in inst_out
|
||||
|
||||
# Without --add, ensure that two packages "a" get installed
|
||||
inst_out = install("a", output=str)
|
||||
assert len([x for x in e.all_specs() if x.installed and x.name == "a"]) == 2
|
||||
inst_out = install("pkg-a", output=str)
|
||||
assert len([x for x in e.all_specs() if x.installed and x.name == "pkg-a"]) == 2
|
||||
|
||||
# Install an unambiguous dependency spec (that already exists as a dep
|
||||
# in the environment) and make sure it gets installed (w/ deps),
|
||||
@@ -873,7 +852,7 @@ def test_install_no_add_in_env(tmpdir, mock_fetch, install_mockery, mutable_mock
|
||||
# root of the environment as well as installed.
|
||||
assert b_spec not in e.roots()
|
||||
|
||||
install("--add", "b")
|
||||
install("--add", "pkg-b")
|
||||
|
||||
assert b_spec in e.roots()
|
||||
assert b_spec not in e.uninstalled_specs()
|
||||
@@ -908,7 +887,7 @@ def test_cdash_auth_token(tmpdir, mock_fetch, install_mockery, monkeypatch, capf
|
||||
# capfd interferes with Spack's capturing
|
||||
with tmpdir.as_cwd(), capfd.disabled():
|
||||
monkeypatch.setenv("SPACK_CDASH_AUTH_TOKEN", "asdf")
|
||||
out = install("-v", "--log-file=cdash_reports", "--log-format=cdash", "a")
|
||||
out = install("-v", "--log-file=cdash_reports", "--log-format=cdash", "pkg-a")
|
||||
assert "Using CDash auth token from environment" in out
|
||||
|
||||
|
||||
@@ -916,54 +895,42 @@ def test_cdash_auth_token(tmpdir, mock_fetch, install_mockery, monkeypatch, capf
|
||||
@pytest.mark.disable_clean_stage_check
|
||||
def test_cdash_configure_warning(tmpdir, mock_fetch, install_mockery, capfd):
|
||||
# capfd interferes with Spack's capturing of e.g., Build.xml output
|
||||
with capfd.disabled():
|
||||
with tmpdir.as_cwd():
|
||||
# Test would fail if install raised an error.
|
||||
with capfd.disabled(), tmpdir.as_cwd():
|
||||
# Test would fail if install raised an error.
|
||||
|
||||
# Ensure that even on non-x86_64 architectures, there are no
|
||||
# dependencies installed
|
||||
spec = spack.spec.Spec("configure-warning").concretized()
|
||||
spec.clear_dependencies()
|
||||
specfile = "./spec.json"
|
||||
with open(specfile, "w") as f:
|
||||
f.write(spec.to_json())
|
||||
# Ensure that even on non-x86_64 architectures, there are no
|
||||
# dependencies installed
|
||||
spec = Spec("configure-warning").concretized()
|
||||
spec.clear_dependencies()
|
||||
specfile = "./spec.json"
|
||||
with open(specfile, "w") as f:
|
||||
f.write(spec.to_json())
|
||||
|
||||
install("--log-file=cdash_reports", "--log-format=cdash", specfile)
|
||||
# Verify Configure.xml exists with expected contents.
|
||||
report_dir = tmpdir.join("cdash_reports")
|
||||
assert report_dir in tmpdir.listdir()
|
||||
report_file = report_dir.join("Configure.xml")
|
||||
assert report_file in report_dir.listdir()
|
||||
content = report_file.open().read()
|
||||
assert "foo: No such file or directory" in content
|
||||
install("--log-file=cdash_reports", "--log-format=cdash", specfile)
|
||||
# Verify Configure.xml exists with expected contents.
|
||||
report_dir = tmpdir.join("cdash_reports")
|
||||
assert report_dir in tmpdir.listdir()
|
||||
report_file = report_dir.join("Configure.xml")
|
||||
assert report_file in report_dir.listdir()
|
||||
content = report_file.open().read()
|
||||
assert "foo: No such file or directory" in content
|
||||
|
||||
|
||||
@pytest.mark.not_on_windows("ArchSpec gives test platform debian rather than windows")
|
||||
def test_compiler_bootstrap(
|
||||
install_mockery_mutable_config,
|
||||
mock_packages,
|
||||
mock_fetch,
|
||||
mock_archive,
|
||||
mutable_config,
|
||||
monkeypatch,
|
||||
install_mockery, mock_packages, mock_fetch, mock_archive, mutable_config, monkeypatch
|
||||
):
|
||||
monkeypatch.setattr(spack.concretize.Concretizer, "check_for_compiler_existence", False)
|
||||
spack.config.set("config:install_missing_compilers", True)
|
||||
assert CompilerSpec("gcc@=12.0") not in compilers.all_compiler_specs()
|
||||
|
||||
# Test succeeds if it does not raise an error
|
||||
install("a%gcc@=12.0")
|
||||
install("pkg-a%gcc@=12.0")
|
||||
|
||||
|
||||
@pytest.mark.not_on_windows("Binary mirrors not supported on windows")
|
||||
def test_compiler_bootstrap_from_binary_mirror(
|
||||
install_mockery_mutable_config,
|
||||
mock_packages,
|
||||
mock_fetch,
|
||||
mock_archive,
|
||||
mutable_config,
|
||||
monkeypatch,
|
||||
tmpdir,
|
||||
install_mockery, mock_packages, mock_fetch, mock_archive, mutable_config, monkeypatch, tmpdir
|
||||
):
|
||||
"""
|
||||
Make sure installing compiler from buildcache registers compiler
|
||||
@@ -992,19 +959,14 @@ def test_compiler_bootstrap_from_binary_mirror(
|
||||
# Now make sure that when the compiler is installed from binary mirror,
|
||||
# it also gets configured as a compiler. Test succeeds if it does not
|
||||
# raise an error
|
||||
install("--no-check-signature", "--cache-only", "--only", "dependencies", "b%gcc@=10.2.0")
|
||||
install("--no-cache", "--only", "package", "b%gcc@10.2.0")
|
||||
install("--no-check-signature", "--cache-only", "--only", "dependencies", "pkg-b%gcc@=10.2.0")
|
||||
install("--no-cache", "--only", "package", "pkg-b%gcc@10.2.0")
|
||||
|
||||
|
||||
@pytest.mark.not_on_windows("ArchSpec gives test platform debian rather than windows")
|
||||
@pytest.mark.regression("16221")
|
||||
def test_compiler_bootstrap_already_installed(
|
||||
install_mockery_mutable_config,
|
||||
mock_packages,
|
||||
mock_fetch,
|
||||
mock_archive,
|
||||
mutable_config,
|
||||
monkeypatch,
|
||||
install_mockery, mock_packages, mock_fetch, mock_archive, mutable_config, monkeypatch
|
||||
):
|
||||
monkeypatch.setattr(spack.concretize.Concretizer, "check_for_compiler_existence", False)
|
||||
spack.config.set("config:install_missing_compilers", True)
|
||||
@@ -1013,7 +975,7 @@ def test_compiler_bootstrap_already_installed(
|
||||
|
||||
# Test succeeds if it does not raise an error
|
||||
install("gcc@=12.0")
|
||||
install("a%gcc@=12.0")
|
||||
install("pkg-a%gcc@=12.0")
|
||||
|
||||
|
||||
def test_install_fails_no_args(tmpdir):
|
||||
@@ -1104,13 +1066,7 @@ def test_installation_fail_tests(install_mockery, mock_fetch, name, method):
|
||||
|
||||
@pytest.mark.not_on_windows("Buildcache not supported on windows")
|
||||
def test_install_use_buildcache(
|
||||
capsys,
|
||||
mock_packages,
|
||||
mock_fetch,
|
||||
mock_archive,
|
||||
mock_binary_index,
|
||||
tmpdir,
|
||||
install_mockery_mutable_config,
|
||||
capsys, mock_packages, mock_fetch, mock_archive, mock_binary_index, tmpdir, install_mockery
|
||||
):
|
||||
"""
|
||||
Make sure installing with use-buildcache behaves correctly.
|
||||
@@ -1183,19 +1139,19 @@ def install_use_buildcache(opt):
|
||||
@pytest.mark.not_on_windows("Windows logger I/O operation on closed file when install fails")
|
||||
@pytest.mark.regression("34006")
|
||||
@pytest.mark.disable_clean_stage_check
|
||||
def test_padded_install_runtests_root(install_mockery_mutable_config, mock_fetch):
|
||||
def test_padded_install_runtests_root(install_mockery, mock_fetch):
|
||||
spack.config.set("config:install_tree:padded_length", 255)
|
||||
output = install("--test=root", "--no-cache", "test-build-callbacks", fail_on_error=False)
|
||||
assert output.count("method not implemented") == 1
|
||||
|
||||
|
||||
@pytest.mark.regression("35337")
|
||||
def test_report_filename_for_cdash(install_mockery_mutable_config, mock_fetch):
|
||||
def test_report_filename_for_cdash(install_mockery, mock_fetch):
|
||||
"""Test that the temporary file used to write the XML for CDash is not the upload URL"""
|
||||
parser = argparse.ArgumentParser()
|
||||
spack.cmd.install.setup_parser(parser)
|
||||
args = parser.parse_args(
|
||||
["--cdash-upload-url", "https://blahblah/submit.php?project=debugging", "a"]
|
||||
["--cdash-upload-url", "https://blahblah/submit.php?project=debugging", "pkg-a"]
|
||||
)
|
||||
specs = spack.cmd.install.concrete_specs_from_cli(args, {})
|
||||
filename = spack.cmd.install.report_filename(args, specs)
|
||||
|
@@ -3,7 +3,6 @@
|
||||
#
|
||||
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
||||
|
||||
import os
|
||||
import shutil
|
||||
|
||||
import pytest
|
||||
@@ -16,10 +15,8 @@
|
||||
from spack.main import SpackCommand, SpackCommandError
|
||||
|
||||
# Everything here uses (or can use) the mock config and database.
|
||||
pytestmark = [
|
||||
pytest.mark.usefixtures("config", "database"),
|
||||
pytest.mark.not_on_windows("does not run on windows"),
|
||||
]
|
||||
pytestmark = [pytest.mark.usefixtures("mutable_config", "mutable_database")]
|
||||
|
||||
# location prints out "locations of packages and spack directories"
|
||||
location = SpackCommand("location")
|
||||
env = SpackCommand("env")
|
||||
@@ -65,7 +62,7 @@ def test_location_source_dir_missing():
|
||||
prefix = "==> Error: "
|
||||
expected = (
|
||||
"%sSource directory does not exist yet. Run this to create it:"
|
||||
"%s spack stage %s" % (prefix, os.linesep, spec)
|
||||
"%s spack stage %s" % (prefix, "\n", spec)
|
||||
)
|
||||
out = location("--source-dir", spec, fail_on_error=False).strip()
|
||||
assert out == expected
|
||||
@@ -126,6 +123,7 @@ def test_location_env_missing():
|
||||
|
||||
|
||||
@pytest.mark.db
|
||||
@pytest.mark.not_on_windows("Broken on Windows")
|
||||
def test_location_install_dir(mock_spec):
|
||||
"""Tests spack location --install-dir."""
|
||||
spec, _ = mock_spec
|
||||
|
@@ -121,7 +121,7 @@ def test_maintainers_list_packages(mock_packages, capfd):
|
||||
|
||||
|
||||
def test_maintainers_list_fails(mock_packages, capfd):
|
||||
out = maintainers("a", fail_on_error=False)
|
||||
out = maintainers("pkg-a", fail_on_error=False)
|
||||
assert not out
|
||||
assert maintainers.returncode == 1
|
||||
|
||||
|
@@ -35,7 +35,7 @@ def test_regression_8083(tmpdir, capfd, mock_packages, mock_fetch, config):
|
||||
|
||||
|
||||
@pytest.mark.regression("12345")
|
||||
def test_mirror_from_env(tmp_path, mock_packages, mock_fetch, config, mutable_mock_env_path):
|
||||
def test_mirror_from_env(tmp_path, mock_packages, mock_fetch, mutable_mock_env_path):
|
||||
mirror_dir = str(tmp_path / "mirror")
|
||||
env_name = "test"
|
||||
|
||||
@@ -232,13 +232,7 @@ def test_mirror_name_collision(mutable_config):
|
||||
|
||||
|
||||
def test_mirror_destroy(
|
||||
install_mockery_mutable_config,
|
||||
mock_packages,
|
||||
mock_fetch,
|
||||
mock_archive,
|
||||
mutable_config,
|
||||
monkeypatch,
|
||||
tmpdir,
|
||||
install_mockery, mock_packages, mock_fetch, mock_archive, mutable_config, monkeypatch, tmpdir
|
||||
):
|
||||
# Create a temp mirror directory for buildcache usage
|
||||
mirror_dir = tmpdir.join("mirror_dir")
|
||||
|
@@ -11,6 +11,7 @@
|
||||
import spack.config
|
||||
import spack.main
|
||||
import spack.modules
|
||||
import spack.spec
|
||||
import spack.store
|
||||
|
||||
module = spack.main.SpackCommand("module")
|
||||
@@ -139,7 +140,7 @@ def test_find_recursive():
|
||||
|
||||
|
||||
@pytest.mark.db
|
||||
def test_find_recursive_excluded(database, module_configuration):
|
||||
def test_find_recursive_excluded(mutable_database, module_configuration):
|
||||
module_configuration("exclude")
|
||||
|
||||
module("lmod", "refresh", "-y", "--delete-tree")
|
||||
@@ -147,7 +148,7 @@ def test_find_recursive_excluded(database, module_configuration):
|
||||
|
||||
|
||||
@pytest.mark.db
|
||||
def test_loads_recursive_excluded(database, module_configuration):
|
||||
def test_loads_recursive_excluded(mutable_database, module_configuration):
|
||||
module_configuration("exclude")
|
||||
|
||||
module("lmod", "refresh", "-y", "--delete-tree")
|
||||
@@ -178,8 +179,8 @@ def test_setdefault_command(mutable_database, mutable_config):
|
||||
}
|
||||
}
|
||||
spack.config.set("modules", data)
|
||||
# Install two different versions of a package
|
||||
other_spec, preferred = "a@1.0", "a@2.0"
|
||||
# Install two different versions of pkg-a
|
||||
other_spec, preferred = "pkg-a@1.0", "pkg-a@2.0"
|
||||
|
||||
spack.spec.Spec(other_spec).concretized().package.do_install(fake=True)
|
||||
spack.spec.Spec(preferred).concretized().package.do_install(fake=True)
|
||||
|
@@ -29,8 +29,8 @@ def install(self, spec, prefix):
|
||||
pass
|
||||
"""
|
||||
|
||||
abc = set(("pkg-a", "pkg-b", "pkg-c"))
|
||||
abd = set(("pkg-a", "pkg-b", "pkg-d"))
|
||||
abc = {"mockpkg-a", "mockpkg-b", "mockpkg-c"}
|
||||
abd = {"mockpkg-a", "mockpkg-b", "mockpkg-d"}
|
||||
|
||||
|
||||
# Force all tests to use a git repository *in* the mock packages repo.
|
||||
@@ -55,27 +55,33 @@ def mock_pkg_git_repo(git, tmp_path_factory):
|
||||
git("config", "user.name", "Spack Testing")
|
||||
git("-c", "commit.gpgsign=false", "commit", "-m", "initial mock repo commit")
|
||||
|
||||
# add commit with pkg-a, pkg-b, pkg-c packages
|
||||
mkdirp("pkg-a", "pkg-b", "pkg-c")
|
||||
with open("pkg-a/package.py", "w") as f:
|
||||
# add commit with mockpkg-a, mockpkg-b, mockpkg-c packages
|
||||
mkdirp("mockpkg-a", "mockpkg-b", "mockpkg-c")
|
||||
with open("mockpkg-a/package.py", "w") as f:
|
||||
f.write(pkg_template.format(name="PkgA"))
|
||||
with open("pkg-b/package.py", "w") as f:
|
||||
with open("mockpkg-b/package.py", "w") as f:
|
||||
f.write(pkg_template.format(name="PkgB"))
|
||||
with open("pkg-c/package.py", "w") as f:
|
||||
with open("mockpkg-c/package.py", "w") as f:
|
||||
f.write(pkg_template.format(name="PkgC"))
|
||||
git("add", "pkg-a", "pkg-b", "pkg-c")
|
||||
git("-c", "commit.gpgsign=false", "commit", "-m", "add pkg-a, pkg-b, pkg-c")
|
||||
git("add", "mockpkg-a", "mockpkg-b", "mockpkg-c")
|
||||
git("-c", "commit.gpgsign=false", "commit", "-m", "add mockpkg-a, mockpkg-b, mockpkg-c")
|
||||
|
||||
# remove pkg-c, add pkg-d
|
||||
with open("pkg-b/package.py", "a") as f:
|
||||
f.write("\n# change pkg-b")
|
||||
git("add", "pkg-b")
|
||||
mkdirp("pkg-d")
|
||||
with open("pkg-d/package.py", "w") as f:
|
||||
# remove mockpkg-c, add mockpkg-d
|
||||
with open("mockpkg-b/package.py", "a") as f:
|
||||
f.write("\n# change mockpkg-b")
|
||||
git("add", "mockpkg-b")
|
||||
mkdirp("mockpkg-d")
|
||||
with open("mockpkg-d/package.py", "w") as f:
|
||||
f.write(pkg_template.format(name="PkgD"))
|
||||
git("add", "pkg-d")
|
||||
git("rm", "-rf", "pkg-c")
|
||||
git("-c", "commit.gpgsign=false", "commit", "-m", "change pkg-b, remove pkg-c, add pkg-d")
|
||||
git("add", "mockpkg-d")
|
||||
git("rm", "-rf", "mockpkg-c")
|
||||
git(
|
||||
"-c",
|
||||
"commit.gpgsign=false",
|
||||
"commit",
|
||||
"-m",
|
||||
"change mockpkg-b, remove mockpkg-c, add mockpkg-d",
|
||||
)
|
||||
|
||||
with spack.repo.use_repositories(str(repo_dir)):
|
||||
yield mock_repo_packages
|
||||
@@ -88,12 +94,11 @@ def mock_pkg_names():
|
||||
# Be sure to include virtual packages since packages with stand-alone
|
||||
# tests may inherit additional tests from the virtuals they provide,
|
||||
# such as packages that implement `mpi`.
|
||||
names = set(
|
||||
return {
|
||||
name
|
||||
for name in repo.all_package_names(include_virtuals=True)
|
||||
if not name.startswith("pkg-")
|
||||
)
|
||||
return names
|
||||
if not name.startswith("mockpkg-")
|
||||
}
|
||||
|
||||
|
||||
def split(output):
|
||||
@@ -115,17 +120,17 @@ def test_mock_packages_path(mock_packages):
|
||||
|
||||
def test_pkg_add(git, mock_pkg_git_repo):
|
||||
with working_dir(mock_pkg_git_repo):
|
||||
mkdirp("pkg-e")
|
||||
with open("pkg-e/package.py", "w") as f:
|
||||
mkdirp("mockpkg-e")
|
||||
with open("mockpkg-e/package.py", "w") as f:
|
||||
f.write(pkg_template.format(name="PkgE"))
|
||||
|
||||
pkg("add", "pkg-e")
|
||||
pkg("add", "mockpkg-e")
|
||||
|
||||
with working_dir(mock_pkg_git_repo):
|
||||
try:
|
||||
assert "A pkg-e/package.py" in git("status", "--short", output=str)
|
||||
assert "A mockpkg-e/package.py" in git("status", "--short", output=str)
|
||||
finally:
|
||||
shutil.rmtree("pkg-e")
|
||||
shutil.rmtree("mockpkg-e")
|
||||
# Removing a package mid-run disrupts Spack's caching
|
||||
if spack.repo.PATH.repos[0]._fast_package_checker:
|
||||
spack.repo.PATH.repos[0]._fast_package_checker.invalidate()
|
||||
@@ -140,10 +145,10 @@ def test_pkg_list(mock_pkg_git_repo, mock_pkg_names):
|
||||
assert sorted(mock_pkg_names) == sorted(out)
|
||||
|
||||
out = split(pkg("list", "HEAD^"))
|
||||
assert sorted(mock_pkg_names.union(["pkg-a", "pkg-b", "pkg-c"])) == sorted(out)
|
||||
assert sorted(mock_pkg_names.union(["mockpkg-a", "mockpkg-b", "mockpkg-c"])) == sorted(out)
|
||||
|
||||
out = split(pkg("list", "HEAD"))
|
||||
assert sorted(mock_pkg_names.union(["pkg-a", "pkg-b", "pkg-d"])) == sorted(out)
|
||||
assert sorted(mock_pkg_names.union(["mockpkg-a", "mockpkg-b", "mockpkg-d"])) == sorted(out)
|
||||
|
||||
# test with three dots to make sure pkg calls `git merge-base`
|
||||
out = split(pkg("list", "HEAD^^..."))
|
||||
@@ -153,25 +158,25 @@ def test_pkg_list(mock_pkg_git_repo, mock_pkg_names):
|
||||
@pytest.mark.not_on_windows("stdout format conflict")
|
||||
def test_pkg_diff(mock_pkg_git_repo, mock_pkg_names):
|
||||
out = split(pkg("diff", "HEAD^^", "HEAD^"))
|
||||
assert out == ["HEAD^:", "pkg-a", "pkg-b", "pkg-c"]
|
||||
assert out == ["HEAD^:", "mockpkg-a", "mockpkg-b", "mockpkg-c"]
|
||||
|
||||
out = split(pkg("diff", "HEAD^^", "HEAD"))
|
||||
assert out == ["HEAD:", "pkg-a", "pkg-b", "pkg-d"]
|
||||
assert out == ["HEAD:", "mockpkg-a", "mockpkg-b", "mockpkg-d"]
|
||||
|
||||
out = split(pkg("diff", "HEAD^", "HEAD"))
|
||||
assert out == ["HEAD^:", "pkg-c", "HEAD:", "pkg-d"]
|
||||
assert out == ["HEAD^:", "mockpkg-c", "HEAD:", "mockpkg-d"]
|
||||
|
||||
|
||||
@pytest.mark.not_on_windows("stdout format conflict")
|
||||
def test_pkg_added(mock_pkg_git_repo):
|
||||
out = split(pkg("added", "HEAD^^", "HEAD^"))
|
||||
assert ["pkg-a", "pkg-b", "pkg-c"] == out
|
||||
assert ["mockpkg-a", "mockpkg-b", "mockpkg-c"] == out
|
||||
|
||||
out = split(pkg("added", "HEAD^^", "HEAD"))
|
||||
assert ["pkg-a", "pkg-b", "pkg-d"] == out
|
||||
assert ["mockpkg-a", "mockpkg-b", "mockpkg-d"] == out
|
||||
|
||||
out = split(pkg("added", "HEAD^", "HEAD"))
|
||||
assert ["pkg-d"] == out
|
||||
assert ["mockpkg-d"] == out
|
||||
|
||||
out = split(pkg("added", "HEAD", "HEAD"))
|
||||
assert out == []
|
||||
@@ -186,7 +191,7 @@ def test_pkg_removed(mock_pkg_git_repo):
|
||||
assert out == []
|
||||
|
||||
out = split(pkg("removed", "HEAD^", "HEAD"))
|
||||
assert out == ["pkg-c"]
|
||||
assert out == ["mockpkg-c"]
|
||||
|
||||
|
||||
@pytest.mark.not_on_windows("stdout format conflict")
|
||||
@@ -198,34 +203,34 @@ def test_pkg_changed(mock_pkg_git_repo):
|
||||
assert out == []
|
||||
|
||||
out = split(pkg("changed", "--type", "a", "HEAD^^", "HEAD^"))
|
||||
assert out == ["pkg-a", "pkg-b", "pkg-c"]
|
||||
assert out == ["mockpkg-a", "mockpkg-b", "mockpkg-c"]
|
||||
|
||||
out = split(pkg("changed", "--type", "r", "HEAD^^", "HEAD^"))
|
||||
assert out == []
|
||||
|
||||
out = split(pkg("changed", "--type", "ar", "HEAD^^", "HEAD^"))
|
||||
assert out == ["pkg-a", "pkg-b", "pkg-c"]
|
||||
assert out == ["mockpkg-a", "mockpkg-b", "mockpkg-c"]
|
||||
|
||||
out = split(pkg("changed", "--type", "arc", "HEAD^^", "HEAD^"))
|
||||
assert out == ["pkg-a", "pkg-b", "pkg-c"]
|
||||
assert out == ["mockpkg-a", "mockpkg-b", "mockpkg-c"]
|
||||
|
||||
out = split(pkg("changed", "HEAD^", "HEAD"))
|
||||
assert out == ["pkg-b"]
|
||||
assert out == ["mockpkg-b"]
|
||||
|
||||
out = split(pkg("changed", "--type", "c", "HEAD^", "HEAD"))
|
||||
assert out == ["pkg-b"]
|
||||
assert out == ["mockpkg-b"]
|
||||
|
||||
out = split(pkg("changed", "--type", "a", "HEAD^", "HEAD"))
|
||||
assert out == ["pkg-d"]
|
||||
assert out == ["mockpkg-d"]
|
||||
|
||||
out = split(pkg("changed", "--type", "r", "HEAD^", "HEAD"))
|
||||
assert out == ["pkg-c"]
|
||||
assert out == ["mockpkg-c"]
|
||||
|
||||
out = split(pkg("changed", "--type", "ar", "HEAD^", "HEAD"))
|
||||
assert out == ["pkg-c", "pkg-d"]
|
||||
assert out == ["mockpkg-c", "mockpkg-d"]
|
||||
|
||||
out = split(pkg("changed", "--type", "arc", "HEAD^", "HEAD"))
|
||||
assert out == ["pkg-b", "pkg-c", "pkg-d"]
|
||||
assert out == ["mockpkg-b", "mockpkg-c", "mockpkg-d"]
|
||||
|
||||
# invalid type argument
|
||||
with pytest.raises(spack.main.SpackCommandError):
|
||||
@@ -291,7 +296,7 @@ def test_pkg_canonical_source(mock_packages):
|
||||
|
||||
|
||||
def test_pkg_hash(mock_packages):
|
||||
output = pkg("hash", "a", "b").strip().split()
|
||||
output = pkg("hash", "pkg-a", "pkg-b").strip().split()
|
||||
assert len(output) == 2 and all(len(elt) == 32 for elt in output)
|
||||
|
||||
output = pkg("hash", "multimethod").strip().split()
|
||||
|
@@ -10,8 +10,6 @@
|
||||
|
||||
providers = SpackCommand("providers")
|
||||
|
||||
pytestmark = pytest.mark.not_on_windows("Providers not currently supported on Windows")
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"pkg",
|
||||
|
@@ -4,8 +4,6 @@
|
||||
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
||||
import os
|
||||
|
||||
import pytest
|
||||
|
||||
import spack.store
|
||||
from spack.main import SpackCommand
|
||||
|
||||
@@ -13,8 +11,6 @@
|
||||
deprecate = SpackCommand("deprecate")
|
||||
reindex = SpackCommand("reindex")
|
||||
|
||||
pytestmark = pytest.mark.not_on_windows("does not run on windows")
|
||||
|
||||
|
||||
def test_reindex_basic(mock_packages, mock_archive, mock_fetch, install_mockery):
|
||||
install("libelf@0.8.13")
|
||||
|
@@ -14,7 +14,7 @@
|
||||
import spack.store
|
||||
from spack.main import SpackCommand, SpackCommandError
|
||||
|
||||
pytestmark = pytest.mark.usefixtures("config", "mutable_mock_repo")
|
||||
pytestmark = pytest.mark.usefixtures("mutable_config", "mutable_mock_repo")
|
||||
|
||||
spec = SpackCommand("spec")
|
||||
|
||||
@@ -31,7 +31,7 @@ def test_spec():
|
||||
|
||||
|
||||
@pytest.mark.only_clingo("Known failure of the original concretizer")
|
||||
def test_spec_concretizer_args(mutable_config, mutable_database, do_not_check_runtimes_on_reuse):
|
||||
def test_spec_concretizer_args(mutable_database, do_not_check_runtimes_on_reuse):
|
||||
"""End-to-end test of CLI concretizer prefs.
|
||||
|
||||
It's here to make sure that everything works from CLI
|
||||
@@ -58,7 +58,7 @@ def test_spec_concretizer_args(mutable_config, mutable_database, do_not_check_ru
|
||||
def test_spec_parse_dependency_variant_value():
|
||||
"""Verify that we can provide multiple key=value variants to multiple separate
|
||||
packages within a spec string."""
|
||||
output = spec("multivalue-variant fee=barbaz ^ a foobar=baz")
|
||||
output = spec("multivalue-variant fee=barbaz ^ pkg-a foobar=baz")
|
||||
|
||||
assert "fee=barbaz" in output
|
||||
assert "foobar=baz" in output
|
||||
@@ -97,7 +97,7 @@ def test_spec_json():
|
||||
assert "mpich" in mpileaks
|
||||
|
||||
|
||||
def test_spec_format(database, config):
|
||||
def test_spec_format(mutable_database):
|
||||
output = spec("--format", "{name}-{^mpi.name}", "mpileaks^mpich")
|
||||
assert output.rstrip("\n") == "mpileaks-mpich"
|
||||
|
||||
|
@@ -22,7 +22,6 @@
|
||||
pytestmark = pytest.mark.usefixtures("install_mockery", "mock_packages")
|
||||
|
||||
|
||||
@pytest.mark.not_on_windows("not implemented on windows")
|
||||
@pytest.mark.disable_clean_stage_check
|
||||
def test_stage_spec(monkeypatch):
|
||||
"""Verify that staging specs works."""
|
||||
@@ -63,7 +62,6 @@ def test_stage_path_errors_multiple_specs(check_stage_path):
|
||||
stage(f"--path={check_stage_path}", "trivial-install-test-package", "mpileaks")
|
||||
|
||||
|
||||
@pytest.mark.not_on_windows("not implemented on windows")
|
||||
@pytest.mark.disable_clean_stage_check
|
||||
def test_stage_with_env_outside_env(mutable_mock_env_path, monkeypatch):
|
||||
"""Verify that stage concretizes specs not in environment instead of erroring."""
|
||||
@@ -82,7 +80,6 @@ def fake_stage(pkg, mirror_only=False):
|
||||
stage("trivial-install-test-package")
|
||||
|
||||
|
||||
@pytest.mark.not_on_windows("not implemented on windows")
|
||||
@pytest.mark.disable_clean_stage_check
|
||||
def test_stage_with_env_inside_env(mutable_mock_env_path, monkeypatch):
|
||||
"""Verify that stage filters specs in environment instead of reconcretizing."""
|
||||
@@ -101,7 +98,6 @@ def fake_stage(pkg, mirror_only=False):
|
||||
stage("mpileaks")
|
||||
|
||||
|
||||
@pytest.mark.not_on_windows("not implemented on windows")
|
||||
@pytest.mark.disable_clean_stage_check
|
||||
def test_stage_full_env(mutable_mock_env_path, monkeypatch):
|
||||
"""Verify that stage filters specs in environment."""
|
||||
|
@@ -10,10 +10,14 @@
|
||||
|
||||
from llnl.util.filesystem import copy_tree
|
||||
|
||||
import spack.cmd.common.arguments
|
||||
import spack.cmd.install
|
||||
import spack.cmd.test
|
||||
import spack.config
|
||||
import spack.install_test
|
||||
import spack.package_base
|
||||
import spack.paths
|
||||
import spack.spec
|
||||
import spack.store
|
||||
from spack.install_test import TestStatus
|
||||
from spack.main import SpackCommand
|
||||
@@ -25,13 +29,7 @@
|
||||
|
||||
|
||||
def test_test_package_not_installed(
|
||||
tmpdir,
|
||||
mock_packages,
|
||||
mock_archive,
|
||||
mock_fetch,
|
||||
config,
|
||||
install_mockery_mutable_config,
|
||||
mock_test_stage,
|
||||
tmpdir, mock_packages, mock_archive, mock_fetch, install_mockery, mock_test_stage
|
||||
):
|
||||
output = spack_test("run", "libdwarf")
|
||||
|
||||
@@ -54,7 +52,7 @@ def test_test_dirty_flag(arguments, expected):
|
||||
|
||||
|
||||
def test_test_dup_alias(
|
||||
mock_test_stage, mock_packages, mock_archive, mock_fetch, install_mockery_mutable_config, capfd
|
||||
mock_test_stage, mock_packages, mock_archive, mock_fetch, install_mockery, capfd
|
||||
):
|
||||
"""Ensure re-using an alias fails with suggestion to change."""
|
||||
install("libdwarf")
|
||||
@@ -69,9 +67,7 @@ def test_test_dup_alias(
|
||||
assert "already exists" in out and "Try another alias" in out
|
||||
|
||||
|
||||
def test_test_output(
|
||||
mock_test_stage, mock_packages, mock_archive, mock_fetch, install_mockery_mutable_config
|
||||
):
|
||||
def test_test_output(mock_test_stage, mock_packages, mock_archive, mock_fetch, install_mockery):
|
||||
"""Ensure output printed from pkgs is captured by output redirection."""
|
||||
install("printing-package")
|
||||
spack_test("run", "--alias", "printpkg", "printing-package")
|
||||
@@ -97,13 +93,7 @@ def test_test_output(
|
||||
"pkg_name,failure", [("test-error", "exited with status 1"), ("test-fail", "not callable")]
|
||||
)
|
||||
def test_test_output_fails(
|
||||
mock_packages,
|
||||
mock_archive,
|
||||
mock_fetch,
|
||||
install_mockery_mutable_config,
|
||||
mock_test_stage,
|
||||
pkg_name,
|
||||
failure,
|
||||
mock_packages, mock_archive, mock_fetch, install_mockery, mock_test_stage, pkg_name, failure
|
||||
):
|
||||
"""Confirm stand-alone test failure with expected outputs."""
|
||||
install(pkg_name)
|
||||
@@ -117,9 +107,7 @@ def test_test_output_fails(
|
||||
assert "See test log for details" in out
|
||||
|
||||
|
||||
@pytest.mark.usefixtures(
|
||||
"mock_packages", "mock_archive", "mock_fetch", "install_mockery_mutable_config"
|
||||
)
|
||||
@pytest.mark.usefixtures("mock_packages", "mock_archive", "mock_fetch", "install_mockery")
|
||||
@pytest.mark.parametrize(
|
||||
"pkg_name,msgs",
|
||||
[
|
||||
@@ -153,13 +141,7 @@ def test_junit_output_with_failures(tmpdir, mock_test_stage, pkg_name, msgs):
|
||||
|
||||
|
||||
def test_cdash_output_test_error(
|
||||
tmpdir,
|
||||
mock_fetch,
|
||||
install_mockery_mutable_config,
|
||||
mock_packages,
|
||||
mock_archive,
|
||||
mock_test_stage,
|
||||
capfd,
|
||||
tmpdir, mock_fetch, install_mockery, mock_packages, mock_archive, mock_test_stage, capfd
|
||||
):
|
||||
"""Confirm stand-alone test error expected outputs in CDash reporting."""
|
||||
install("test-error")
|
||||
@@ -179,12 +161,7 @@ def test_cdash_output_test_error(
|
||||
|
||||
|
||||
def test_cdash_upload_clean_test(
|
||||
tmpdir,
|
||||
mock_fetch,
|
||||
install_mockery_mutable_config,
|
||||
mock_packages,
|
||||
mock_archive,
|
||||
mock_test_stage,
|
||||
tmpdir, mock_fetch, install_mockery, mock_packages, mock_archive, mock_test_stage
|
||||
):
|
||||
install("printing-package")
|
||||
with tmpdir.as_cwd():
|
||||
@@ -233,7 +210,7 @@ def test_test_list_all(mock_packages):
|
||||
)
|
||||
|
||||
|
||||
def test_test_list(mock_packages, mock_archive, mock_fetch, install_mockery_mutable_config):
|
||||
def test_test_list(mock_packages, mock_archive, mock_fetch, install_mockery):
|
||||
pkg_with_tests = "printing-package"
|
||||
install(pkg_with_tests)
|
||||
output = spack_test("list")
|
||||
@@ -299,7 +276,7 @@ def test_test_results_status(mock_packages, mock_test_stage, status):
|
||||
|
||||
|
||||
@pytest.mark.regression("35337")
|
||||
def test_report_filename_for_cdash(install_mockery_mutable_config, mock_fetch):
|
||||
def test_report_filename_for_cdash(install_mockery, mock_fetch):
|
||||
"""Test that the temporary file used to write Testing.xml for CDash is not the upload URL"""
|
||||
name = "trivial"
|
||||
spec = spack.spec.Spec("trivial-smoke-test").concretized()
|
||||
@@ -322,7 +299,7 @@ def test_report_filename_for_cdash(install_mockery_mutable_config, mock_fetch):
|
||||
|
||||
|
||||
def test_test_output_multiple_specs(
|
||||
mock_test_stage, mock_packages, mock_archive, mock_fetch, install_mockery_mutable_config
|
||||
mock_test_stage, mock_packages, mock_archive, mock_fetch, install_mockery
|
||||
):
|
||||
"""Ensure proper reporting for suite with skipped, failing, and passed tests."""
|
||||
install("test-error", "simple-standalone-test@0.9", "simple-standalone-test@1.0")
|
||||
|
@@ -222,7 +222,7 @@ class TestUninstallFromEnv:
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def environment_setup(
|
||||
self, mutable_mock_env_path, config, mock_packages, mutable_database, install_mockery
|
||||
self, mutable_mock_env_path, mock_packages, mutable_database, install_mockery
|
||||
):
|
||||
TestUninstallFromEnv.env("create", "e1")
|
||||
e1 = spack.environment.read("e1")
|
||||
|
@@ -3,7 +3,6 @@
|
||||
#
|
||||
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
||||
import re
|
||||
import sys
|
||||
|
||||
import pytest
|
||||
|
||||
@@ -117,7 +116,6 @@ def test_url_summary(mock_packages):
|
||||
assert out_correct_versions == correct_versions
|
||||
|
||||
|
||||
@pytest.mark.skipif(sys.platform.startswith("win"), reason="Unsupported on Windows for now")
|
||||
def test_url_stats(capfd, mock_packages):
|
||||
with capfd.disabled():
|
||||
output = url("stats")
|
||||
|
@@ -63,9 +63,7 @@ def test_single_file_verify_cmd(tmpdir):
|
||||
assert sorted(errors) == sorted(expected)
|
||||
|
||||
|
||||
def test_single_spec_verify_cmd(
|
||||
tmpdir, mock_packages, mock_archive, mock_fetch, config, install_mockery
|
||||
):
|
||||
def test_single_spec_verify_cmd(tmpdir, mock_packages, mock_archive, mock_fetch, install_mockery):
|
||||
# Test the verify command interface to verify a single spec
|
||||
install("libelf")
|
||||
s = spack.spec.Spec("libelf").concretized()
|
||||
|
@@ -28,9 +28,7 @@ def create_projection_file(tmpdir, projection):
|
||||
|
||||
|
||||
@pytest.mark.parametrize("cmd", ["hardlink", "symlink", "hard", "add", "copy", "relocate"])
|
||||
def test_view_link_type(
|
||||
tmpdir, mock_packages, mock_archive, mock_fetch, config, install_mockery, cmd
|
||||
):
|
||||
def test_view_link_type(tmpdir, mock_packages, mock_archive, mock_fetch, install_mockery, cmd):
|
||||
install("libdwarf")
|
||||
viewpath = str(tmpdir.mkdir("view_{0}".format(cmd)))
|
||||
view(cmd, viewpath, "libdwarf")
|
||||
@@ -44,7 +42,7 @@ def test_view_link_type(
|
||||
|
||||
@pytest.mark.parametrize("add_cmd", ["hardlink", "symlink", "hard", "add", "copy", "relocate"])
|
||||
def test_view_link_type_remove(
|
||||
tmpdir, mock_packages, mock_archive, mock_fetch, config, install_mockery, add_cmd
|
||||
tmpdir, mock_packages, mock_archive, mock_fetch, install_mockery, add_cmd
|
||||
):
|
||||
install("needs-relocation")
|
||||
viewpath = str(tmpdir.mkdir("view_{0}".format(add_cmd)))
|
||||
@@ -57,9 +55,7 @@ def test_view_link_type_remove(
|
||||
|
||||
|
||||
@pytest.mark.parametrize("cmd", ["hardlink", "symlink", "hard", "add", "copy", "relocate"])
|
||||
def test_view_projections(
|
||||
tmpdir, mock_packages, mock_archive, mock_fetch, config, install_mockery, cmd
|
||||
):
|
||||
def test_view_projections(tmpdir, mock_packages, mock_archive, mock_fetch, install_mockery, cmd):
|
||||
install("libdwarf@20130207")
|
||||
|
||||
viewpath = str(tmpdir.mkdir("view_{0}".format(cmd)))
|
||||
@@ -76,7 +72,7 @@ def test_view_projections(
|
||||
|
||||
|
||||
def test_view_multiple_projections(
|
||||
tmpdir, mock_packages, mock_archive, mock_fetch, config, install_mockery
|
||||
tmpdir, mock_packages, mock_archive, mock_fetch, install_mockery
|
||||
):
|
||||
install("libdwarf@20130207")
|
||||
install("extendee@1.0%gcc")
|
||||
@@ -96,7 +92,7 @@ def test_view_multiple_projections(
|
||||
|
||||
|
||||
def test_view_multiple_projections_all_first(
|
||||
tmpdir, mock_packages, mock_archive, mock_fetch, config, install_mockery
|
||||
tmpdir, mock_packages, mock_archive, mock_fetch, install_mockery
|
||||
):
|
||||
install("libdwarf@20130207")
|
||||
install("extendee@1.0%gcc")
|
||||
@@ -115,14 +111,14 @@ def test_view_multiple_projections_all_first(
|
||||
assert os.path.exists(extendee_prefix)
|
||||
|
||||
|
||||
def test_view_external(tmpdir, mock_packages, mock_archive, mock_fetch, config, install_mockery):
|
||||
def test_view_external(tmpdir, mock_packages, mock_archive, mock_fetch, install_mockery):
|
||||
install("externaltool")
|
||||
viewpath = str(tmpdir.mkdir("view"))
|
||||
output = view("symlink", viewpath, "externaltool")
|
||||
assert "Skipping external package: externaltool" in output
|
||||
|
||||
|
||||
def test_view_extension(tmpdir, mock_packages, mock_archive, mock_fetch, config, install_mockery):
|
||||
def test_view_extension(tmpdir, mock_packages, mock_archive, mock_fetch, install_mockery):
|
||||
install("extendee")
|
||||
install("extension1@1.0")
|
||||
install("extension1@2.0")
|
||||
@@ -136,9 +132,7 @@ def test_view_extension(tmpdir, mock_packages, mock_archive, mock_fetch, config,
|
||||
assert os.path.exists(os.path.join(viewpath, "bin", "extension1"))
|
||||
|
||||
|
||||
def test_view_extension_remove(
|
||||
tmpdir, mock_packages, mock_archive, mock_fetch, config, install_mockery
|
||||
):
|
||||
def test_view_extension_remove(tmpdir, mock_packages, mock_archive, mock_fetch, install_mockery):
|
||||
install("extendee")
|
||||
install("extension1@1.0")
|
||||
viewpath = str(tmpdir.mkdir("view"))
|
||||
@@ -149,9 +143,7 @@ def test_view_extension_remove(
|
||||
assert not os.path.exists(os.path.join(viewpath, "bin", "extension1"))
|
||||
|
||||
|
||||
def test_view_extension_conflict(
|
||||
tmpdir, mock_packages, mock_archive, mock_fetch, config, install_mockery
|
||||
):
|
||||
def test_view_extension_conflict(tmpdir, mock_packages, mock_archive, mock_fetch, install_mockery):
|
||||
install("extendee")
|
||||
install("extension1@1.0")
|
||||
install("extension1@2.0")
|
||||
@@ -162,7 +154,7 @@ def test_view_extension_conflict(
|
||||
|
||||
|
||||
def test_view_extension_conflict_ignored(
|
||||
tmpdir, mock_packages, mock_archive, mock_fetch, config, install_mockery
|
||||
tmpdir, mock_packages, mock_archive, mock_fetch, install_mockery
|
||||
):
|
||||
install("extendee")
|
||||
install("extension1@1.0")
|
||||
@@ -184,7 +176,7 @@ def test_view_fails_with_missing_projections_file(tmpdir):
|
||||
@pytest.mark.parametrize("with_projection", [False, True])
|
||||
@pytest.mark.parametrize("cmd", ["symlink", "copy"])
|
||||
def test_view_files_not_ignored(
|
||||
tmpdir, mock_packages, mock_archive, mock_fetch, config, install_mockery, cmd, with_projection
|
||||
tmpdir, mock_packages, mock_archive, mock_fetch, install_mockery, cmd, with_projection
|
||||
):
|
||||
spec = Spec("view-not-ignored").concretized()
|
||||
pkg = spec.package
|
||||
|
@@ -24,6 +24,7 @@
|
||||
import spack.platforms
|
||||
import spack.repo
|
||||
import spack.solver.asp
|
||||
import spack.store
|
||||
import spack.util.file_cache
|
||||
import spack.util.libc
|
||||
import spack.variant as vt
|
||||
@@ -410,7 +411,7 @@ def test_compiler_flags_from_compiler_and_dependent(self):
|
||||
def test_compiler_flags_differ_identical_compilers(self, mutable_config, clang12_with_flags):
|
||||
mutable_config.set("compilers", [clang12_with_flags])
|
||||
# Correct arch to use test compiler that has flags
|
||||
spec = Spec("a %clang@12.2.0 platform=test os=fe target=fe")
|
||||
spec = Spec("pkg-a %clang@12.2.0 platform=test os=fe target=fe")
|
||||
|
||||
# Get the compiler that matches the spec (
|
||||
compiler = spack.compilers.compiler_for_spec("clang@=12.2.0", spec.architecture)
|
||||
@@ -487,7 +488,7 @@ def test_architecture_deep_inheritance(self, mock_targets, compiler_factory):
|
||||
assert s.architecture.target == spec.architecture.target
|
||||
|
||||
def test_compiler_flags_from_user_are_grouped(self):
|
||||
spec = Spec('a%gcc cflags="-O -foo-flag foo-val" platform=test')
|
||||
spec = Spec('pkg-a%gcc cflags="-O -foo-flag foo-val" platform=test')
|
||||
spec.concretize()
|
||||
cflags = spec.compiler_flags["cflags"]
|
||||
assert any(x == "-foo-flag foo-val" for x in cflags)
|
||||
@@ -595,20 +596,20 @@ def test_concretize_propagate_multivalue_variant(self):
|
||||
spec = Spec("multivalue-variant foo==baz,fee")
|
||||
spec.concretize()
|
||||
|
||||
assert spec.satisfies("^a foo=baz,fee")
|
||||
assert spec.satisfies("^b foo=baz,fee")
|
||||
assert not spec.satisfies("^a foo=bar")
|
||||
assert not spec.satisfies("^b foo=bar")
|
||||
assert spec.satisfies("^pkg-a foo=baz,fee")
|
||||
assert spec.satisfies("^pkg-b foo=baz,fee")
|
||||
assert not spec.satisfies("^pkg-a foo=bar")
|
||||
assert not spec.satisfies("^pkg-b foo=bar")
|
||||
|
||||
def test_no_matching_compiler_specs(self, mock_low_high_config):
|
||||
# only relevant when not building compilers as needed
|
||||
with spack.concretize.enable_compiler_existence_check():
|
||||
s = Spec("a %gcc@=0.0.0")
|
||||
s = Spec("pkg-a %gcc@=0.0.0")
|
||||
with pytest.raises(spack.concretize.UnavailableCompilerVersionError):
|
||||
s.concretize()
|
||||
|
||||
def test_no_compilers_for_arch(self):
|
||||
s = Spec("a arch=linux-rhel0-x86_64")
|
||||
s = Spec("pkg-a arch=linux-rhel0-x86_64")
|
||||
with pytest.raises(spack.error.SpackError):
|
||||
s.concretize()
|
||||
|
||||
@@ -688,7 +689,8 @@ def test_nobuild_package(self):
|
||||
with pytest.raises(spack.error.SpecError):
|
||||
spec.concretize()
|
||||
|
||||
def test_external_and_virtual(self):
|
||||
def test_external_and_virtual(self, mutable_config):
|
||||
mutable_config.set("packages:stuff", {"buildable": False})
|
||||
spec = Spec("externaltest")
|
||||
spec.concretize()
|
||||
assert spec["externaltool"].external_path == os.path.sep + os.path.join(
|
||||
@@ -817,7 +819,7 @@ def test_regression_issue_7941(self):
|
||||
# The string representation of a spec containing
|
||||
# an explicit multi-valued variant and a dependency
|
||||
# might be parsed differently than the originating spec
|
||||
s = Spec("a foobar=bar ^b")
|
||||
s = Spec("pkg-a foobar=bar ^pkg-b")
|
||||
t = Spec(str(s))
|
||||
|
||||
s.concretize()
|
||||
@@ -1170,16 +1172,14 @@ def test_external_that_would_require_a_virtual_dependency(self):
|
||||
assert s.external
|
||||
assert "stuff" not in s
|
||||
|
||||
def test_transitive_conditional_virtual_dependency(self):
|
||||
def test_transitive_conditional_virtual_dependency(self, mutable_config):
|
||||
"""Test that an external is used as provider if the virtual is non-buildable"""
|
||||
mutable_config.set("packages:stuff", {"buildable": False})
|
||||
s = Spec("transitive-conditional-virtual-dependency").concretized()
|
||||
|
||||
# The default for conditional-virtual-dependency is to have
|
||||
# +stuff~mpi, so check that these defaults are respected
|
||||
assert "+stuff" in s["conditional-virtual-dependency"]
|
||||
assert "~mpi" in s["conditional-virtual-dependency"]
|
||||
|
||||
# 'stuff' is provided by an external package, so check it's present
|
||||
assert "externalvirtual" in s
|
||||
# Test that the default +stuff~mpi is maintained, and the right provider is selected
|
||||
assert s.satisfies("^conditional-virtual-dependency +stuff~mpi")
|
||||
assert s.satisfies("^[virtuals=stuff] externalvirtual")
|
||||
|
||||
@pytest.mark.regression("20040")
|
||||
@pytest.mark.only_clingo("Use case not supported by the original concretizer")
|
||||
@@ -1197,14 +1197,14 @@ def test_conditional_provides_or_depends_on(self):
|
||||
[
|
||||
# Check that True is treated correctly and attaches test deps
|
||||
# to all nodes in the DAG
|
||||
("a", True, ["a"], []),
|
||||
("a foobar=bar", True, ["a", "b"], []),
|
||||
("pkg-a", True, ["pkg-a"], []),
|
||||
("pkg-a foobar=bar", True, ["pkg-a", "pkg-b"], []),
|
||||
# Check that a list of names activates the dependency only for
|
||||
# packages in that list
|
||||
("a foobar=bar", ["a"], ["a"], ["b"]),
|
||||
("a foobar=bar", ["b"], ["b"], ["a"]),
|
||||
("pkg-a foobar=bar", ["pkg-a"], ["pkg-a"], ["pkg-b"]),
|
||||
("pkg-a foobar=bar", ["pkg-b"], ["pkg-b"], ["pkg-a"]),
|
||||
# Check that False disregard test dependencies
|
||||
("a foobar=bar", False, [], ["a", "b"]),
|
||||
("pkg-a foobar=bar", False, [], ["pkg-a", "pkg-b"]),
|
||||
],
|
||||
)
|
||||
def test_activating_test_dependencies(self, spec_str, tests_arg, with_dep, without_dep):
|
||||
@@ -1263,7 +1263,7 @@ def test_custom_compiler_version(self, mutable_config, compiler_factory, monkeyp
|
||||
"compilers", [compiler_factory(spec="gcc@10foo", operating_system="redhat6")]
|
||||
)
|
||||
monkeypatch.setattr(spack.compiler.Compiler, "real_version", "10.2.1")
|
||||
s = Spec("a %gcc@10foo os=redhat6").concretized()
|
||||
s = Spec("pkg-a %gcc@10foo os=redhat6").concretized()
|
||||
assert "%gcc@10foo" in s
|
||||
|
||||
def test_all_patches_applied(self):
|
||||
@@ -1407,10 +1407,10 @@ def test_no_reuse_when_variant_condition_does_not_hold(self, mutable_database, m
|
||||
@pytest.mark.only_clingo("Use case not supported by the original concretizer")
|
||||
def test_reuse_with_flags(self, mutable_database, mutable_config):
|
||||
spack.config.set("concretizer:reuse", True)
|
||||
spec = Spec("a cflags=-g cxxflags=-g").concretized()
|
||||
spec = Spec("pkg-a cflags=-g cxxflags=-g").concretized()
|
||||
spack.store.STORE.db.add(spec, None)
|
||||
|
||||
testspec = Spec("a cflags=-g")
|
||||
testspec = Spec("pkg-a cflags=-g")
|
||||
testspec.concretize()
|
||||
assert testspec == spec
|
||||
|
||||
@@ -1593,7 +1593,7 @@ def test_non_default_provider_of_multiple_virtuals(self):
|
||||
)
|
||||
@pytest.mark.only_clingo("Use case not supported by the original concretizer")
|
||||
def test_concrete_specs_are_not_modified_on_reuse(
|
||||
self, mutable_database, spec_str, expect_installed, config
|
||||
self, mutable_database, spec_str, expect_installed
|
||||
):
|
||||
# Test the internal consistency of solve + DAG reconstruction
|
||||
# when reused specs are added to the mix. This prevents things
|
||||
@@ -1753,31 +1753,31 @@ def test_reuse_with_unknown_namespace_dont_raise(
|
||||
self, temporary_store, mock_custom_repository
|
||||
):
|
||||
with spack.repo.use_repositories(mock_custom_repository, override=False):
|
||||
s = Spec("c").concretized()
|
||||
s = Spec("pkg-c").concretized()
|
||||
assert s.namespace != "builtin.mock"
|
||||
s.package.do_install(fake=True, explicit=True)
|
||||
|
||||
with spack.config.override("concretizer:reuse", True):
|
||||
s = Spec("c").concretized()
|
||||
s = Spec("pkg-c").concretized()
|
||||
assert s.namespace == "builtin.mock"
|
||||
|
||||
@pytest.mark.regression("28259")
|
||||
def test_reuse_with_unknown_package_dont_raise(self, tmpdir, temporary_store, monkeypatch):
|
||||
builder = spack.repo.MockRepositoryBuilder(tmpdir.mkdir("mock.repo"), namespace="myrepo")
|
||||
builder.add_package("c")
|
||||
builder.add_package("pkg-c")
|
||||
with spack.repo.use_repositories(builder.root, override=False):
|
||||
s = Spec("c").concretized()
|
||||
s = Spec("pkg-c").concretized()
|
||||
assert s.namespace == "myrepo"
|
||||
s.package.do_install(fake=True, explicit=True)
|
||||
|
||||
del sys.modules["spack.pkg.myrepo.c"]
|
||||
del sys.modules["spack.pkg.myrepo.pkg-c"]
|
||||
del sys.modules["spack.pkg.myrepo"]
|
||||
builder.remove("c")
|
||||
builder.remove("pkg-c")
|
||||
with spack.repo.use_repositories(builder.root, override=False) as repos:
|
||||
# TODO (INJECT CONFIGURATION): unclear why the cache needs to be invalidated explicitly
|
||||
repos.repos[0]._pkg_checker.invalidate()
|
||||
with spack.config.override("concretizer:reuse", True):
|
||||
s = Spec("c").concretized()
|
||||
s = Spec("pkg-c").concretized()
|
||||
assert s.namespace == "builtin.mock"
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@@ -1785,7 +1785,7 @@ def test_reuse_with_unknown_package_dont_raise(self, tmpdir, temporary_store, mo
|
||||
[
|
||||
(["libelf", "libelf@0.8.10"], 1, 1),
|
||||
(["libdwarf%gcc", "libelf%clang"], 2, 1),
|
||||
(["libdwarf%gcc", "libdwarf%clang"], 3, 2),
|
||||
(["libdwarf%gcc", "libdwarf%clang"], 3, 1),
|
||||
(["libdwarf^libelf@0.8.12", "libdwarf^libelf@0.8.13"], 4, 1),
|
||||
(["hdf5", "zmpi"], 3, 1),
|
||||
(["hdf5", "mpich"], 2, 1),
|
||||
@@ -1856,7 +1856,7 @@ def test_best_effort_coconcretize_preferences(self, specs, expected_spec, occura
|
||||
assert counter == occurances, concrete_specs
|
||||
|
||||
@pytest.mark.only_clingo("Original concretizer cannot concretize in rounds")
|
||||
def test_solve_in_rounds_all_unsolved(self, monkeypatch, mock_packages, config):
|
||||
def test_solve_in_rounds_all_unsolved(self, monkeypatch, mock_packages):
|
||||
specs = [Spec(x) for x in ["libdwarf%gcc", "libdwarf%clang"]]
|
||||
solver = spack.solver.asp.Solver()
|
||||
solver.reuse = False
|
||||
@@ -1908,20 +1908,20 @@ def test_misleading_error_message_on_version(self, mutable_database):
|
||||
@pytest.mark.only_clingo("Use case not supported by the original concretizer")
|
||||
def test_version_weight_and_provenance(self):
|
||||
"""Test package preferences during coconcretization."""
|
||||
reusable_specs = [Spec(spec_str).concretized() for spec_str in ("b@0.9", "b@1.0")]
|
||||
root_spec = Spec("a foobar=bar")
|
||||
reusable_specs = [Spec(spec_str).concretized() for spec_str in ("pkg-b@0.9", "pkg-b@1.0")]
|
||||
root_spec = Spec("pkg-a foobar=bar")
|
||||
|
||||
with spack.config.override("concretizer:reuse", True):
|
||||
solver = spack.solver.asp.Solver()
|
||||
setup = spack.solver.asp.SpackSolverSetup()
|
||||
result, _, _ = solver.driver.solve(setup, [root_spec], reuse=reusable_specs)
|
||||
# The result here should have a single spec to build ('a')
|
||||
# and it should be using b@1.0 with a version badness of 2
|
||||
# The result here should have a single spec to build ('pkg-a')
|
||||
# and it should be using pkg-b@1.0 with a version badness of 2
|
||||
# The provenance is:
|
||||
# version_declared("b","1.0",0,"package_py").
|
||||
# version_declared("b","0.9",1,"package_py").
|
||||
# version_declared("b","1.0",2,"installed").
|
||||
# version_declared("b","0.9",3,"installed").
|
||||
# version_declared("pkg-b","1.0",0,"package_py").
|
||||
# version_declared("pkg-b","0.9",1,"package_py").
|
||||
# version_declared("pkg-b","1.0",2,"installed").
|
||||
# version_declared("pkg-b","0.9",3,"installed").
|
||||
#
|
||||
# Depending on the target, it may also use gnuconfig
|
||||
result_spec = result.specs[0]
|
||||
@@ -1935,11 +1935,11 @@ def test_version_weight_and_provenance(self):
|
||||
|
||||
for criterion in criteria:
|
||||
assert criterion in result.criteria, criterion
|
||||
assert result_spec.satisfies("^b@1.0")
|
||||
assert result_spec.satisfies("^pkg-b@1.0")
|
||||
|
||||
@pytest.mark.only_clingo("Use case not supported by the original concretizer")
|
||||
def test_reuse_succeeds_with_config_compatible_os(self):
|
||||
root_spec = Spec("b")
|
||||
root_spec = Spec("pkg-b")
|
||||
s = root_spec.concretized()
|
||||
other_os = s.copy()
|
||||
mock_os = "ubuntu2204"
|
||||
@@ -2203,7 +2203,7 @@ def test_external_python_extension_find_unified_python(self):
|
||||
"specs",
|
||||
[
|
||||
["mpileaks^ callpath ^dyninst@8.1.1:8 ^mpich2@1.3:1"],
|
||||
["multivalue-variant ^a@2:2"],
|
||||
["multivalue-variant ^pkg-a@2:2"],
|
||||
["v1-consumer ^conditional-provider@1:1 +disable-v1"],
|
||||
],
|
||||
)
|
||||
@@ -2219,7 +2219,7 @@ def test_result_specs_is_not_empty(self, specs):
|
||||
assert result.specs
|
||||
|
||||
@pytest.mark.regression("38664")
|
||||
def test_unsolved_specs_raises_error(self, monkeypatch, mock_packages, config):
|
||||
def test_unsolved_specs_raises_error(self, monkeypatch, mock_packages):
|
||||
"""Check that the solver raises an exception when input specs are not
|
||||
satisfied.
|
||||
"""
|
||||
@@ -2239,12 +2239,12 @@ def test_unsolved_specs_raises_error(self, monkeypatch, mock_packages, config):
|
||||
|
||||
@pytest.mark.regression("43141")
|
||||
@pytest.mark.only_clingo("Use case not supported by the original concretizer")
|
||||
def test_clear_error_when_unknown_compiler_requested(self, mock_packages, config):
|
||||
def test_clear_error_when_unknown_compiler_requested(self, mock_packages):
|
||||
"""Tests that the solver can report a case where the compiler cannot be set"""
|
||||
with pytest.raises(
|
||||
spack.error.UnsatisfiableSpecError, match="Cannot set the required compiler: a%foo"
|
||||
spack.error.UnsatisfiableSpecError, match="Cannot set the required compiler: pkg-a%foo"
|
||||
):
|
||||
Spec("a %foo").concretized()
|
||||
Spec("pkg-a %foo").concretized()
|
||||
|
||||
@pytest.mark.regression("36339")
|
||||
def test_compiler_match_constraints_when_selected(self):
|
||||
@@ -2280,7 +2280,7 @@ def test_compiler_match_constraints_when_selected(self):
|
||||
},
|
||||
]
|
||||
spack.config.set("compilers", compiler_configuration)
|
||||
s = Spec("a %gcc@:11").concretized()
|
||||
s = Spec("pkg-a %gcc@:11").concretized()
|
||||
assert s.compiler.version == ver("=11.1.0"), s
|
||||
|
||||
@pytest.mark.regression("36339")
|
||||
@@ -2301,7 +2301,7 @@ def test_compiler_with_custom_non_numeric_version(self, mock_executable):
|
||||
}
|
||||
]
|
||||
spack.config.set("compilers", compiler_configuration)
|
||||
s = Spec("a %gcc@foo").concretized()
|
||||
s = Spec("pkg-a %gcc@foo").concretized()
|
||||
assert s.compiler.version == ver("=foo")
|
||||
|
||||
@pytest.mark.regression("36628")
|
||||
@@ -2327,13 +2327,13 @@ def test_concretization_with_compilers_supporting_target_any(self):
|
||||
]
|
||||
|
||||
with spack.config.override("compilers", compiler_configuration):
|
||||
s = spack.spec.Spec("a").concretized()
|
||||
s = Spec("pkg-a").concretized()
|
||||
assert s.satisfies("%gcc@12.1.0")
|
||||
|
||||
@pytest.mark.parametrize("spec_str", ["mpileaks", "mpileaks ^mpich"])
|
||||
def test_virtuals_are_annotated_on_edges(self, spec_str, default_mock_concretization):
|
||||
def test_virtuals_are_annotated_on_edges(self, spec_str):
|
||||
"""Tests that information on virtuals is annotated on DAG edges"""
|
||||
spec = default_mock_concretization(spec_str)
|
||||
spec = Spec(spec_str).concretized()
|
||||
mpi_provider = spec["mpi"].name
|
||||
|
||||
edges = spec.edges_to_dependencies(name=mpi_provider)
|
||||
@@ -2347,7 +2347,7 @@ def test_virtuals_are_annotated_on_edges(self, spec_str, default_mock_concretiza
|
||||
"spec_str,mpi_name",
|
||||
[("mpileaks", "mpich"), ("mpileaks ^mpich2", "mpich2"), ("mpileaks ^zmpi", "zmpi")],
|
||||
)
|
||||
def test_virtuals_are_reconstructed_on_reuse(self, spec_str, mpi_name, database):
|
||||
def test_virtuals_are_reconstructed_on_reuse(self, spec_str, mpi_name, mutable_database):
|
||||
"""Tests that when we reuse a spec, virtual on edges are reconstructed correctly"""
|
||||
with spack.config.override("concretizer:reuse", True):
|
||||
spec = Spec(spec_str).concretized()
|
||||
@@ -2362,7 +2362,7 @@ def test_dont_define_new_version_from_input_if_checksum_required(self, working_e
|
||||
with pytest.raises(spack.error.UnsatisfiableSpecError):
|
||||
# normally spack concretizes to @=3.0 if it's not defined in package.py, except
|
||||
# when checksums are required
|
||||
Spec("a@=3.0").concretized()
|
||||
Spec("pkg-a@=3.0").concretized()
|
||||
|
||||
@pytest.mark.regression("39570")
|
||||
@pytest.mark.db
|
||||
@@ -2462,7 +2462,7 @@ def _default_libc(self):
|
||||
spack.util.libc, "libc_from_current_python_process", lambda: Spec("glibc@=2.28")
|
||||
)
|
||||
mutable_config.set("config:install_missing_compilers", True)
|
||||
s = Spec("a %gcc@=13.2.0").concretized()
|
||||
s = Spec("pkg-a %gcc@=13.2.0").concretized()
|
||||
assert s.satisfies("%gcc@13.2.0")
|
||||
|
||||
@pytest.mark.regression("43267")
|
||||
@@ -2595,17 +2595,17 @@ def test_cannot_reuse_host_incompatible_libc(self):
|
||||
|
||||
# We install b@1 ^glibc@2.30, and b@0 ^glibc@2.28. The former is not host compatible, the
|
||||
# latter is.
|
||||
fst = Spec("b@1").concretized()
|
||||
fst = Spec("pkg-b@1").concretized()
|
||||
fst._mark_concrete(False)
|
||||
fst.dependencies("glibc")[0].versions = VersionList(["=2.30"])
|
||||
fst._mark_concrete(True)
|
||||
snd = Spec("b@0").concretized()
|
||||
snd = Spec("pkg-b@0").concretized()
|
||||
|
||||
# The spec b@1 ^glibc@2.30 is "more optimal" than b@0 ^glibc@2.28, but due to glibc
|
||||
# incompatibility, it should not be reused.
|
||||
solver = spack.solver.asp.Solver()
|
||||
setup = spack.solver.asp.SpackSolverSetup()
|
||||
result, _, _ = solver.driver.solve(setup, [Spec("b")], reuse=[fst, snd])
|
||||
result, _, _ = solver.driver.solve(setup, [Spec("pkg-b")], reuse=[fst, snd])
|
||||
assert len(result.specs) == 1
|
||||
assert result.specs[0] == snd
|
||||
|
||||
@@ -2810,7 +2810,9 @@ def test_drop_moving_targets(v_str, v_opts, checksummed):
|
||||
class TestConcreteSpecsByHash:
|
||||
"""Tests the container of concrete specs"""
|
||||
|
||||
@pytest.mark.parametrize("input_specs", [["a"], ["a foobar=bar", "b"], ["a foobar=baz", "b"]])
|
||||
@pytest.mark.parametrize(
|
||||
"input_specs", [["pkg-a"], ["pkg-a foobar=bar", "pkg-b"], ["pkg-a foobar=baz", "pkg-b"]]
|
||||
)
|
||||
def test_adding_specs(self, input_specs, default_mock_concretization):
|
||||
"""Tests that concrete specs in the container are equivalent, but stored as different
|
||||
objects in memory.
|
||||
@@ -3006,7 +3008,7 @@ def test_concretization_version_order():
|
||||
),
|
||||
],
|
||||
)
|
||||
@pytest.mark.usefixtures("database", "mock_store")
|
||||
@pytest.mark.usefixtures("mutable_database", "mock_store")
|
||||
@pytest.mark.not_on_windows("Expected length is different on Windows")
|
||||
def test_filtering_reused_specs(
|
||||
roots, reuse_yaml, expected, not_expected, expected_length, mutable_config, monkeypatch
|
||||
@@ -3027,7 +3029,7 @@ def test_filtering_reused_specs(
|
||||
assert all(not x.satisfies(constraint) for x in specs)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("database", "mock_store")
|
||||
@pytest.mark.usefixtures("mutable_database", "mock_store")
|
||||
@pytest.mark.parametrize(
|
||||
"reuse_yaml,expected_length",
|
||||
[({"from": [{"type": "local"}]}, 17), ({"from": [{"type": "buildcache"}]}, 0)],
|
||||
@@ -3063,9 +3065,7 @@ def test_spec_filters(specs, include, exclude, expected):
|
||||
|
||||
@pytest.mark.only_clingo("clingo only reuse feature being tested")
|
||||
@pytest.mark.regression("38484")
|
||||
def test_git_ref_version_can_be_reused(
|
||||
install_mockery_mutable_config, do_not_check_runtimes_on_reuse
|
||||
):
|
||||
def test_git_ref_version_can_be_reused(install_mockery, do_not_check_runtimes_on_reuse):
|
||||
first_spec = spack.spec.Spec("git-ref-package@git.2.1.5=2.1.5~opt").concretized()
|
||||
first_spec.package.do_install(fake=True, explicit=True)
|
||||
|
||||
@@ -3084,7 +3084,7 @@ def test_git_ref_version_can_be_reused(
|
||||
@pytest.mark.only_clingo("clingo only reuse feature being tested")
|
||||
@pytest.mark.parametrize("standard_version", ["2.0.0", "2.1.5", "2.1.6"])
|
||||
def test_reuse_prefers_standard_over_git_versions(
|
||||
standard_version, install_mockery_mutable_config, do_not_check_runtimes_on_reuse
|
||||
standard_version, install_mockery, do_not_check_runtimes_on_reuse
|
||||
):
|
||||
"""
|
||||
order matters in this test. typically reuse would pick the highest versioned installed match
|
||||
|
@@ -9,6 +9,7 @@
|
||||
|
||||
import archspec.cpu
|
||||
|
||||
import spack.config
|
||||
import spack.paths
|
||||
import spack.repo
|
||||
import spack.solver.asp
|
||||
@@ -32,7 +33,7 @@ def _concretize_with_reuse(*, root_str, reused_str):
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def runtime_repo(config):
|
||||
def runtime_repo(mutable_config):
|
||||
repo = os.path.join(spack.paths.repos_path, "compiler_runtime.test")
|
||||
with spack.repo.use_repositories(repo) as mock_repo:
|
||||
yield mock_repo
|
||||
@@ -47,8 +48,8 @@ def enable_runtimes():
|
||||
|
||||
|
||||
def test_correct_gcc_runtime_is_injected_as_dependency(runtime_repo):
|
||||
s = spack.spec.Spec("a%gcc@10.2.1 ^b%gcc@9.4.0").concretized()
|
||||
a, b = s["a"], s["b"]
|
||||
s = spack.spec.Spec("pkg-a%gcc@10.2.1 ^pkg-b%gcc@9.4.0").concretized()
|
||||
a, b = s["pkg-a"], s["pkg-b"]
|
||||
|
||||
# Both a and b should depend on the same gcc-runtime directly
|
||||
assert a.dependencies("gcc-runtime") == b.dependencies("gcc-runtime")
|
||||
@@ -61,16 +62,16 @@ def test_correct_gcc_runtime_is_injected_as_dependency(runtime_repo):
|
||||
def test_external_nodes_do_not_have_runtimes(runtime_repo, mutable_config, tmp_path):
|
||||
"""Tests that external nodes don't have runtime dependencies."""
|
||||
|
||||
packages_yaml = {"b": {"externals": [{"spec": "b@1.0", "prefix": f"{str(tmp_path)}"}]}}
|
||||
packages_yaml = {"pkg-b": {"externals": [{"spec": "pkg-b@1.0", "prefix": f"{str(tmp_path)}"}]}}
|
||||
spack.config.set("packages", packages_yaml)
|
||||
|
||||
s = spack.spec.Spec("a%gcc@10.2.1").concretized()
|
||||
s = spack.spec.Spec("pkg-a%gcc@10.2.1").concretized()
|
||||
|
||||
a, b = s["a"], s["b"]
|
||||
a, b = s["pkg-a"], s["pkg-b"]
|
||||
|
||||
# Since b is an external, it doesn't depend on gcc-runtime
|
||||
assert a.dependencies("gcc-runtime")
|
||||
assert a.dependencies("b")
|
||||
assert a.dependencies("pkg-b")
|
||||
assert not b.dependencies("gcc-runtime")
|
||||
|
||||
|
||||
@@ -78,23 +79,36 @@ def test_external_nodes_do_not_have_runtimes(runtime_repo, mutable_config, tmp_p
|
||||
"root_str,reused_str,expected,nruntime",
|
||||
[
|
||||
# The reused runtime is older than we need, thus we'll add a more recent one for a
|
||||
("a%gcc@10.2.1", "b%gcc@9.4.0", {"a": "gcc-runtime@10.2.1", "b": "gcc-runtime@9.4.0"}, 2),
|
||||
(
|
||||
"pkg-a%gcc@10.2.1",
|
||||
"pkg-b%gcc@9.4.0",
|
||||
{"pkg-a": "gcc-runtime@10.2.1", "pkg-b": "gcc-runtime@9.4.0"},
|
||||
2,
|
||||
),
|
||||
# The root is compiled with an older compiler, thus we'll NOT reuse the runtime from b
|
||||
("a%gcc@9.4.0", "b%gcc@10.2.1", {"a": "gcc-runtime@9.4.0", "b": "gcc-runtime@9.4.0"}, 1),
|
||||
(
|
||||
"pkg-a%gcc@9.4.0",
|
||||
"pkg-b%gcc@10.2.1",
|
||||
{"pkg-a": "gcc-runtime@9.4.0", "pkg-b": "gcc-runtime@9.4.0"},
|
||||
1,
|
||||
),
|
||||
# Same as before, but tests that we can reuse from a more generic target
|
||||
pytest.param(
|
||||
"a%gcc@9.4.0",
|
||||
"b%gcc@10.2.1 target=x86_64",
|
||||
{"a": "gcc-runtime@9.4.0", "b": "gcc-runtime@9.4.0"},
|
||||
"pkg-a%gcc@9.4.0",
|
||||
"pkg-b%gcc@10.2.1 target=x86_64",
|
||||
{"pkg-a": "gcc-runtime@9.4.0", "pkg-b": "gcc-runtime@9.4.0"},
|
||||
1,
|
||||
marks=pytest.mark.skipif(
|
||||
str(archspec.cpu.host().family) != "x86_64", reason="test data is x86_64 specific"
|
||||
),
|
||||
),
|
||||
pytest.param(
|
||||
"a%gcc@10.2.1",
|
||||
"b%gcc@9.4.0 target=x86_64",
|
||||
{"a": "gcc-runtime@10.2.1 target=x86_64", "b": "gcc-runtime@9.4.0 target=x86_64"},
|
||||
"pkg-a%gcc@10.2.1",
|
||||
"pkg-b%gcc@9.4.0 target=x86_64",
|
||||
{
|
||||
"pkg-a": "gcc-runtime@10.2.1 target=x86_64",
|
||||
"pkg-b": "gcc-runtime@9.4.0 target=x86_64",
|
||||
},
|
||||
2,
|
||||
marks=pytest.mark.skipif(
|
||||
str(archspec.cpu.host().family) != "x86_64", reason="test data is x86_64 specific"
|
||||
@@ -112,9 +126,9 @@ def test_reusing_specs_with_gcc_runtime(root_str, reused_str, expected, nruntime
|
||||
root, reused_spec = _concretize_with_reuse(root_str=root_str, reused_str=reused_str)
|
||||
|
||||
runtime_a = root.dependencies("gcc-runtime")[0]
|
||||
assert runtime_a.satisfies(expected["a"])
|
||||
runtime_b = root["b"].dependencies("gcc-runtime")[0]
|
||||
assert runtime_b.satisfies(expected["b"])
|
||||
assert runtime_a.satisfies(expected["pkg-a"])
|
||||
runtime_b = root["pkg-b"].dependencies("gcc-runtime")[0]
|
||||
assert runtime_b.satisfies(expected["pkg-b"])
|
||||
|
||||
runtimes = [x for x in root.traverse() if x.name == "gcc-runtime"]
|
||||
assert len(runtimes) == nruntime
|
||||
@@ -125,7 +139,7 @@ def test_reusing_specs_with_gcc_runtime(root_str, reused_str, expected, nruntime
|
||||
[
|
||||
# Ensure that, whether we have multiple runtimes in the DAG or not,
|
||||
# we always link only the latest version
|
||||
("a%gcc@10.2.1", "b%gcc@9.4.0", ["gcc-runtime@10.2.1"], ["gcc-runtime@9.4.0"])
|
||||
("pkg-a%gcc@10.2.1", "pkg-b%gcc@9.4.0", ["gcc-runtime@10.2.1"], ["gcc-runtime@9.4.0"])
|
||||
],
|
||||
)
|
||||
def test_views_can_handle_duplicate_runtime_nodes(
|
||||
|
@@ -516,5 +516,5 @@ def test_default_preference_variant_different_type_does_not_error(self):
|
||||
packages.yaml doesn't fail with an error.
|
||||
"""
|
||||
with spack.config.override("packages:all", {"variants": "+foo"}):
|
||||
s = Spec("a").concretized()
|
||||
s = Spec("pkg-a").concretized()
|
||||
assert s.satisfies("foo=bar")
|
||||
|
@@ -927,9 +927,9 @@ def test_default_requirements_semantic(packages_yaml, concretize_scope, mock_pac
|
||||
Spec("zlib ~shared").concretized()
|
||||
|
||||
# A spec without the shared variant still concretize
|
||||
s = Spec("a").concretized()
|
||||
assert not s.satisfies("a +shared")
|
||||
assert not s.satisfies("a ~shared")
|
||||
s = Spec("pkg-a").concretized()
|
||||
assert not s.satisfies("pkg-a +shared")
|
||||
assert not s.satisfies("pkg-a ~shared")
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
|
@@ -13,7 +13,7 @@
|
||||
import pytest
|
||||
|
||||
import llnl.util.tty as tty
|
||||
from llnl.util.filesystem import getuid, join_path, mkdirp, touch, touchp
|
||||
from llnl.util.filesystem import join_path, touch, touchp
|
||||
|
||||
import spack.config
|
||||
import spack.directory_layout
|
||||
@@ -864,26 +864,18 @@ def test_bad_config_section(mock_low_high_config):
|
||||
spack.config.get("foobar")
|
||||
|
||||
|
||||
@pytest.mark.not_on_windows("chmod not supported on Windows")
|
||||
@pytest.mark.skipif(getuid() == 0, reason="user is root")
|
||||
def test_bad_command_line_scopes(tmpdir, config):
|
||||
def test_bad_command_line_scopes(tmp_path, config):
|
||||
cfg = spack.config.Configuration()
|
||||
file_path = tmp_path / "file_instead_of_dir"
|
||||
non_existing_path = tmp_path / "non_existing_dir"
|
||||
|
||||
with tmpdir.as_cwd():
|
||||
with pytest.raises(spack.config.ConfigError):
|
||||
spack.config._add_command_line_scopes(cfg, ["bad_path"])
|
||||
file_path.write_text("")
|
||||
|
||||
touch("unreadable_file")
|
||||
with pytest.raises(spack.config.ConfigError):
|
||||
spack.config._add_command_line_scopes(cfg, ["unreadable_file"])
|
||||
with pytest.raises(spack.config.ConfigError):
|
||||
spack.config._add_command_line_scopes(cfg, [str(file_path)])
|
||||
|
||||
mkdirp("unreadable_dir")
|
||||
with pytest.raises(spack.config.ConfigError):
|
||||
try:
|
||||
os.chmod("unreadable_dir", 0)
|
||||
spack.config._add_command_line_scopes(cfg, ["unreadable_dir"])
|
||||
finally:
|
||||
os.chmod("unreadable_dir", 0o700) # so tmpdir can be removed
|
||||
with pytest.raises(spack.config.ConfigError):
|
||||
spack.config._add_command_line_scopes(cfg, [str(non_existing_path)])
|
||||
|
||||
|
||||
def test_add_command_line_scopes(tmpdir, mutable_config):
|
||||
@@ -898,6 +890,45 @@ def test_add_command_line_scopes(tmpdir, mutable_config):
|
||||
)
|
||||
|
||||
spack.config._add_command_line_scopes(mutable_config, [str(tmpdir)])
|
||||
assert mutable_config.get("config:verify_ssl") is False
|
||||
assert mutable_config.get("config:dirty") is False
|
||||
|
||||
|
||||
def test_add_command_line_scope_env(tmp_path, mutable_mock_env_path):
|
||||
"""Test whether --config-scope <env> works, either by name or path."""
|
||||
managed_env = ev.create("example").manifest_path
|
||||
|
||||
with open(managed_env, "w") as f:
|
||||
f.write(
|
||||
"""\
|
||||
spack:
|
||||
config:
|
||||
install_tree:
|
||||
root: /tmp/first
|
||||
"""
|
||||
)
|
||||
|
||||
with open(tmp_path / "spack.yaml", "w") as f:
|
||||
f.write(
|
||||
"""\
|
||||
spack:
|
||||
config:
|
||||
install_tree:
|
||||
root: /tmp/second
|
||||
"""
|
||||
)
|
||||
|
||||
config = spack.config.Configuration()
|
||||
spack.config._add_command_line_scopes(config, ["example", str(tmp_path)])
|
||||
assert len(config.scopes) == 2
|
||||
assert config.get("config:install_tree:root") == "/tmp/second"
|
||||
|
||||
config = spack.config.Configuration()
|
||||
spack.config._add_command_line_scopes(config, [str(tmp_path), "example"])
|
||||
assert len(config.scopes) == 2
|
||||
assert config.get("config:install_tree:root") == "/tmp/first"
|
||||
|
||||
assert ev.active_environment() is None # shouldn't cause an environment to be activated
|
||||
|
||||
|
||||
def test_nested_override():
|
||||
@@ -1210,13 +1241,13 @@ def test_license_dir_config(mutable_config, mock_packages):
|
||||
expected_dir = spack.paths.default_license_dir
|
||||
assert spack.config.get("config:license_dir") == expected_dir
|
||||
assert spack.package_base.PackageBase.global_license_dir == expected_dir
|
||||
assert spack.repo.PATH.get_pkg_class("a").global_license_dir == expected_dir
|
||||
assert spack.repo.PATH.get_pkg_class("pkg-a").global_license_dir == expected_dir
|
||||
|
||||
rel_path = os.path.join(os.path.sep, "foo", "bar", "baz")
|
||||
spack.config.set("config:license_dir", rel_path)
|
||||
assert spack.config.get("config:license_dir") == rel_path
|
||||
assert spack.package_base.PackageBase.global_license_dir == rel_path
|
||||
assert spack.repo.PATH.get_pkg_class("a").global_license_dir == rel_path
|
||||
assert spack.repo.PATH.get_pkg_class("pkg-a").global_license_dir == rel_path
|
||||
|
||||
|
||||
@pytest.mark.regression("22547")
|
||||
|
@@ -63,6 +63,12 @@
|
||||
from spack.util.pattern import Bunch
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def check_config_fixture(request):
|
||||
if "config" in request.fixturenames and "mutable_config" in request.fixturenames:
|
||||
raise RuntimeError("'config' and 'mutable_config' are both requested")
|
||||
|
||||
|
||||
def ensure_configuration_fixture_run_before(request):
|
||||
"""Ensure that fixture mutating the configuration run before the one where
|
||||
the function is called.
|
||||
@@ -597,7 +603,7 @@ def mutable_mock_repo(mock_repo_path, request):
|
||||
def mock_custom_repository(tmpdir, mutable_mock_repo):
|
||||
"""Create a custom repository with a single package "c" and return its path."""
|
||||
builder = spack.repo.MockRepositoryBuilder(tmpdir.mkdir("myrepo"))
|
||||
builder.add_package("c")
|
||||
builder.add_package("pkg-c")
|
||||
return builder.root
|
||||
|
||||
|
||||
@@ -851,7 +857,7 @@ def _install(spec):
|
||||
_install("mpileaks ^mpich")
|
||||
_install("mpileaks ^mpich2")
|
||||
_install("mpileaks ^zmpi")
|
||||
_install("externaltest")
|
||||
_install("externaltest ^externalvirtual")
|
||||
_install("trivial-smoke-test")
|
||||
|
||||
|
||||
@@ -992,19 +998,6 @@ def temporary_store(tmpdir, request):
|
||||
temporary_store_path.remove()
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def install_mockery_mutable_config(temporary_store, mutable_config, mock_packages):
|
||||
"""Hooks a fake install directory, DB, and stage directory into Spack.
|
||||
|
||||
This is specifically for tests which want to use 'install_mockery' but
|
||||
also need to modify configuration (and hence would want to use
|
||||
'mutable config'): 'install_mockery' does not support this.
|
||||
"""
|
||||
# We use a fake package, so temporarily disable checksumming
|
||||
with spack.config.override("config:checksum", False):
|
||||
yield
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def mock_fetch(mock_archive, monkeypatch):
|
||||
"""Fake the URL for a package so it downloads from a file."""
|
||||
@@ -2069,4 +2062,5 @@ def _c_compiler_always_exists():
|
||||
@pytest.fixture(scope="session")
|
||||
def mock_test_cache(tmp_path_factory):
|
||||
cache_dir = tmp_path_factory.mktemp("cache")
|
||||
print(cache_dir)
|
||||
return spack.util.file_cache.FileCache(str(cache_dir))
|
||||
|
@@ -58,16 +58,22 @@ def upstream_and_downstream_db(tmpdir, gen_mock_layout):
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"install_tree,result",
|
||||
[("all", ["b", "c"]), ("upstream", ["c"]), ("local", ["b"]), ("{u}", ["c"]), ("{d}", ["b"])],
|
||||
[
|
||||
("all", ["pkg-b", "pkg-c"]),
|
||||
("upstream", ["pkg-c"]),
|
||||
("local", ["pkg-b"]),
|
||||
("{u}", ["pkg-c"]),
|
||||
("{d}", ["pkg-b"]),
|
||||
],
|
||||
)
|
||||
def test_query_by_install_tree(
|
||||
install_tree, result, upstream_and_downstream_db, mock_packages, monkeypatch, config
|
||||
):
|
||||
up_write_db, up_db, up_layout, down_db, down_layout = upstream_and_downstream_db
|
||||
|
||||
# Set the upstream DB to contain "c" and downstream to contain "b")
|
||||
b = spack.spec.Spec("b").concretized()
|
||||
c = spack.spec.Spec("c").concretized()
|
||||
# Set the upstream DB to contain "pkg-c" and downstream to contain "pkg-b")
|
||||
b = spack.spec.Spec("pkg-b").concretized()
|
||||
c = spack.spec.Spec("pkg-c").concretized()
|
||||
up_write_db.add(c, up_layout)
|
||||
up_db._read()
|
||||
down_db.add(b, down_layout)
|
||||
@@ -86,7 +92,7 @@ def test_spec_installed_upstream(
|
||||
|
||||
# a known installed spec should say that it's installed
|
||||
with spack.repo.use_repositories(mock_custom_repository):
|
||||
spec = spack.spec.Spec("c").concretized()
|
||||
spec = spack.spec.Spec("pkg-c").concretized()
|
||||
assert not spec.installed
|
||||
assert not spec.installed_upstream
|
||||
|
||||
@@ -848,7 +854,7 @@ def test_query_virtual_spec(database):
|
||||
|
||||
def test_failed_spec_path_error(database):
|
||||
"""Ensure spec not concrete check is covered."""
|
||||
s = spack.spec.Spec("a")
|
||||
s = spack.spec.Spec("pkg-a")
|
||||
with pytest.raises(AssertionError, match="concrete spec required"):
|
||||
spack.store.STORE.failure_tracker.mark(s)
|
||||
|
||||
@@ -863,14 +869,14 @@ def _is(self, spec):
|
||||
# Pretend the spec has been failure locked
|
||||
monkeypatch.setattr(spack.database.FailureTracker, "lock_taken", _is)
|
||||
|
||||
s = spack.spec.Spec("a").concretized()
|
||||
s = spack.spec.Spec("pkg-a").concretized()
|
||||
spack.store.STORE.failure_tracker.clear(s)
|
||||
out = capfd.readouterr()[0]
|
||||
assert "Retaining failure marking" in out
|
||||
|
||||
|
||||
@pytest.mark.db
|
||||
def test_clear_failure_forced(default_mock_concretization, mutable_database, monkeypatch, capfd):
|
||||
def test_clear_failure_forced(mutable_database, monkeypatch, capfd):
|
||||
"""Add test coverage for clear_failure operation when force."""
|
||||
|
||||
def _is(self, spec):
|
||||
@@ -881,7 +887,7 @@ def _is(self, spec):
|
||||
# Ensure raise OSError when try to remove the non-existent marking
|
||||
monkeypatch.setattr(spack.database.FailureTracker, "persistent_mark", _is)
|
||||
|
||||
s = default_mock_concretization("a")
|
||||
s = spack.spec.Spec("pkg-a").concretized()
|
||||
spack.store.STORE.failure_tracker.clear(s, force=True)
|
||||
out = capfd.readouterr()[1]
|
||||
assert "Removing failure marking despite lock" in out
|
||||
@@ -889,30 +895,30 @@ def _is(self, spec):
|
||||
|
||||
|
||||
@pytest.mark.db
|
||||
def test_mark_failed(default_mock_concretization, mutable_database, monkeypatch, tmpdir, capsys):
|
||||
def test_mark_failed(mutable_database, monkeypatch, tmpdir, capsys):
|
||||
"""Add coverage to mark_failed."""
|
||||
|
||||
def _raise_exc(lock):
|
||||
raise lk.LockTimeoutError("write", "/mock-lock", 1.234, 10)
|
||||
|
||||
# Ensure attempt to acquire write lock on the mark raises the exception
|
||||
monkeypatch.setattr(lk.Lock, "acquire_write", _raise_exc)
|
||||
|
||||
with tmpdir.as_cwd():
|
||||
s = default_mock_concretization("a")
|
||||
spack.store.STORE.failure_tracker.mark(s)
|
||||
s = spack.spec.Spec("pkg-a").concretized()
|
||||
|
||||
# Ensure attempt to acquire write lock on the mark raises the exception
|
||||
monkeypatch.setattr(lk.Lock, "acquire_write", _raise_exc)
|
||||
|
||||
spack.store.STORE.failure_tracker.mark(s)
|
||||
out = str(capsys.readouterr()[1])
|
||||
assert "Unable to mark a as failed" in out
|
||||
assert "Unable to mark pkg-a as failed" in out
|
||||
|
||||
spack.store.STORE.failure_tracker.clear_all()
|
||||
|
||||
|
||||
@pytest.mark.db
|
||||
def test_prefix_failed(default_mock_concretization, mutable_database, monkeypatch):
|
||||
def test_prefix_failed(mutable_database, monkeypatch):
|
||||
"""Add coverage to failed operation."""
|
||||
|
||||
s = default_mock_concretization("a")
|
||||
s = spack.spec.Spec("pkg-a").concretized()
|
||||
|
||||
# Confirm the spec is not already marked as failed
|
||||
assert not spack.store.STORE.failure_tracker.has_failed(s)
|
||||
@@ -930,13 +936,13 @@ def test_prefix_failed(default_mock_concretization, mutable_database, monkeypatc
|
||||
assert spack.store.STORE.failure_tracker.has_failed(s)
|
||||
|
||||
|
||||
def test_prefix_write_lock_error(default_mock_concretization, mutable_database, monkeypatch):
|
||||
def test_prefix_write_lock_error(mutable_database, monkeypatch):
|
||||
"""Cover the prefix write lock exception."""
|
||||
|
||||
def _raise(db, spec):
|
||||
raise lk.LockError("Mock lock error")
|
||||
|
||||
s = default_mock_concretization("a")
|
||||
s = spack.spec.Spec("pkg-a").concretized()
|
||||
|
||||
# Ensure subsequent lock operations fail
|
||||
monkeypatch.setattr(lk.Lock, "acquire_write", _raise)
|
||||
@@ -1112,7 +1118,7 @@ def test_database_read_works_with_trailing_data(tmp_path, default_mock_concretiz
|
||||
# Populate a database
|
||||
root = str(tmp_path)
|
||||
db = spack.database.Database(root)
|
||||
spec = default_mock_concretization("a")
|
||||
spec = default_mock_concretization("pkg-a")
|
||||
db.add(spec, directory_layout=None)
|
||||
specs_in_db = db.query_local()
|
||||
assert spec in specs_in_db
|
||||
|
@@ -31,7 +31,7 @@ def test_true_directives_exist(mock_packages):
|
||||
|
||||
assert cls.dependencies
|
||||
assert "extendee" in cls.dependencies[spack.spec.Spec()]
|
||||
assert "b" in cls.dependencies[spack.spec.Spec()]
|
||||
assert "pkg-b" in cls.dependencies[spack.spec.Spec()]
|
||||
|
||||
assert cls.resources
|
||||
assert spack.spec.Spec() in cls.resources
|
||||
@@ -44,7 +44,7 @@ def test_constraints_from_context(mock_packages):
|
||||
pkg_cls = spack.repo.PATH.get_pkg_class("with-constraint-met")
|
||||
|
||||
assert pkg_cls.dependencies
|
||||
assert "b" in pkg_cls.dependencies[spack.spec.Spec("@1.0")]
|
||||
assert "pkg-b" in pkg_cls.dependencies[spack.spec.Spec("@1.0")]
|
||||
|
||||
assert pkg_cls.conflicts
|
||||
assert (spack.spec.Spec("%gcc"), None) in pkg_cls.conflicts[spack.spec.Spec("+foo@1.0")]
|
||||
@@ -55,7 +55,7 @@ def test_constraints_from_context_are_merged(mock_packages):
|
||||
pkg_cls = spack.repo.PATH.get_pkg_class("with-constraint-met")
|
||||
|
||||
assert pkg_cls.dependencies
|
||||
assert "c" in pkg_cls.dependencies[spack.spec.Spec("@0.14:15 ^b@3.8:4.0")]
|
||||
assert "pkg-c" in pkg_cls.dependencies[spack.spec.Spec("@0.14:15 ^pkg-b@3.8:4.0")]
|
||||
|
||||
|
||||
@pytest.mark.regression("27754")
|
||||
@@ -69,9 +69,9 @@ def test_extends_spec(config, mock_packages):
|
||||
|
||||
@pytest.mark.regression("34368")
|
||||
def test_error_on_anonymous_dependency(config, mock_packages):
|
||||
pkg = spack.repo.PATH.get_pkg_class("a")
|
||||
pkg = spack.repo.PATH.get_pkg_class("pkg-a")
|
||||
with pytest.raises(spack.directives.DependencyError):
|
||||
spack.directives._depends_on(pkg, "@4.5")
|
||||
spack.directives._depends_on(pkg, spack.spec.Spec("@4.5"))
|
||||
|
||||
|
||||
@pytest.mark.regression("34879")
|
||||
|
@@ -96,7 +96,7 @@ def test_env_change_spec(tmp_path, mock_packages, config):
|
||||
"""
|
||||
|
||||
|
||||
def test_env_change_spec_in_definition(tmp_path, mock_packages, config, mutable_mock_env_path):
|
||||
def test_env_change_spec_in_definition(tmp_path, mock_packages, mutable_mock_env_path):
|
||||
manifest_file = tmp_path / ev.manifest_name
|
||||
manifest_file.write_text(_test_matrix_yaml)
|
||||
e = ev.create("test", manifest_file)
|
||||
@@ -118,9 +118,7 @@ def test_env_change_spec_in_definition(tmp_path, mock_packages, config, mutable_
|
||||
assert not any(x.intersects("mpileaks@2.1%gcc") for x in e.user_specs)
|
||||
|
||||
|
||||
def test_env_change_spec_in_matrix_raises_error(
|
||||
tmp_path, mock_packages, config, mutable_mock_env_path
|
||||
):
|
||||
def test_env_change_spec_in_matrix_raises_error(tmp_path, mock_packages, mutable_mock_env_path):
|
||||
manifest_file = tmp_path / ev.manifest_name
|
||||
manifest_file.write_text(_test_matrix_yaml)
|
||||
e = ev.create("test", manifest_file)
|
||||
@@ -255,7 +253,7 @@ def test_update_default_view(init_view, update_value, tmp_path, mock_packages, c
|
||||
if isinstance(init_view, str) and update_value is True:
|
||||
expected_value = init_view
|
||||
|
||||
assert env.manifest.pristine_yaml_content["spack"]["view"] == expected_value
|
||||
assert env.manifest.yaml_content["spack"]["view"] == expected_value
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@@ -383,10 +381,10 @@ def test_can_add_specs_to_environment_without_specs_attribute(tmp_path, mock_pac
|
||||
"""
|
||||
)
|
||||
env = ev.Environment(tmp_path)
|
||||
env.add("a")
|
||||
env.add("pkg-a")
|
||||
|
||||
assert len(env.user_specs) == 1
|
||||
assert env.manifest.pristine_yaml_content["spack"]["specs"] == ["a"]
|
||||
assert env.manifest.yaml_content["spack"]["specs"] == ["pkg-a"]
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@@ -584,7 +582,7 @@ def test_conflicts_with_packages_that_are_not_dependencies(
|
||||
spack:
|
||||
specs:
|
||||
- {spec_str}
|
||||
- b
|
||||
- pkg-b
|
||||
concretizer:
|
||||
unify: true
|
||||
"""
|
||||
@@ -712,7 +710,7 @@ def test_variant_propagation_with_unify_false(tmp_path, mock_packages, config):
|
||||
spack:
|
||||
specs:
|
||||
- parent-foo ++foo
|
||||
- c
|
||||
- pkg-c
|
||||
concretizer:
|
||||
unify: false
|
||||
"""
|
||||
@@ -797,10 +795,10 @@ def test_deconcretize_then_concretize_does_not_error(mutable_mock_env_path, mock
|
||||
"""spack:
|
||||
specs:
|
||||
# These two specs concretize to the same hash
|
||||
- c
|
||||
- c@1.0
|
||||
- pkg-c
|
||||
- pkg-c@1.0
|
||||
# Spec used to trigger the bug
|
||||
- a
|
||||
- pkg-a
|
||||
concretizer:
|
||||
unify: true
|
||||
"""
|
||||
@@ -808,10 +806,10 @@ def test_deconcretize_then_concretize_does_not_error(mutable_mock_env_path, mock
|
||||
e = ev.Environment(mutable_mock_env_path)
|
||||
with e:
|
||||
e.concretize()
|
||||
e.deconcretize(spack.spec.Spec("a"), concrete=False)
|
||||
e.deconcretize(spack.spec.Spec("pkg-a"), concrete=False)
|
||||
e.concretize()
|
||||
assert len(e.concrete_roots()) == 3
|
||||
all_root_hashes = set(x.dag_hash() for x in e.concrete_roots())
|
||||
all_root_hashes = {x.dag_hash() for x in e.concrete_roots()}
|
||||
assert len(all_root_hashes) == 2
|
||||
|
||||
|
||||
@@ -843,3 +841,28 @@ def test_root_version_weights_for_old_versions(mutable_mock_env_path, mock_packa
|
||||
|
||||
assert bowtie.satisfies("@=1.3.0")
|
||||
assert gcc.satisfies("@=1.0")
|
||||
|
||||
|
||||
def test_env_view_on_empty_dir_is_fine(tmp_path, config, mock_packages, temporary_store):
|
||||
"""Tests that creating a view pointing to an empty dir is not an error."""
|
||||
view_dir = tmp_path / "view"
|
||||
view_dir.mkdir()
|
||||
env = ev.create_in_dir(tmp_path, with_view="view")
|
||||
env.add("mpileaks")
|
||||
env.concretize()
|
||||
env.install_all(fake=True)
|
||||
env.regenerate_views()
|
||||
assert view_dir.is_symlink()
|
||||
|
||||
|
||||
def test_env_view_on_non_empty_dir_errors(tmp_path, config, mock_packages, temporary_store):
|
||||
"""Tests that creating a view pointing to a non-empty dir errors."""
|
||||
view_dir = tmp_path / "view"
|
||||
view_dir.mkdir()
|
||||
(view_dir / "file").write_text("")
|
||||
env = ev.create_in_dir(tmp_path, with_view="view")
|
||||
env.add("mpileaks")
|
||||
env.concretize()
|
||||
env.install_all(fake=True)
|
||||
with pytest.raises(ev.SpackEnvironmentError, match="because it is a non-empty dir"):
|
||||
env.regenerate_views()
|
||||
|
@@ -99,7 +99,7 @@ def test_hms(sec, result):
|
||||
|
||||
def test_get_dependent_ids(install_mockery, mock_packages):
|
||||
# Concretize the parent package, which handle dependency too
|
||||
spec = spack.spec.Spec("a")
|
||||
spec = spack.spec.Spec("pkg-a")
|
||||
spec.concretize()
|
||||
assert spec.concrete
|
||||
|
||||
@@ -190,11 +190,11 @@ def _spec(spec, unsigned=False, mirrors_for_spec=None):
|
||||
# Skip database updates
|
||||
monkeypatch.setattr(spack.database.Database, "add", _noop)
|
||||
|
||||
spec = spack.spec.Spec("a").concretized()
|
||||
spec = spack.spec.Spec("pkg-a").concretized()
|
||||
assert inst._process_binary_cache_tarball(spec.package, explicit=False, unsigned=False)
|
||||
|
||||
out = capfd.readouterr()[0]
|
||||
assert "Extracting a" in out
|
||||
assert "Extracting pkg-a" in out
|
||||
assert "from binary cache" in out
|
||||
|
||||
|
||||
@@ -243,7 +243,7 @@ def test_installer_prune_built_build_deps(install_mockery, monkeypatch, tmpdir):
|
||||
|
||||
@property
|
||||
def _mock_installed(self):
|
||||
return self.name in ["c"]
|
||||
return self.name == "pkg-c"
|
||||
|
||||
# Mock the installed property to say that (b) is installed
|
||||
monkeypatch.setattr(spack.spec.Spec, "installed", _mock_installed)
|
||||
@@ -251,23 +251,24 @@ def _mock_installed(self):
|
||||
# Create mock repository with packages (a), (b), (c), (d), and (e)
|
||||
builder = spack.repo.MockRepositoryBuilder(tmpdir.mkdir("mock-repo"))
|
||||
|
||||
builder.add_package("a", dependencies=[("b", "build", None), ("c", "build", None)])
|
||||
builder.add_package("b", dependencies=[("d", "build", None)])
|
||||
builder.add_package("pkg-a", dependencies=[("pkg-b", "build", None), ("pkg-c", "build", None)])
|
||||
builder.add_package("pkg-b", dependencies=[("pkg-d", "build", None)])
|
||||
builder.add_package(
|
||||
"c", dependencies=[("d", "build", None), ("e", "all", None), ("f", "build", None)]
|
||||
"pkg-c",
|
||||
dependencies=[("pkg-d", "build", None), ("pkg-e", "all", None), ("pkg-f", "build", None)],
|
||||
)
|
||||
builder.add_package("d")
|
||||
builder.add_package("e")
|
||||
builder.add_package("f")
|
||||
builder.add_package("pkg-d")
|
||||
builder.add_package("pkg-e")
|
||||
builder.add_package("pkg-f")
|
||||
|
||||
with spack.repo.use_repositories(builder.root):
|
||||
installer = create_installer(["a"])
|
||||
installer = create_installer(["pkg-a"])
|
||||
|
||||
installer._init_queue()
|
||||
|
||||
# Assert that (c) is not in the build_pq
|
||||
result = set([task.pkg_id[0] for _, task in installer.build_pq])
|
||||
expected = set(["a", "b", "c", "d", "e"])
|
||||
result = {task.pkg_id[:5] for _, task in installer.build_pq}
|
||||
expected = {"pkg-a", "pkg-b", "pkg-c", "pkg-d", "pkg-e"}
|
||||
assert result == expected
|
||||
|
||||
|
||||
@@ -379,8 +380,7 @@ def test_ensure_locked_have(install_mockery, tmpdir, capsys):
|
||||
|
||||
@pytest.mark.parametrize("lock_type,reads,writes", [("read", 1, 0), ("write", 0, 1)])
|
||||
def test_ensure_locked_new_lock(install_mockery, tmpdir, lock_type, reads, writes):
|
||||
pkg_id = "a"
|
||||
installer = create_installer([pkg_id], {})
|
||||
installer = create_installer(["pkg-a"], {})
|
||||
spec = installer.build_requests[0].pkg.spec
|
||||
with tmpdir.as_cwd():
|
||||
ltype, lock = installer._ensure_locked(lock_type, spec.package)
|
||||
@@ -398,8 +398,7 @@ def _pl(db, spec, timeout):
|
||||
lock.default_timeout = 1e-9 if timeout is None else None
|
||||
return lock
|
||||
|
||||
pkg_id = "a"
|
||||
installer = create_installer([pkg_id], {})
|
||||
installer = create_installer(["pkg-a"], {})
|
||||
spec = installer.build_requests[0].pkg.spec
|
||||
|
||||
monkeypatch.setattr(spack.database.SpecLocker, "lock", _pl)
|
||||
@@ -453,7 +452,7 @@ def test_packages_needed_to_bootstrap_compiler_packages(install_mockery, monkeyp
|
||||
spec.concretize()
|
||||
|
||||
def _conc_spec(compiler):
|
||||
return spack.spec.Spec("a").concretized()
|
||||
return spack.spec.Spec("pkg-a").concretized()
|
||||
|
||||
# Ensure we can get past functions that are precluding obtaining
|
||||
# packages.
|
||||
@@ -561,7 +560,7 @@ def test_clear_failures_success(tmpdir):
|
||||
"""Test the clear_failures happy path."""
|
||||
failures = spack.database.FailureTracker(str(tmpdir), default_timeout=0.1)
|
||||
|
||||
spec = spack.spec.Spec("a")
|
||||
spec = spack.spec.Spec("pkg-a")
|
||||
spec._mark_concrete()
|
||||
|
||||
# Set up a test prefix failure lock
|
||||
@@ -587,7 +586,7 @@ def test_clear_failures_success(tmpdir):
|
||||
def test_clear_failures_errs(tmpdir, capsys):
|
||||
"""Test the clear_failures exception paths."""
|
||||
failures = spack.database.FailureTracker(str(tmpdir), default_timeout=0.1)
|
||||
spec = spack.spec.Spec("a")
|
||||
spec = spack.spec.Spec("pkg-a")
|
||||
spec._mark_concrete()
|
||||
failures.mark(spec)
|
||||
|
||||
@@ -649,11 +648,11 @@ def test_check_deps_status_install_failure(install_mockery):
|
||||
"""Tests that checking the dependency status on a request to install
|
||||
'a' fails, if we mark the dependency as failed.
|
||||
"""
|
||||
s = spack.spec.Spec("a").concretized()
|
||||
s = spack.spec.Spec("pkg-a").concretized()
|
||||
for dep in s.traverse(root=False):
|
||||
spack.store.STORE.failure_tracker.mark(dep)
|
||||
|
||||
installer = create_installer(["a"], {})
|
||||
installer = create_installer(["pkg-a"], {})
|
||||
request = installer.build_requests[0]
|
||||
|
||||
with pytest.raises(inst.InstallError, match="install failure"):
|
||||
@@ -661,7 +660,7 @@ def test_check_deps_status_install_failure(install_mockery):
|
||||
|
||||
|
||||
def test_check_deps_status_write_locked(install_mockery, monkeypatch):
|
||||
installer = create_installer(["a"], {})
|
||||
installer = create_installer(["pkg-a"], {})
|
||||
request = installer.build_requests[0]
|
||||
|
||||
# Ensure the lock is not acquired
|
||||
@@ -672,7 +671,7 @@ def test_check_deps_status_write_locked(install_mockery, monkeypatch):
|
||||
|
||||
|
||||
def test_check_deps_status_external(install_mockery, monkeypatch):
|
||||
installer = create_installer(["a"], {})
|
||||
installer = create_installer(["pkg-a"], {})
|
||||
request = installer.build_requests[0]
|
||||
|
||||
# Mock the dependencies as external so assumed to be installed
|
||||
@@ -684,7 +683,7 @@ def test_check_deps_status_external(install_mockery, monkeypatch):
|
||||
|
||||
|
||||
def test_check_deps_status_upstream(install_mockery, monkeypatch):
|
||||
installer = create_installer(["a"], {})
|
||||
installer = create_installer(["pkg-a"], {})
|
||||
request = installer.build_requests[0]
|
||||
|
||||
# Mock the known dependencies as installed upstream
|
||||
@@ -756,7 +755,7 @@ def test_install_task_add_compiler(install_mockery, monkeypatch, capfd):
|
||||
def _add(_compilers):
|
||||
tty.msg(config_msg)
|
||||
|
||||
installer = create_installer(["a"], {})
|
||||
installer = create_installer(["pkg-a"], {})
|
||||
task = create_build_task(installer.build_requests[0].pkg)
|
||||
task.compiler = True
|
||||
|
||||
@@ -792,7 +791,7 @@ def test_release_lock_write_n_exception(install_mockery, tmpdir, capsys):
|
||||
@pytest.mark.parametrize("installed", [True, False])
|
||||
def test_push_task_skip_processed(install_mockery, installed):
|
||||
"""Test to ensure skip re-queueing a processed package."""
|
||||
installer = create_installer(["a"], {})
|
||||
installer = create_installer(["pkg-a"], {})
|
||||
assert len(list(installer.build_tasks)) == 0
|
||||
|
||||
# Mark the package as installed OR failed
|
||||
@@ -809,7 +808,7 @@ def test_push_task_skip_processed(install_mockery, installed):
|
||||
|
||||
def test_requeue_task(install_mockery, capfd):
|
||||
"""Test to ensure cover _requeue_task."""
|
||||
installer = create_installer(["a"], {})
|
||||
installer = create_installer(["pkg-a"], {})
|
||||
task = create_build_task(installer.build_requests[0].pkg)
|
||||
|
||||
# temporarily set tty debug messages on so we can test output
|
||||
@@ -826,7 +825,7 @@ def test_requeue_task(install_mockery, capfd):
|
||||
assert qtask.attempts == task.attempts + 1
|
||||
|
||||
out = capfd.readouterr()[1]
|
||||
assert "Installing a" in out
|
||||
assert "Installing pkg-a" in out
|
||||
assert " in progress by another process" in out
|
||||
|
||||
|
||||
@@ -839,16 +838,16 @@ def _mktask(pkg):
|
||||
def _rmtask(installer, pkg_id):
|
||||
raise RuntimeError("Raise an exception to test except path")
|
||||
|
||||
installer = create_installer(["a"], {})
|
||||
installer = create_installer(["pkg-a"], {})
|
||||
spec = installer.build_requests[0].pkg.spec
|
||||
|
||||
# Cover task removal happy path
|
||||
installer.build_tasks["a"] = _mktask(spec.package)
|
||||
installer.build_tasks["pkg-a"] = _mktask(spec.package)
|
||||
installer._cleanup_all_tasks()
|
||||
assert len(installer.build_tasks) == 0
|
||||
|
||||
# Cover task removal exception path
|
||||
installer.build_tasks["a"] = _mktask(spec.package)
|
||||
installer.build_tasks["pkg-a"] = _mktask(spec.package)
|
||||
monkeypatch.setattr(inst.PackageInstaller, "_remove_task", _rmtask)
|
||||
installer._cleanup_all_tasks()
|
||||
assert len(installer.build_tasks) == 1
|
||||
@@ -938,7 +937,7 @@ def test_install_uninstalled_deps(install_mockery, monkeypatch, capsys):
|
||||
|
||||
def test_install_failed(install_mockery, monkeypatch, capsys):
|
||||
"""Test install with failed install."""
|
||||
installer = create_installer(["b"], {})
|
||||
installer = create_installer(["pkg-b"], {})
|
||||
|
||||
# Make sure the package is identified as failed
|
||||
monkeypatch.setattr(spack.database.FailureTracker, "has_failed", _true)
|
||||
@@ -953,7 +952,7 @@ def test_install_failed(install_mockery, monkeypatch, capsys):
|
||||
|
||||
def test_install_failed_not_fast(install_mockery, monkeypatch, capsys):
|
||||
"""Test install with failed install."""
|
||||
installer = create_installer(["a"], {"fail_fast": False})
|
||||
installer = create_installer(["pkg-a"], {"fail_fast": False})
|
||||
|
||||
# Make sure the package is identified as failed
|
||||
monkeypatch.setattr(spack.database.FailureTracker, "has_failed", _true)
|
||||
@@ -963,12 +962,12 @@ def test_install_failed_not_fast(install_mockery, monkeypatch, capsys):
|
||||
|
||||
out = str(capsys.readouterr())
|
||||
assert "failed to install" in out
|
||||
assert "Skipping build of a" in out
|
||||
assert "Skipping build of pkg-a" in out
|
||||
|
||||
|
||||
def test_install_fail_on_interrupt(install_mockery, monkeypatch):
|
||||
"""Test ctrl-c interrupted install."""
|
||||
spec_name = "a"
|
||||
spec_name = "pkg-a"
|
||||
err_msg = "mock keyboard interrupt for {0}".format(spec_name)
|
||||
|
||||
def _interrupt(installer, task, install_status, **kwargs):
|
||||
@@ -985,13 +984,13 @@ def _interrupt(installer, task, install_status, **kwargs):
|
||||
with pytest.raises(KeyboardInterrupt, match=err_msg):
|
||||
installer.install()
|
||||
|
||||
assert "b" in installer.installed # ensure dependency of a is 'installed'
|
||||
assert "pkg-b" in installer.installed # ensure dependency of pkg-a is 'installed'
|
||||
assert spec_name not in installer.installed
|
||||
|
||||
|
||||
def test_install_fail_single(install_mockery, monkeypatch):
|
||||
"""Test expected results for failure of single package."""
|
||||
spec_name = "a"
|
||||
spec_name = "pkg-a"
|
||||
err_msg = "mock internal package build error for {0}".format(spec_name)
|
||||
|
||||
class MyBuildException(Exception):
|
||||
@@ -1011,13 +1010,13 @@ def _install(installer, task, install_status, **kwargs):
|
||||
with pytest.raises(MyBuildException, match=err_msg):
|
||||
installer.install()
|
||||
|
||||
assert "b" in installer.installed # ensure dependency of a is 'installed'
|
||||
assert "pkg-b" in installer.installed # ensure dependency of a is 'installed'
|
||||
assert spec_name not in installer.installed
|
||||
|
||||
|
||||
def test_install_fail_multi(install_mockery, monkeypatch):
|
||||
"""Test expected results for failure of multiple packages."""
|
||||
spec_name = "c"
|
||||
spec_name = "pkg-c"
|
||||
err_msg = "mock internal package build error"
|
||||
|
||||
class MyBuildException(Exception):
|
||||
@@ -1029,7 +1028,7 @@ def _install(installer, task, install_status, **kwargs):
|
||||
else:
|
||||
installer.installed.add(task.pkg.name)
|
||||
|
||||
installer = create_installer([spec_name, "a"], {})
|
||||
installer = create_installer([spec_name, "pkg-a"], {})
|
||||
|
||||
# Raise a KeyboardInterrupt error to trigger early termination
|
||||
monkeypatch.setattr(inst.PackageInstaller, "_install_task", _install)
|
||||
@@ -1037,13 +1036,13 @@ def _install(installer, task, install_status, **kwargs):
|
||||
with pytest.raises(inst.InstallError, match="Installation request failed"):
|
||||
installer.install()
|
||||
|
||||
assert "a" in installer.installed # ensure the the second spec installed
|
||||
assert "pkg-a" in installer.installed # ensure the the second spec installed
|
||||
assert spec_name not in installer.installed
|
||||
|
||||
|
||||
def test_install_fail_fast_on_detect(install_mockery, monkeypatch, capsys):
|
||||
"""Test fail_fast install when an install failure is detected."""
|
||||
b, c = spack.spec.Spec("b").concretized(), spack.spec.Spec("c").concretized()
|
||||
b, c = spack.spec.Spec("pkg-b").concretized(), spack.spec.Spec("pkg-c").concretized()
|
||||
b_id, c_id = inst.package_id(b), inst.package_id(c)
|
||||
|
||||
installer = create_installer([b, c], {"fail_fast": True})
|
||||
@@ -1056,7 +1055,7 @@ def test_install_fail_fast_on_detect(install_mockery, monkeypatch, capsys):
|
||||
installer.install()
|
||||
|
||||
assert b_id in installer.failed, "Expected b to be marked as failed"
|
||||
assert c_id not in installer.failed, "Expected no attempt to install c"
|
||||
assert c_id not in installer.failed, "Expected no attempt to install pkg-c"
|
||||
assert f"{b_id} failed to install" in capsys.readouterr().err
|
||||
|
||||
|
||||
@@ -1070,7 +1069,7 @@ def _test_install_fail_fast_on_except_patch(installer, **kwargs):
|
||||
@pytest.mark.disable_clean_stage_check
|
||||
def test_install_fail_fast_on_except(install_mockery, monkeypatch, capsys):
|
||||
"""Test fail_fast install when an install failure results from an error."""
|
||||
installer = create_installer(["a"], {"fail_fast": True})
|
||||
installer = create_installer(["pkg-a"], {"fail_fast": True})
|
||||
|
||||
# Raise a non-KeyboardInterrupt exception to trigger fast failure.
|
||||
#
|
||||
@@ -1084,7 +1083,7 @@ def test_install_fail_fast_on_except(install_mockery, monkeypatch, capsys):
|
||||
installer.install()
|
||||
|
||||
out = str(capsys.readouterr())
|
||||
assert "Skipping build of a" in out
|
||||
assert "Skipping build of pkg-a" in out
|
||||
|
||||
|
||||
def test_install_lock_failures(install_mockery, monkeypatch, capfd):
|
||||
@@ -1093,7 +1092,7 @@ def test_install_lock_failures(install_mockery, monkeypatch, capfd):
|
||||
def _requeued(installer, task, install_status):
|
||||
tty.msg("requeued {0}".format(task.pkg.spec.name))
|
||||
|
||||
installer = create_installer(["b"], {})
|
||||
installer = create_installer(["pkg-b"], {})
|
||||
|
||||
# Ensure never acquire a lock
|
||||
monkeypatch.setattr(inst.PackageInstaller, "_ensure_locked", _not_locked)
|
||||
@@ -1112,7 +1111,7 @@ def _requeued(installer, task, install_status):
|
||||
|
||||
def test_install_lock_installed_requeue(install_mockery, monkeypatch, capfd):
|
||||
"""Cover basic install handling for installed package."""
|
||||
b = spack.spec.Spec("b").concretized()
|
||||
b = spack.spec.Spec("pkg-b").concretized()
|
||||
b_pkg_id = inst.package_id(b)
|
||||
installer = create_installer([b])
|
||||
|
||||
@@ -1166,7 +1165,7 @@ def _requeued(installer, task, install_status):
|
||||
# Ensure don't continually requeue the task
|
||||
monkeypatch.setattr(inst.PackageInstaller, "_requeue_task", _requeued)
|
||||
|
||||
installer = create_installer(["b"], {})
|
||||
installer = create_installer(["pkg-b"], {})
|
||||
|
||||
with pytest.raises(inst.InstallError, match="request failed"):
|
||||
installer.install()
|
||||
@@ -1181,7 +1180,7 @@ def _requeued(installer, task, install_status):
|
||||
|
||||
def test_install_skip_patch(install_mockery, mock_fetch):
|
||||
"""Test the path skip_patch install path."""
|
||||
installer = create_installer(["b"], {"fake": False, "skip_patch": True})
|
||||
installer = create_installer(["pkg-b"], {"fake": False, "skip_patch": True})
|
||||
installer.install()
|
||||
assert inst.package_id(installer.build_requests[0].pkg.spec) in installer.installed
|
||||
|
||||
@@ -1202,7 +1201,7 @@ def test_overwrite_install_backup_success(temporary_store, config, mock_packages
|
||||
of the original prefix, and leave the original spec marked installed.
|
||||
"""
|
||||
# Get a build task. TODO: refactor this to avoid calling internal methods
|
||||
installer = create_installer(["b"])
|
||||
installer = create_installer(["pkg-b"])
|
||||
installer._init_queue()
|
||||
task = installer._pop_task()
|
||||
|
||||
@@ -1262,7 +1261,7 @@ def remove(self, spec):
|
||||
self.called = True
|
||||
|
||||
# Get a build task. TODO: refactor this to avoid calling internal methods
|
||||
installer = create_installer(["b"])
|
||||
installer = create_installer(["pkg-b"])
|
||||
installer._init_queue()
|
||||
task = installer._pop_task()
|
||||
|
||||
@@ -1290,8 +1289,8 @@ def test_term_status_line():
|
||||
# accept that. `with log_output(buf)` doesn't really work because it trims output
|
||||
# and we actually want to test for escape sequences etc.
|
||||
x = inst.TermStatusLine(enabled=True)
|
||||
x.add("a")
|
||||
x.add("b")
|
||||
x.add("pkg-a")
|
||||
x.add("pkg-b")
|
||||
x.clear()
|
||||
|
||||
|
||||
|
@@ -200,13 +200,13 @@ def test_invalid_json_mirror_collection(invalid_json, error_message):
|
||||
assert error_message in exc_msg
|
||||
|
||||
|
||||
def test_mirror_archive_paths_no_version(mock_packages, config, mock_archive):
|
||||
def test_mirror_archive_paths_no_version(mock_packages, mock_archive):
|
||||
spec = Spec("trivial-install-test-package@=nonexistingversion").concretized()
|
||||
fetcher = spack.fetch_strategy.URLFetchStrategy(mock_archive.url)
|
||||
spack.mirror.mirror_archive_paths(fetcher, "per-package-ref", spec)
|
||||
|
||||
|
||||
def test_mirror_with_url_patches(mock_packages, config, monkeypatch):
|
||||
def test_mirror_with_url_patches(mock_packages, monkeypatch):
|
||||
spec = Spec("patch-several-dependencies")
|
||||
spec.concretize()
|
||||
|
||||
@@ -289,8 +289,8 @@ def test_mirror_cache_symlinks(tmpdir):
|
||||
@pytest.mark.parametrize(
|
||||
"specs,expected_specs",
|
||||
[
|
||||
(["a"], ["a@=1.0", "a@=2.0"]),
|
||||
(["a", "brillig"], ["a@=1.0", "a@=2.0", "brillig@=1.0.0", "brillig@=2.0.0"]),
|
||||
(["pkg-a"], ["pkg-a@=1.0", "pkg-a@=2.0"]),
|
||||
(["pkg-a", "brillig"], ["pkg-a@=1.0", "pkg-a@=2.0", "brillig@=1.0.0", "brillig@=2.0.0"]),
|
||||
],
|
||||
)
|
||||
def test_get_all_versions(specs, expected_specs):
|
||||
|
@@ -48,7 +48,7 @@ def provider(request):
|
||||
return request.param
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("config", "mock_packages")
|
||||
@pytest.mark.usefixtures("mutable_config", "mock_packages")
|
||||
class TestLmod:
|
||||
@pytest.mark.regression("37788")
|
||||
@pytest.mark.parametrize("modules_config", ["core_compilers", "core_compilers_at_equal"])
|
||||
@@ -355,7 +355,6 @@ def test_override_template_in_modules_yaml(
|
||||
content = modulefile_content(f"mpileaks target={host_architecture_str}")
|
||||
assert "Override even better!" in content
|
||||
|
||||
@pytest.mark.usefixtures("config")
|
||||
def test_external_configure_args(self, factory):
|
||||
# If this package is detected as an external, its configure option line
|
||||
# in the module file starts with 'unknown'
|
||||
|
@@ -26,7 +26,7 @@
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("config", "mock_packages", "mock_module_filename")
|
||||
@pytest.mark.usefixtures("mutable_config", "mock_packages", "mock_module_filename")
|
||||
class TestTcl:
|
||||
def test_simple_case(self, modulefile_content, module_configuration):
|
||||
"""Tests the generation of a simple Tcl module file."""
|
||||
@@ -439,19 +439,19 @@ def test_extend_context(self, modulefile_content, module_configuration):
|
||||
|
||||
@pytest.mark.regression("4400")
|
||||
@pytest.mark.db
|
||||
def test_hide_implicits_no_arg(self, module_configuration, database):
|
||||
def test_hide_implicits_no_arg(self, module_configuration, mutable_database):
|
||||
module_configuration("exclude_implicits")
|
||||
|
||||
# mpileaks has been installed explicitly when setting up
|
||||
# the tests database
|
||||
mpileaks_specs = database.query("mpileaks")
|
||||
mpileaks_specs = mutable_database.query("mpileaks")
|
||||
for item in mpileaks_specs:
|
||||
writer = writer_cls(item, "default")
|
||||
assert not writer.conf.excluded
|
||||
|
||||
# callpath is a dependency of mpileaks, and has been pulled
|
||||
# in implicitly
|
||||
callpath_specs = database.query("callpath")
|
||||
callpath_specs = mutable_database.query("callpath")
|
||||
for item in callpath_specs:
|
||||
writer = writer_cls(item, "default")
|
||||
assert writer.conf.excluded
|
||||
@@ -473,8 +473,7 @@ def test_hide_implicits_with_arg(self, module_configuration):
|
||||
assert writer.conf.excluded
|
||||
|
||||
@pytest.mark.regression("9624")
|
||||
@pytest.mark.db
|
||||
def test_autoload_with_constraints(self, modulefile_content, module_configuration, database):
|
||||
def test_autoload_with_constraints(self, modulefile_content, module_configuration):
|
||||
"""Tests the automatic loading of direct dependencies."""
|
||||
|
||||
module_configuration("autoload_with_constraints")
|
||||
|
@@ -13,28 +13,44 @@
|
||||
# Normalize simple conditionals
|
||||
("optional-dep-test", {"optional-dep-test": None}),
|
||||
("optional-dep-test~a", {"optional-dep-test~a": None}),
|
||||
("optional-dep-test+a", {"optional-dep-test+a": {"a": None}}),
|
||||
("optional-dep-test a=true", {"optional-dep-test a=true": {"a": None}}),
|
||||
("optional-dep-test a=true", {"optional-dep-test+a": {"a": None}}),
|
||||
("optional-dep-test@1.1", {"optional-dep-test@1.1": {"b": None}}),
|
||||
("optional-dep-test%intel", {"optional-dep-test%intel": {"c": None}}),
|
||||
("optional-dep-test%intel@64.1", {"optional-dep-test%intel@64.1": {"c": None, "d": None}}),
|
||||
("optional-dep-test+a", {"optional-dep-test+a": {"pkg-a": None}}),
|
||||
("optional-dep-test a=true", {"optional-dep-test a=true": {"pkg-a": None}}),
|
||||
("optional-dep-test a=true", {"optional-dep-test+a": {"pkg-a": None}}),
|
||||
("optional-dep-test@1.1", {"optional-dep-test@1.1": {"pkg-b": None}}),
|
||||
("optional-dep-test%intel", {"optional-dep-test%intel": {"pkg-c": None}}),
|
||||
(
|
||||
"optional-dep-test%intel@64.1",
|
||||
{"optional-dep-test%intel@64.1": {"pkg-c": None, "pkg-d": None}},
|
||||
),
|
||||
(
|
||||
"optional-dep-test%intel@64.1.2",
|
||||
{"optional-dep-test%intel@64.1.2": {"c": None, "d": None}},
|
||||
{"optional-dep-test%intel@64.1.2": {"pkg-c": None, "pkg-d": None}},
|
||||
),
|
||||
("optional-dep-test%clang@35", {"optional-dep-test%clang@35": {"e": None}}),
|
||||
("optional-dep-test%clang@35", {"optional-dep-test%clang@35": {"pkg-e": None}}),
|
||||
# Normalize multiple conditionals
|
||||
("optional-dep-test+a@1.1", {"optional-dep-test+a@1.1": {"a": None, "b": None}}),
|
||||
("optional-dep-test+a%intel", {"optional-dep-test+a%intel": {"a": None, "c": None}}),
|
||||
("optional-dep-test@1.1%intel", {"optional-dep-test@1.1%intel": {"b": None, "c": None}}),
|
||||
("optional-dep-test+a@1.1", {"optional-dep-test+a@1.1": {"pkg-a": None, "pkg-b": None}}),
|
||||
(
|
||||
"optional-dep-test+a%intel",
|
||||
{"optional-dep-test+a%intel": {"pkg-a": None, "pkg-c": None}},
|
||||
),
|
||||
(
|
||||
"optional-dep-test@1.1%intel",
|
||||
{"optional-dep-test@1.1%intel": {"pkg-b": None, "pkg-c": None}},
|
||||
),
|
||||
(
|
||||
"optional-dep-test@1.1%intel@64.1.2+a",
|
||||
{"optional-dep-test@1.1%intel@64.1.2+a": {"a": None, "b": None, "c": None, "d": None}},
|
||||
{
|
||||
"optional-dep-test@1.1%intel@64.1.2+a": {
|
||||
"pkg-a": None,
|
||||
"pkg-b": None,
|
||||
"pkg-c": None,
|
||||
"pkg-d": None,
|
||||
}
|
||||
},
|
||||
),
|
||||
(
|
||||
"optional-dep-test@1.1%clang@36.5+a",
|
||||
{"optional-dep-test@1.1%clang@36.5+a": {"b": None, "a": None, "e": None}},
|
||||
{"optional-dep-test@1.1%clang@36.5+a": {"pkg-b": None, "pkg-a": None, "pkg-e": None}},
|
||||
),
|
||||
# Chained MPI
|
||||
(
|
||||
@@ -44,7 +60,10 @@
|
||||
# Each of these dependencies comes from a conditional
|
||||
# dependency on another. This requires iterating to evaluate
|
||||
# the whole chain.
|
||||
("optional-dep-test+f", {"optional-dep-test+f": {"f": None, "g": None, "mpi": None}}),
|
||||
(
|
||||
"optional-dep-test+f",
|
||||
{"optional-dep-test+f": {"pkg-f": None, "pkg-g": None, "mpi": None}},
|
||||
),
|
||||
]
|
||||
)
|
||||
def spec_and_expected(request):
|
||||
@@ -63,12 +82,12 @@ def test_normalize(spec_and_expected, config, mock_packages):
|
||||
def test_default_variant(config, mock_packages):
|
||||
spec = Spec("optional-dep-test-3")
|
||||
spec.concretize()
|
||||
assert "a" in spec
|
||||
assert "pkg-a" in spec
|
||||
|
||||
spec = Spec("optional-dep-test-3~var")
|
||||
spec.concretize()
|
||||
assert "a" in spec
|
||||
assert "pkg-a" in spec
|
||||
|
||||
spec = Spec("optional-dep-test-3+var")
|
||||
spec.concretize()
|
||||
assert "b" in spec
|
||||
assert "pkg-b" in spec
|
||||
|
@@ -21,6 +21,7 @@
|
||||
import spack.install_test
|
||||
import spack.package_base
|
||||
import spack.repo
|
||||
import spack.spec
|
||||
from spack.build_systems.generic import Package
|
||||
from spack.installer import InstallError
|
||||
|
||||
@@ -142,19 +143,19 @@ def setup_install_test(source_paths, test_root):
|
||||
"spec,sources,extras,expect",
|
||||
[
|
||||
(
|
||||
"a",
|
||||
"pkg-a",
|
||||
["example/a.c"], # Source(s)
|
||||
["example/a.c"], # Extra test source
|
||||
["example/a.c"],
|
||||
), # Test install dir source(s)
|
||||
(
|
||||
"b",
|
||||
"pkg-b",
|
||||
["test/b.cpp", "test/b.hpp", "example/b.txt"], # Source(s)
|
||||
["test"], # Extra test source
|
||||
["test/b.cpp", "test/b.hpp"],
|
||||
), # Test install dir source
|
||||
(
|
||||
"c",
|
||||
"pkg-c",
|
||||
["examples/a.py", "examples/b.py", "examples/c.py", "tests/d.py"],
|
||||
["examples/b.py", "tests"],
|
||||
["examples/b.py", "tests/d.py"],
|
||||
@@ -202,7 +203,7 @@ def test_cache_extra_sources(install_mockery, spec, sources, extras, expect):
|
||||
|
||||
|
||||
def test_cache_extra_sources_fails(install_mockery):
|
||||
s = spack.spec.Spec("a").concretized()
|
||||
s = spack.spec.Spec("pkg-a").concretized()
|
||||
s.package.spec.concretize()
|
||||
|
||||
with pytest.raises(InstallError) as exc_info:
|
||||
@@ -226,7 +227,7 @@ class URLsPackage(spack.package.Package):
|
||||
url = "https://www.example.com/url-package-1.0.tgz"
|
||||
urls = ["https://www.example.com/archive"]
|
||||
|
||||
s = spack.spec.Spec("a")
|
||||
s = spack.spec.Spec("pkg-a")
|
||||
with pytest.raises(ValueError, match="defines both"):
|
||||
URLsPackage(s)
|
||||
|
||||
@@ -236,7 +237,7 @@ class LicensedPackage(spack.package.Package):
|
||||
extendees = None # currently a required attribute for is_extension()
|
||||
license_files = None
|
||||
|
||||
s = spack.spec.Spec("a")
|
||||
s = spack.spec.Spec("pkg-a")
|
||||
pkg = LicensedPackage(s)
|
||||
assert pkg.global_license_file is None
|
||||
|
||||
@@ -249,21 +250,21 @@ class BaseTestPackage(Package):
|
||||
|
||||
|
||||
def test_package_version_fails():
|
||||
s = spack.spec.Spec("a")
|
||||
s = spack.spec.Spec("pkg-a")
|
||||
pkg = BaseTestPackage(s)
|
||||
with pytest.raises(ValueError, match="does not have a concrete version"):
|
||||
pkg.version()
|
||||
|
||||
|
||||
def test_package_tester_fails():
|
||||
s = spack.spec.Spec("a")
|
||||
s = spack.spec.Spec("pkg-a")
|
||||
pkg = BaseTestPackage(s)
|
||||
with pytest.raises(ValueError, match="without concrete version"):
|
||||
pkg.tester()
|
||||
|
||||
|
||||
def test_package_fetcher_fails():
|
||||
s = spack.spec.Spec("a")
|
||||
s = spack.spec.Spec("pkg-a")
|
||||
pkg = BaseTestPackage(s)
|
||||
with pytest.raises(ValueError, match="without concrete version"):
|
||||
pkg.fetcher
|
||||
@@ -275,7 +276,7 @@ def compilers(compiler, arch_spec):
|
||||
|
||||
monkeypatch.setattr(spack.compilers, "compilers_for_spec", compilers)
|
||||
|
||||
s = spack.spec.Spec("a")
|
||||
s = spack.spec.Spec("pkg-a")
|
||||
pkg = BaseTestPackage(s)
|
||||
pkg.test_requires_compiler = True
|
||||
pkg.do_test()
|
||||
@@ -293,7 +294,7 @@ def compilers(compiler, arch_spec):
|
||||
],
|
||||
)
|
||||
def test_package_run_test_install(
|
||||
install_mockery_mutable_config, mock_fetch, capfd, msg, installed, purpose, expected
|
||||
install_mockery, mock_fetch, capfd, msg, installed, purpose, expected
|
||||
):
|
||||
"""Confirm expected outputs from run_test for installed/not installed exe."""
|
||||
s = spack.spec.Spec("trivial-smoke-test").concretized()
|
||||
@@ -314,9 +315,7 @@ def test_package_run_test_install(
|
||||
(False, 1, str(spack.install_test.TestStatus.FAILED)),
|
||||
],
|
||||
)
|
||||
def test_package_run_test_missing(
|
||||
install_mockery_mutable_config, mock_fetch, capfd, skip, failures, status
|
||||
):
|
||||
def test_package_run_test_missing(install_mockery, mock_fetch, capfd, skip, failures, status):
|
||||
"""Confirm expected results from run_test for missing exe when skip or not."""
|
||||
s = spack.spec.Spec("trivial-smoke-test").concretized()
|
||||
pkg = s.package
|
||||
@@ -328,7 +327,7 @@ def test_package_run_test_missing(
|
||||
|
||||
|
||||
# TODO (post-34236): Remove when remove deprecated run_test(), etc.
|
||||
def test_package_run_test_fail_fast(install_mockery_mutable_config, mock_fetch):
|
||||
def test_package_run_test_fail_fast(install_mockery, mock_fetch):
|
||||
"""Confirm expected exception when run_test with fail_fast enabled."""
|
||||
s = spack.spec.Spec("trivial-smoke-test").concretized()
|
||||
pkg = s.package
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user