Skip to content

Commit d049e60

Browse files
authored
Merge pull request #640 from materialsproject/uv-ci-test-lowest-highest-dep-resolution
Increase CI sensitivity by testing both lowest-direct and highest dependency resolution strategy
2 parents ac5e5fc + a503b9a commit d049e60

File tree

11 files changed

+58
-48
lines changed

11 files changed

+58
-48
lines changed

.github/workflows/testing.yml

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,20 @@ jobs:
3535
runs-on: ubuntu-latest
3636
strategy:
3737
matrix:
38-
python-version: ['3.10', '3.11', '3.12']
38+
version:
39+
- { python: "3.10", resolution: highest, extras: "tests,strict" }
40+
- { python: "3.12", resolution: lowest-direct, extras: "tests" }
41+
- { python: "3.12", resolution: highest, extras: tests }
42+
# python 3.12 CI failing due to maggma incompatible, see
43+
# https://github.com/materialsproject/jobflow/pull/640#issuecomment-2209055692
44+
# - { python: "3.12", resolution: lowest-direct, extras: tests }
3945

4046
steps:
4147
- uses: actions/checkout@v4
4248

4349
- uses: actions/setup-python@v5
4450
with:
45-
python-version: ${{ matrix.python-version }}
51+
python-version: ${{ matrix.version.python }}
4652
cache: pip
4753
cache-dependency-path: pyproject.toml
4854

@@ -52,7 +58,7 @@ jobs:
5258
- name: Install dependencies
5359
run: |
5460
pip install uv
55-
uv pip install .[strict,tests] --system
61+
uv pip install '.[${{ matrix.version.extras }}]' --system --resolution=${{ matrix.version.resolution }}
5662
5763
- name: Test
5864
run: pytest --cov=jobflow --cov-report=xml

.pre-commit-config.yaml

Lines changed: 6 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,25 @@
11
default_language_version:
22
python: python3
3-
exclude: "^src/atomate2/vasp/schemas/calc_types/"
3+
exclude: '^src/atomate2/vasp/schemas/calc_types/'
44
repos:
55
- repo: https://github.com/charliermarsh/ruff-pre-commit
6-
rev: v0.11.12
6+
rev: v0.13.0
77
hooks:
88
- id: ruff
99
args: [--fix]
1010
- id: ruff-format
1111
- repo: https://github.com/pre-commit/pre-commit-hooks
12-
rev: v5.0.0
12+
rev: v6.0.0
1313
hooks:
1414
- id: check-yaml
15-
- id: fix-encoding-pragma
16-
args: [--remove]
1715
- id: end-of-file-fixer
1816
- id: trailing-whitespace
1917
- repo: https://github.com/asottile/blacken-docs
20-
rev: 1.19.1
18+
rev: 1.20.0
2119
hooks:
2220
- id: blacken-docs
2321
additional_dependencies: [black]
2422
exclude: ^(README.md|paper/paper.md)$
25-
- repo: https://github.com/pycqa/flake8
26-
rev: 7.0.0
27-
hooks:
28-
- id: flake8
29-
entry: pflake8
30-
files: ^src/
31-
additional_dependencies:
32-
- pyproject-flake8
33-
- flake8-bugbear
34-
- flake8-typing-imports
35-
- flake8-docstrings
36-
- flake8-rst-docstrings
37-
- flake8-rst
3823
- repo: https://github.com/pre-commit/pygrep-hooks
3924
rev: v1.10.0
4025
hooks:
@@ -43,7 +28,7 @@ repos:
4328
- id: rst-directive-colons
4429
- id: rst-inline-touching-normal
4530
- repo: https://github.com/pre-commit/mirrors-mypy
46-
rev: v1.16.0
31+
rev: v1.18.1
4732
hooks:
4833
- id: mypy
4934
files: ^src/
@@ -58,6 +43,6 @@ repos:
5843
stages: [commit, commit-msg]
5944
args:
6045
- --ignore-words-list
61-
- "titel,statics,ba,nd,te,atomate"
46+
- 'titel,statics,ba,nd,te,atomate'
6247
- --check-filenames
6348
types_or: [python, rst, markdown]

pyproject.toml

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,13 @@ classifiers = [
2727
]
2828
requires-python = ">=3.10"
2929
dependencies = [
30-
"PyYAML",
31-
"maggma>=0.57.0",
30+
"PyYAML>=6.0.1",
31+
"maggma>=0.72.0",
3232
"monty>=2023.9.25",
33-
"networkx",
33+
"networkx>=3.2.1",
3434
"pydantic-settings>=2.0.3",
35-
"pydantic>=2.0.1",
36-
"pydash",
35+
"pydantic>=2.4",
36+
"pydash>=8.0.1",
3737
]
3838

3939
[project.optional-dependencies]
@@ -163,6 +163,7 @@ ignore = [
163163
"FBT001",
164164
"FBT002",
165165
"ISC001",
166+
"PLC0415", # import should be at the top-level of a file
166167
"PLR0911", # too-many-return-statements
167168
"PLR0912", # too-many-branches
168169
"PLR0913", # too-many-arguments
@@ -180,5 +181,6 @@ isort.known-first-party = ["jobflow"]
180181
# D: pydocstyle
181182
# PLR2004: magic-value-comparison
182183
# PT004: pytest-missing-fixture-name-underscore
184+
183185
"**/tests/*" = ["ANN", "ARG001", "D", "PLR2004", "PT004", "S101"]
184186
"docs/tutorials/*" = ["D", "PLR2004"]

tests/core/test_flow.py

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -115,12 +115,13 @@ def test_flow_of_jobs_init():
115115

116116
# test job given rather than outputs
117117
add_job = get_test_job()
118-
with pytest.warns(UserWarning):
118+
warn_msg = "Flow 'Flow' contains a Flow or Job as an output."
119+
with pytest.warns(UserWarning, match=warn_msg):
119120
Flow([add_job], output=add_job)
120121

121122
# test complex object containing job given rather than outputs
122123
add_job = get_test_job()
123-
with pytest.warns(UserWarning):
124+
with pytest.warns(UserWarning, match=warn_msg):
124125
Flow([add_job], output={1: [[{"a": add_job}]]})
125126

126127
# test job already belongs to another flow
@@ -203,13 +204,14 @@ def test_flow_of_flows_init():
203204
# test flow given rather than outputs
204205
add_job = get_test_job()
205206
sub_flow = Flow([add_job], output=add_job.output)
206-
with pytest.warns(UserWarning):
207+
warn_msg = "Flow 'Flow' contains a Flow or Job as an output."
208+
with pytest.warns(UserWarning, match=warn_msg):
207209
Flow([sub_flow], output=sub_flow)
208210

209211
# test complex object containing job given rather than outputs
210212
add_job = get_test_job()
211213
sub_flow = Flow([add_job], output=add_job.output)
212-
with pytest.warns(UserWarning):
214+
with pytest.warns(UserWarning, match=warn_msg):
213215
Flow([sub_flow], output={1: [[{"a": sub_flow}]]})
214216

215217
# test flow already belongs to another flow
@@ -354,6 +356,8 @@ def test_graph():
354356

355357

356358
def test_draw_graph():
359+
pytest.importorskip("matplotlib")
360+
357361
from jobflow import Flow, JobOrder
358362

359363
# test unconnected graph
@@ -383,8 +387,9 @@ def test_draw_graph():
383387
assert flow.draw_graph()
384388

385389

386-
@pytest.mark.usefixtures("no_pydot")
387-
def test_draw_graph_nopydot():
390+
def test_draw_graph_nopydot(no_pydot):
391+
pytest.importorskip("matplotlib")
392+
388393
from jobflow import Flow, JobOrder
389394

390395
# test unconnected graph
@@ -714,7 +719,7 @@ def test_add_jobs():
714719
flow2 = Flow([flow1])
715720
flow3 = Flow([flow2])
716721
with pytest.raises(
717-
ValueError, match="circular dependency: Flow .+ contains the current Flow"
722+
ValueError, match=r"circular dependency: Flow .+ contains the current Flow"
718723
):
719724
flow1.add_jobs(flow3)
720725

@@ -1312,7 +1317,7 @@ def test_flow_magic_methods_edge_cases():
13121317
):
13131318
_ = flow1 + job1
13141319

1315-
with pytest.raises(ValueError, match="Job .+ already belongs to another flow"):
1320+
with pytest.raises(ValueError, match=r"Job .+ already belongs to another flow"):
13161321
_ = flow1 + job6
13171322

13181323

tests/core/test_job.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,9 @@ def test_job_init():
3333
assert test_job.output.uuid == test_job.uuid
3434

3535
# test job as another job as input
36-
with pytest.warns(UserWarning):
36+
with pytest.warns(
37+
UserWarning, match="Job 'add' contains an Flow or Job as an input"
38+
):
3739
Job(function=add, function_args=(test_job,))
3840

3941
# test init with kwargs

tests/core/test_maker.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,6 @@ def bad_func(_: Maker) -> int:
252252
# test bad recursive call
253253
with pytest.raises(
254254
ValueError,
255-
match="Function must return a Maker object. Got <class 'int'> instead.",
255+
match=r"Function must return a Maker object. Got <class 'int'> instead.",
256256
):
257257
recursive_call(maker, bad_func)

tests/core/test_store.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ def test_basic(memory_store):
3232

3333

3434
def test_additional(memory_store):
35+
pytest.importorskip("moto")
36+
3537
from copy import deepcopy
3638

3739
import boto3

tests/managers/test_fireworks.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import pytest
22

3+
pytest.importorskip("fireworks")
4+
35

46
def test_flow_to_workflow(
57
memory_jobstore, simple_job, simple_flow, connected_flow, nested_flow

tests/test_settings.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ def test_settings_object(clean_dir, test_data):
7979
with open(config_file_path, "w") as f:
8080
pass
8181

82-
with pytest.warns(UserWarning):
82+
with pytest.warns(UserWarning, match="An empty JobFlow config file was located at"):
8383
settings = JobflowSettings()
8484

8585
# An error should be thrown if the file exists and

tests/utils/test_graph.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ def test_itergraph():
2020

2121
# test non-connected
2222
graph = DiGraph([("a", "b"), ("c", "d")])
23-
with pytest.warns(UserWarning):
23+
with pytest.warns(UserWarning, match="Some jobs are not connected"):
2424
result = list(itergraph(graph))
2525
assert {*result} == {"a", "b", "c", "d"}
2626

@@ -33,6 +33,8 @@ def test_itergraph():
3333

3434

3535
def test_draw_graph():
36+
pytest.importorskip("matplotlib")
37+
3638
from networkx import DiGraph, planar_layout
3739

3840
from jobflow.utils.graph import draw_graph
@@ -43,8 +45,9 @@ def test_draw_graph():
4345
assert draw_graph(graph, layout_function=planar_layout)
4446

4547

46-
@pytest.mark.usefixtures("no_pydot")
47-
def test_draw_graph_no_pydot():
48+
def test_draw_graph_no_pydot(no_pydot):
49+
pytest.importorskip("matplotlib")
50+
4851
from networkx import DiGraph
4952

5053
from jobflow.utils.graph import draw_graph
@@ -53,8 +56,7 @@ def test_draw_graph_no_pydot():
5356
assert draw_graph(graph)
5457

5558

56-
@pytest.mark.usefixtures("no_matplotlib")
57-
def test_draw_graph_no_matplotlib():
59+
def test_draw_graph_no_matplotlib(no_matplotlib):
5860
from networkx import DiGraph
5961

6062
import jobflow.utils.graph
@@ -71,6 +73,8 @@ def add(a, b):
7173

7274

7375
def test_to_pydot():
76+
pytest.importorskip("pydot")
77+
7478
from jobflow import Flow, Job
7579
from jobflow.utils.graph import to_pydot
7680

0 commit comments

Comments
 (0)