rootstock 0.5.0__py3-none-any.whl → 0.5.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- rootstock/clusters.py +1 -1
- rootstock-0.5.1.dist-info/METADATA +178 -0
- {rootstock-0.5.0.dist-info → rootstock-0.5.1.dist-info}/RECORD +6 -6
- rootstock-0.5.0.dist-info/METADATA +0 -210
- {rootstock-0.5.0.dist-info → rootstock-0.5.1.dist-info}/WHEEL +0 -0
- {rootstock-0.5.0.dist-info → rootstock-0.5.1.dist-info}/entry_points.txt +0 -0
- {rootstock-0.5.0.dist-info → rootstock-0.5.1.dist-info}/licenses/LICENSE.md +0 -0
rootstock/clusters.py
CHANGED
|
@@ -12,7 +12,7 @@ from pathlib import Path
|
|
|
12
12
|
# Registry of known clusters and their rootstock root directories
|
|
13
13
|
CLUSTER_REGISTRY: dict[str, str] = {
|
|
14
14
|
"modal": "/vol/rootstock",
|
|
15
|
-
"della": "/scratch/gpfs/
|
|
15
|
+
"della": "/scratch/gpfs/ROSENGROUP/common/rootstock",
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
# Known environment families (used for validation)
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: rootstock
|
|
3
|
+
Version: 0.5.1
|
|
4
|
+
Summary: MLIP calculators with isolated Python environments
|
|
5
|
+
License-File: LICENSE.md
|
|
6
|
+
Requires-Python: >=3.10
|
|
7
|
+
Requires-Dist: ase>=3.22
|
|
8
|
+
Requires-Dist: numpy>=1.24
|
|
9
|
+
Requires-Dist: packaging>=21.0
|
|
10
|
+
Requires-Dist: tomli>=2.0; python_version < '3.11'
|
|
11
|
+
Provides-Extra: dev
|
|
12
|
+
Requires-Dist: pytest>=7.0; extra == 'dev'
|
|
13
|
+
Requires-Dist: ruff>=0.1; extra == 'dev'
|
|
14
|
+
Provides-Extra: mace
|
|
15
|
+
Requires-Dist: mace-torch>=0.3; extra == 'mace'
|
|
16
|
+
Requires-Dist: torch>=2.0; extra == 'mace'
|
|
17
|
+
Provides-Extra: modal
|
|
18
|
+
Requires-Dist: modal>=0.56; extra == 'modal'
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
|
|
21
|
+
# Rootstock
|
|
22
|
+
|
|
23
|
+
A proof-of-concept package for running MLIP (Machine Learning Interatomic Potential) calculators in isolated pre-built Python environments, communicating via the i-PI protocol over Unix sockets. Currently deployed on Princeton's Della cluster.
|
|
24
|
+
|
|
25
|
+
## Quick Start
|
|
26
|
+
|
|
27
|
+
```python
|
|
28
|
+
from ase.build import bulk
|
|
29
|
+
from rootstock import RootstockCalculator
|
|
30
|
+
|
|
31
|
+
atoms = bulk("Cu", "fcc", a=3.6) * (5, 5, 5)
|
|
32
|
+
|
|
33
|
+
with RootstockCalculator(
|
|
34
|
+
cluster="della",
|
|
35
|
+
model="mace",
|
|
36
|
+
checkpoint="medium",
|
|
37
|
+
device="cuda",
|
|
38
|
+
) as calc:
|
|
39
|
+
atoms.calc = calc
|
|
40
|
+
print(atoms.get_potential_energy())
|
|
41
|
+
print(atoms.get_forces())
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
**Note:** Environments must be pre-built before use. See [Administrator Setup](#administrator-setup).
|
|
45
|
+
|
|
46
|
+
## Installation
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
pip install rootstock
|
|
50
|
+
# or
|
|
51
|
+
uv pip install rootstock
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## API
|
|
55
|
+
|
|
56
|
+
The `model` parameter selects the environment family. The optional `checkpoint` parameter selects specific model weights (defaults to the environment's default if omitted).
|
|
57
|
+
|
|
58
|
+
```python
|
|
59
|
+
# Explicit checkpoint
|
|
60
|
+
RootstockCalculator(cluster="della", model="mace", checkpoint="medium")
|
|
61
|
+
|
|
62
|
+
# Default checkpoint (each environment has a sensible default)
|
|
63
|
+
RootstockCalculator(cluster="della", model="uma")
|
|
64
|
+
|
|
65
|
+
# Custom root path instead of a known cluster
|
|
66
|
+
RootstockCalculator(root="/scratch/gpfs/ROSENGROUP/common/rootstock", model="mace")
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Available Models
|
|
70
|
+
|
|
71
|
+
| Model | Checkpoint | Description |
|
|
72
|
+
|-------|------------|-------------|
|
|
73
|
+
| `mace` | `small` | MACE-MP-0 small |
|
|
74
|
+
| `mace` | `medium` (default) | MACE-MP-0 medium |
|
|
75
|
+
| `chgnet` | _(pretrained)_ | CHGNet pretrained universal model |
|
|
76
|
+
| `uma` | `uma-s-1p1` (default) | Meta UMA small model (FAIRChem) |
|
|
77
|
+
| `tensornet` | `TensorNet-MatPES-PBE-v2025.1-PES` (default) | TensorNet MatPES PBE (MatGL) |
|
|
78
|
+
|
|
79
|
+
## Architecture
|
|
80
|
+
|
|
81
|
+
```
|
|
82
|
+
Main Process Worker Process (subprocess)
|
|
83
|
+
+-------------------------+ +-----------------------------+
|
|
84
|
+
| RootstockCalculator | | Pre-built venv Python |
|
|
85
|
+
| (ASE-compatible) | | (mace_env/bin/python) |
|
|
86
|
+
| | | |
|
|
87
|
+
| server.py (i-PI server) |<-------->| worker.py (i-PI client) |
|
|
88
|
+
| - sends positions | Unix | - receives positions |
|
|
89
|
+
| - receives forces | socket | - calculates forces |
|
|
90
|
+
+-------------------------+ +-----------------------------+
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
The worker process uses a pre-built virtual environment, providing:
|
|
94
|
+
- **Fast startup**: No dependency installation at runtime
|
|
95
|
+
- **Filesystem compatibility**: Works on NFS, Lustre, GPFS
|
|
96
|
+
- **Reproducibility**: Same environment every time
|
|
97
|
+
|
|
98
|
+
## Directory Structure
|
|
99
|
+
|
|
100
|
+
```
|
|
101
|
+
{root}/
|
|
102
|
+
├── .python/ # uv-managed Python interpreters (portable)
|
|
103
|
+
├── environments/ # Environment SOURCE files (*.py with PEP 723)
|
|
104
|
+
│ ├── mace_env.py
|
|
105
|
+
│ ├── chgnet_env.py
|
|
106
|
+
│ ├── uma_env.py
|
|
107
|
+
│ └── tensornet_env.py
|
|
108
|
+
├── envs/ # Pre-built virtual environments
|
|
109
|
+
│ ├── mace_env/
|
|
110
|
+
│ │ ├── bin/python
|
|
111
|
+
│ │ ├── lib/python3.11/site-packages/
|
|
112
|
+
│ │ └── env_source.py # Copy of environment source
|
|
113
|
+
│ └── ...
|
|
114
|
+
├── home/ # Fake HOME for build & workers
|
|
115
|
+
│ ├── .cache/fairchem/ # FAIRChem weights
|
|
116
|
+
│ └── .matgl/ # MatGL weights
|
|
117
|
+
└── cache/ # XDG_CACHE_HOME for well-behaved libs
|
|
118
|
+
├── mace/
|
|
119
|
+
└── huggingface/
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## CLI Commands
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
# Build a pre-built environment
|
|
126
|
+
rootstock build <env_name> --root <path> [--models m1,m2] [--force]
|
|
127
|
+
|
|
128
|
+
# Show status
|
|
129
|
+
rootstock status --root <path>
|
|
130
|
+
|
|
131
|
+
# Register an environment source file
|
|
132
|
+
rootstock register <env_file> --root <path>
|
|
133
|
+
|
|
134
|
+
# List environments
|
|
135
|
+
rootstock list --root <path>
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## Administrator Setup
|
|
139
|
+
|
|
140
|
+
Environments must be pre-built before users can run calculations.
|
|
141
|
+
|
|
142
|
+
### 1. Create Directory Structure
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
mkdir -p /scratch/gpfs/ROSENGROUP/common/rootstock/{environments,envs,cache,home}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### 2. Register Environment Source Files
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
rootstock register environments/mace_env.py --root /scratch/gpfs/ROSENGROUP/common/rootstock
|
|
152
|
+
rootstock register environments/chgnet_env.py --root /scratch/gpfs/ROSENGROUP/common/rootstock
|
|
153
|
+
rootstock register environments/uma_env.py --root /scratch/gpfs/ROSENGROUP/common/rootstock
|
|
154
|
+
rootstock register environments/tensornet_env.py --root /scratch/gpfs/ROSENGROUP/common/rootstock
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### 3. Build Environments
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
ROOT=/scratch/gpfs/ROSENGROUP/common/rootstock
|
|
161
|
+
|
|
162
|
+
rootstock build mace_env --root $ROOT --models small,medium
|
|
163
|
+
rootstock build chgnet_env --root $ROOT
|
|
164
|
+
rootstock build uma_env --root $ROOT --models uma-s-1p1
|
|
165
|
+
rootstock build tensornet_env --root $ROOT
|
|
166
|
+
|
|
167
|
+
# Verify
|
|
168
|
+
rootstock status --root $ROOT
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## Local Development
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
uv venv && source .venv/bin/activate
|
|
175
|
+
uv pip install -e ".[dev]"
|
|
176
|
+
ruff check rootstock/
|
|
177
|
+
ruff format rootstock/
|
|
178
|
+
```
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
rootstock/__init__.py,sha256=Qu570ne-AeWn6IT4Us00iU43A0yoRlyYDygYvKHduVQ,956
|
|
2
2
|
rootstock/calculator.py,sha256=0KpW3coJ0ealEIZkxq9i4kZV5AxqCX1xZqDI1HkUPA4,6257
|
|
3
3
|
rootstock/cli.py,sha256=6YtUXs38Zc5BC0AjEaAygtmct6JAsfaGTX7Zn2K_imY,13815
|
|
4
|
-
rootstock/clusters.py,sha256=
|
|
4
|
+
rootstock/clusters.py,sha256=V5hTxlpq6-u3rfYhOkndqS96oSw2nXG8nDsTePAp79U,1218
|
|
5
5
|
rootstock/environment.py,sha256=e7AAKd7cECwnX-KHCdfelHYVqm3xa1mIvc2MGaTJwBs,6583
|
|
6
6
|
rootstock/pep723.py,sha256=hgTcP7Tp8_z_DCrmX4VPAitijvujmbGmz2ng1VgNYks,4616
|
|
7
7
|
rootstock/protocol.py,sha256=CgfYNc0aKOkAQ-D8tvUrVO5q1mg0Xwcl2F02ZvYOJCI,10169
|
|
8
8
|
rootstock/server.py,sha256=H7kn1FHGGyrrPZtgRKdfagbAF-SxI89H3u85GSToYmY,9210
|
|
9
9
|
rootstock/worker.py,sha256=ty13OPDcKd_Zy95MAnTwa063Glz_RfUTBDja9Lxy4SM,8961
|
|
10
|
-
rootstock-0.5.
|
|
11
|
-
rootstock-0.5.
|
|
12
|
-
rootstock-0.5.
|
|
13
|
-
rootstock-0.5.
|
|
14
|
-
rootstock-0.5.
|
|
10
|
+
rootstock-0.5.1.dist-info/METADATA,sha256=hoHLVVE66Lm8q5uEAKYetK6x7bllBDN99H3LvpXrZqc,5562
|
|
11
|
+
rootstock-0.5.1.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
12
|
+
rootstock-0.5.1.dist-info/entry_points.txt,sha256=rPiVll-qj1wq7wZQTwSl2aF22GLnnpDz37hkPLvqlh0,49
|
|
13
|
+
rootstock-0.5.1.dist-info/licenses/LICENSE.md,sha256=ORJAYeKSWpOYZ89KWT8ETWFb2u6MvKK3AhrMReDMWrA,1072
|
|
14
|
+
rootstock-0.5.1.dist-info/RECORD,,
|
|
@@ -1,210 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: rootstock
|
|
3
|
-
Version: 0.5.0
|
|
4
|
-
Summary: MLIP calculators with isolated Python environments
|
|
5
|
-
License-File: LICENSE.md
|
|
6
|
-
Requires-Python: >=3.10
|
|
7
|
-
Requires-Dist: ase>=3.22
|
|
8
|
-
Requires-Dist: numpy>=1.24
|
|
9
|
-
Requires-Dist: packaging>=21.0
|
|
10
|
-
Requires-Dist: tomli>=2.0; python_version < '3.11'
|
|
11
|
-
Provides-Extra: dev
|
|
12
|
-
Requires-Dist: pytest>=7.0; extra == 'dev'
|
|
13
|
-
Requires-Dist: ruff>=0.1; extra == 'dev'
|
|
14
|
-
Provides-Extra: mace
|
|
15
|
-
Requires-Dist: mace-torch>=0.3; extra == 'mace'
|
|
16
|
-
Requires-Dist: torch>=2.0; extra == 'mace'
|
|
17
|
-
Provides-Extra: modal
|
|
18
|
-
Requires-Dist: modal>=0.56; extra == 'modal'
|
|
19
|
-
Description-Content-Type: text/markdown
|
|
20
|
-
|
|
21
|
-
# Rootstock
|
|
22
|
-
|
|
23
|
-
Run MLIP (Machine Learning Interatomic Potential) calculators in isolated pre-built Python environments, communicating via the i-PI protocol over Unix sockets.
|
|
24
|
-
|
|
25
|
-
## Quick Start
|
|
26
|
-
|
|
27
|
-
```python
|
|
28
|
-
from ase.build import bulk
|
|
29
|
-
from rootstock import RootstockCalculator
|
|
30
|
-
|
|
31
|
-
atoms = bulk("Cu", "fcc", a=3.6) * (5, 5, 5)
|
|
32
|
-
|
|
33
|
-
# Using a known cluster
|
|
34
|
-
with RootstockCalculator(
|
|
35
|
-
cluster="modal", # or "della"
|
|
36
|
-
model="mace-medium", # or "chgnet", "mace-small", etc.
|
|
37
|
-
device="cuda",
|
|
38
|
-
) as calc:
|
|
39
|
-
atoms.calc = calc
|
|
40
|
-
print(atoms.get_potential_energy())
|
|
41
|
-
print(atoms.get_forces())
|
|
42
|
-
|
|
43
|
-
# Or with an explicit root path
|
|
44
|
-
with RootstockCalculator(
|
|
45
|
-
root="/scratch/gpfs/SHARED/rootstock",
|
|
46
|
-
model="mace-medium",
|
|
47
|
-
device="cuda",
|
|
48
|
-
) as calc:
|
|
49
|
-
atoms.calc = calc
|
|
50
|
-
print(atoms.get_potential_energy())
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
**Note:** Environments must be pre-built before use. See [Administrator Setup](#administrator-setup).
|
|
54
|
-
|
|
55
|
-
## Installation
|
|
56
|
-
|
|
57
|
-
```bash
|
|
58
|
-
pip install rootstock
|
|
59
|
-
# or
|
|
60
|
-
uv pip install rootstock
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
## Model String Format
|
|
64
|
-
|
|
65
|
-
The `model` parameter encodes both the environment and model-specific argument:
|
|
66
|
-
|
|
67
|
-
| `model=` | Environment | Model Arg |
|
|
68
|
-
|---------------------|----------------|---------------------|
|
|
69
|
-
| `"mace-medium"` | mace_env | `"medium"` |
|
|
70
|
-
| `"mace-small"` | mace_env | `"small"` |
|
|
71
|
-
| `"mace-large"` | mace_env | `"large"` |
|
|
72
|
-
| `"chgnet"` | chgnet_env | `""` (default) |
|
|
73
|
-
| `"mace-/path/to/weights.pt"` | mace_env | `"/path/to/weights.pt"` |
|
|
74
|
-
|
|
75
|
-
## Known Clusters
|
|
76
|
-
|
|
77
|
-
| Cluster | Root Path |
|
|
78
|
-
|---------|-----------|
|
|
79
|
-
| `modal` | `/vol/rootstock` |
|
|
80
|
-
| `della` | `/scratch/gpfs/SHARED/rootstock` |
|
|
81
|
-
|
|
82
|
-
For other clusters, use `root="/path/to/rootstock"` directly.
|
|
83
|
-
|
|
84
|
-
## Administrator Setup
|
|
85
|
-
|
|
86
|
-
Environments must be pre-built before users can run calculations.
|
|
87
|
-
|
|
88
|
-
### 1. Create Directory Structure
|
|
89
|
-
|
|
90
|
-
```bash
|
|
91
|
-
mkdir -p /scratch/gpfs/SHARED/rootstock/{environments,envs,cache}
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
### 2. Create Environment Source Files
|
|
95
|
-
|
|
96
|
-
```bash
|
|
97
|
-
# mace_env.py
|
|
98
|
-
cat > /scratch/gpfs/SHARED/rootstock/environments/mace_env.py << 'EOF'
|
|
99
|
-
# /// script
|
|
100
|
-
# requires-python = ">=3.10"
|
|
101
|
-
# dependencies = ["mace-torch>=0.3.0", "ase>=3.22", "torch>=2.0"]
|
|
102
|
-
# ///
|
|
103
|
-
"""MACE environment for Rootstock."""
|
|
104
|
-
|
|
105
|
-
def setup(model: str, device: str = "cuda"):
|
|
106
|
-
from mace.calculators import mace_mp
|
|
107
|
-
return mace_mp(model=model, device=device, default_dtype="float32")
|
|
108
|
-
EOF
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
### 3. Build Environments
|
|
112
|
-
|
|
113
|
-
```bash
|
|
114
|
-
# Build MACE environment with model pre-download
|
|
115
|
-
rootstock build mace_env --root /scratch/gpfs/SHARED/rootstock --models small,medium,large
|
|
116
|
-
|
|
117
|
-
# Build CHGNet environment
|
|
118
|
-
rootstock build chgnet_env --root /scratch/gpfs/SHARED/rootstock
|
|
119
|
-
|
|
120
|
-
# Verify
|
|
121
|
-
rootstock status --root /scratch/gpfs/SHARED/rootstock
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
## Architecture
|
|
125
|
-
|
|
126
|
-
```
|
|
127
|
-
Main Process Worker Process (subprocess)
|
|
128
|
-
+-------------------------+ +-----------------------------+
|
|
129
|
-
| RootstockCalculator | | Pre-built venv Python |
|
|
130
|
-
| (ASE-compatible) | | (mace_env/bin/python) |
|
|
131
|
-
| | | |
|
|
132
|
-
| server.py (i-PI server) |<-------->| worker.py (i-PI client) |
|
|
133
|
-
| - sends positions | Unix | - receives positions |
|
|
134
|
-
| - receives forces | socket | - calculates forces |
|
|
135
|
-
+-------------------------+ +-----------------------------+
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
The worker process uses a pre-built virtual environment, providing:
|
|
139
|
-
- **Fast startup**: No dependency installation at runtime
|
|
140
|
-
- **Filesystem compatibility**: Works on NFS, Lustre, GPFS, Modal volumes
|
|
141
|
-
- **Reproducibility**: Same environment every time
|
|
142
|
-
|
|
143
|
-
## Directory Structure
|
|
144
|
-
|
|
145
|
-
```
|
|
146
|
-
{root}/
|
|
147
|
-
├── environments/ # Environment SOURCE files (*.py with PEP 723)
|
|
148
|
-
│ ├── mace_env.py
|
|
149
|
-
│ └── chgnet_env.py
|
|
150
|
-
├── envs/ # Pre-built virtual environments
|
|
151
|
-
│ ├── mace_env/
|
|
152
|
-
│ │ ├── bin/python
|
|
153
|
-
│ │ ├── lib/python3.11/site-packages/
|
|
154
|
-
│ │ └── env_source.py # Copy of environment source
|
|
155
|
-
│ └── chgnet_env/
|
|
156
|
-
└── cache/ # XDG_CACHE_HOME for model weights
|
|
157
|
-
├── mace/ # MACE models
|
|
158
|
-
└── huggingface/ # HuggingFace models
|
|
159
|
-
```
|
|
160
|
-
|
|
161
|
-
## CLI Commands
|
|
162
|
-
|
|
163
|
-
```bash
|
|
164
|
-
# Build a pre-built environment
|
|
165
|
-
rootstock build <env_name> --root <path> [--models m1,m2] [--force]
|
|
166
|
-
|
|
167
|
-
# Show status
|
|
168
|
-
rootstock status --root <path>
|
|
169
|
-
|
|
170
|
-
# Register an environment source file
|
|
171
|
-
rootstock register <env_file> --root <path>
|
|
172
|
-
|
|
173
|
-
# List environments
|
|
174
|
-
rootstock list --root <path>
|
|
175
|
-
```
|
|
176
|
-
|
|
177
|
-
## Running on Modal
|
|
178
|
-
|
|
179
|
-
```bash
|
|
180
|
-
# Initialize volume and build environments (takes ~10-15 min)
|
|
181
|
-
modal run modal_app.py::init_rootstock_volume
|
|
182
|
-
|
|
183
|
-
# Test pre-built environments
|
|
184
|
-
modal run modal_app.py::test_prebuilt
|
|
185
|
-
|
|
186
|
-
# Show status
|
|
187
|
-
modal run modal_app.py::inspect_status
|
|
188
|
-
|
|
189
|
-
# Run benchmarks
|
|
190
|
-
modal run modal_app.py::benchmark_v4
|
|
191
|
-
```
|
|
192
|
-
|
|
193
|
-
## Performance
|
|
194
|
-
|
|
195
|
-
IPC overhead is <5% for systems with 1000+ atoms compared to direct in-process execution.
|
|
196
|
-
|
|
197
|
-
| System Size | Atoms | Typical Overhead |
|
|
198
|
-
|-------------|-------|------------------|
|
|
199
|
-
| Small | 64 | ~10-15% |
|
|
200
|
-
| Medium | 256 | ~5-8% |
|
|
201
|
-
| Large | 1000 | <5% |
|
|
202
|
-
|
|
203
|
-
## Local Development
|
|
204
|
-
|
|
205
|
-
```bash
|
|
206
|
-
uv venv && source .venv/bin/activate
|
|
207
|
-
uv pip install -e ".[dev]"
|
|
208
|
-
ruff check rootstock/
|
|
209
|
-
ruff format rootstock/
|
|
210
|
-
```
|
|
File without changes
|
|
File without changes
|
|
File without changes
|