Skip to content

Commit 2c400ac

Browse files
committed
Run pydantic migrator on murfey and fix issues that arise
1 parent 9742156 commit 2c400ac

File tree

7 files changed

+51
-48
lines changed

7 files changed

+51
-48
lines changed

pyproject.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ classifiers = [
3131
]
3232
dependencies = [
3333
"defusedxml", # For safely parsing XML files
34-
"pydantic<2", # Locked to <2 by zocalo
34+
"pydantic>=2",
35+
"pydantic_settings",
3536
"requests",
3637
"rich",
3738
"werkzeug",

src/murfey/client/instance_environment.py

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
from typing import Callable, Dict, List, NamedTuple, Optional, Set
99
from urllib.parse import ParseResult
1010

11-
from pydantic import BaseModel, validator
11+
from pydantic import BaseModel, ConfigDict, field_validator
12+
from pydantic_core.core_schema import FieldValidationInfo
1213

1314
from murfey.client.watchdir import DirWatcher
1415

@@ -40,20 +41,20 @@ class MurfeyInstanceEnvironment(BaseModel):
4041
destination_registry: Dict[str, str] = {}
4142
watchers: Dict[Path, DirWatcher] = {}
4243
demo: bool = False
43-
data_collection_group_ids: Dict[str, int] = {}
44-
data_collection_ids: Dict[str, int] = {}
45-
processing_job_ids: Dict[str, Dict[str, int]] = {}
46-
autoproc_program_ids: Dict[str, Dict[str, int]] = {}
4744
id_tag_registry: Dict[str, List[str]] = {
4845
"data_collection_group": [],
4946
"data_collection": [],
5047
"processing_job": [],
5148
"auto_proc_program": [],
5249
}
50+
listeners: Dict[str, Set[Callable]] = {}
51+
data_collection_group_ids: Dict[str, int] = {}
52+
data_collection_ids: Dict[str, int] = {}
53+
processing_job_ids: Dict[str, Dict[str, int]] = {}
54+
autoproc_program_ids: Dict[str, Dict[str, int]] = {}
5355
data_collection_parameters: dict = {}
5456
movies: Dict[Path, MovieTracker] = {}
5557
motion_corrected_movies: Dict[Path, List[str]] = {}
56-
listeners: Dict[str, Set[Callable]] = {}
5758
movie_tilt_pair: Dict[Path, str] = {}
5859
tilt_angles: Dict[str, List[List[str]]] = {}
5960
movie_counters: Dict[str, itertools.count] = {}
@@ -64,42 +65,41 @@ class MurfeyInstanceEnvironment(BaseModel):
6465
murfey_session: Optional[int] = None
6566
samples: Dict[Path, SampleInfo] = {}
6667

67-
class Config:
68-
validate_assignment: bool = True
69-
arbitrary_types_allowed: bool = True
68+
model_config = ConfigDict(arbitrary_types_allowed=True)
7069

71-
@validator("data_collection_group_ids")
72-
def dcg_callback(cls, v, values):
70+
@field_validator("data_collection_group_ids")
71+
def dcg_callback(cls, v, info: FieldValidationInfo):
7372
with global_env_lock:
74-
for l in values.get("listeners", {}).get("data_collection_group_ids", []):
73+
for l in info.data.get("listeners", {}).get(
74+
"data_collection_group_ids", []
75+
):
7576
for k in v.keys():
76-
if k not in values["id_tag_registry"]["data_collection"]:
77+
if k not in info.data["id_tag_registry"]["data_collection"]:
7778
l(k)
7879
return v
7980

80-
@validator("data_collection_ids")
81-
def dc_callback(cls, v, values):
81+
@field_validator("data_collection_ids")
82+
def dc_callback(cls, v, info: FieldValidationInfo):
8283
with global_env_lock:
83-
for l in values.get("listeners", {}).get("data_collection_ids", []):
84+
for l in info.data.get("listeners", {}).get("data_collection_ids", []):
8485
for k in v.keys():
85-
if k not in values["id_tag_registry"]["processing_job"]:
86+
if k not in info.data["id_tag_registry"]["processing_job"]:
8687
l(k)
8788
return v
8889

89-
@validator("processing_job_ids")
90-
def job_callback(cls, v, values):
90+
@field_validator("processing_job_ids")
91+
def job_callback(cls, v, info: FieldValidationInfo):
9192
with global_env_lock:
92-
for l in values.get("listeners", {}).get("processing_job_ids", []):
93+
for l in info.data.get("listeners", {}).get("processing_job_ids", []):
9394
for k in v.keys():
94-
if k not in values["id_tag_registry"]["auto_proc_program"]:
95+
if k not in info.data["id_tag_registry"]["auto_proc_program"]:
9596
l(k, v[k]["ispyb-relion"])
9697
return v
9798

98-
@validator("autoproc_program_ids")
99-
def app_callback(cls, v, values):
100-
# logger.info(f"autoproc program ids validator: {v}")
99+
@field_validator("autoproc_program_ids")
100+
def app_callback(cls, v, info: FieldValidationInfo):
101101
with global_env_lock:
102-
for l in values.get("listeners", {}).get("autoproc_program_ids", []):
102+
for l in info.data.get("listeners", {}).get("autoproc_program_ids", []):
103103
for k in v.keys():
104104
if v[k].get("em-tomo-preprocess"):
105105
l(k, v[k]["em-tomo-preprocess"])

src/murfey/client/tui/screens.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ def validate_form(form: dict, model: BaseModel) -> bool:
197197
try:
198198
convert = lambda x: None if x == "None" else x
199199
validated = model(**{k: convert(v) for k, v in form.items()})
200-
log.info(validated.dict())
200+
log.info(validated.model_dump())
201201
return True
202202
except (AttributeError, ValidationError) as e:
203203
log.warning(f"Form validation failed: {str(e)}")

src/murfey/server/config.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,21 @@
77
from typing import Dict, List, Optional, Union
88

99
import yaml
10-
from pydantic import BaseModel, BaseSettings
10+
from pydantic import BaseModel
11+
from pydantic_settings import BaseSettings
1112

1213

1314
class MachineConfig(BaseModel):
1415
acquisition_software: List[str]
15-
calibrations: Dict[str, Dict[str, Union[dict, float]]]
16+
calibrations: Dict[str, Dict[int, Union[dict, float]]]
1617
data_directories: Dict[Path, str]
1718
rsync_basepath: Path
1819
murfey_db_credentials: str
1920
crypto_key: str
2021
default_model: Path
2122
display_name: str = ""
2223
image_path: Optional[Path] = None
23-
software_versions: Dict[str, str] = {}
24+
software_versions: Dict[str, float] = {}
2425
external_executables: Dict[str, str] = {}
2526
external_executables_eer: Dict[str, str] = {}
2627
external_environment: Dict[str, str] = {}

src/murfey/server/demo_api.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@
1414
from fastapi.responses import FileResponse, HTMLResponse
1515
from ispyb.sqlalchemy import BLSession
1616
from PIL import Image
17-
from pydantic import BaseModel, BaseSettings
17+
from pydantic import BaseModel
18+
from pydantic_settings import BaseSettings
1819
from sqlalchemy import func
1920
from sqlmodel import col, select
2021
from werkzeug.utils import secure_filename

src/murfey/server/main.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from fastapi.middleware.cors import CORSMiddleware
99
from fastapi.staticfiles import StaticFiles
1010
from prometheus_client import make_asgi_app
11-
from pydantic import BaseSettings
11+
from pydantic_settings import BaseSettings
1212

1313
import murfey.server
1414
import murfey.server.api.auth

src/murfey/util/models.py

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -219,13 +219,13 @@ class SPAProcessFile(BaseModel):
219219
tag: str
220220
path: str
221221
description: str
222-
processing_job: Optional[int]
223-
data_collection_id: Optional[int]
222+
processing_job: Optional[int] = None
223+
data_collection_id: Optional[int] = None
224224
image_number: int
225-
autoproc_program_id: Optional[int]
226-
foil_hole_id: Optional[int]
227-
pixel_size: Optional[float]
228-
dose_per_frame: Optional[float]
225+
autoproc_program_id: Optional[int] = None
226+
foil_hole_id: Optional[int] = None
227+
pixel_size: Optional[float] = None
228+
dose_per_frame: Optional[float] = None
229229
mc_binning: Optional[int] = 1
230230
gain_ref: Optional[str] = None
231231
extract_downscale: bool = True
@@ -236,7 +236,7 @@ class SPAProcessFile(BaseModel):
236236
class ProcessingParametersSPA(BaseModel):
237237
tag: str
238238
dose_per_frame: float
239-
gain_ref: Optional[str]
239+
gain_ref: Optional[str] = None
240240
experiment_type: str
241241
voltage: float
242242
image_size_x: int
@@ -247,12 +247,12 @@ class ProcessingParametersSPA(BaseModel):
247247
acquisition_software: str
248248
use_cryolo: bool
249249
symmetry: str
250-
mask_diameter: Optional[int]
251-
boxsize: Optional[int]
250+
mask_diameter: Optional[int] = None
251+
boxsize: Optional[int] = None
252252
downscale: bool
253-
small_boxsize: Optional[int]
253+
small_boxsize: Optional[int] = None
254254
eer_fractionation: int
255-
particle_diameter: Optional[float]
255+
particle_diameter: Optional[float] = None
256256
magnification: Optional[int] = None
257257
total_exposed_dose: Optional[float] = None
258258
c2aperture: Optional[float] = None
@@ -261,14 +261,14 @@ class ProcessingParametersSPA(BaseModel):
261261
phase_plate: bool = False
262262

263263
class Base(BaseModel):
264-
dose_per_frame: Optional[float]
265-
gain_ref: Optional[str]
264+
dose_per_frame: Optional[float] = None
265+
gain_ref: Optional[str] = None
266266
use_cryolo: bool
267267
symmetry: str
268-
mask_diameter: Optional[int]
269-
boxsize: Optional[int]
268+
mask_diameter: Optional[int] = None
269+
boxsize: Optional[int] = None
270270
downscale: bool
271-
small_boxsize: Optional[int]
271+
small_boxsize: Optional[int] = None
272272
eer_fractionation: int
273273

274274

0 commit comments

Comments
 (0)