Skip to content

Commit fcd0d0b

Browse files
Migrate to pydantic version 2 (#372)
Co-authored-by: Eu Pin Tien <[email protected]>
1 parent 060a5da commit fcd0d0b

20 files changed

+141
-89
lines changed

pyproject.toml

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ classifiers = [
3232
dependencies = [
3333
"backports.entry_points_selectable",
3434
"defusedxml", # For safely parsing XML files
35-
"pydantic<2", # Locked to <2 by cygwin terminal
35+
"pydantic>=2",
36+
"pydantic-settings",
3637
"requests",
3738
"rich",
3839
"werkzeug",
@@ -47,7 +48,7 @@ client = [
4748
"websocket-client",
4849
]
4950
developer = [
50-
"bump-my-version<0.11.0", # Version control
51+
"bump-my-version", # Version control
5152
"ipykernel", # Enable interactive coding with VS Code and Jupyter Notebook
5253
"pre-commit", # Formatting, linting, type checking, etc.
5354
"pytest", # Test code functionality
@@ -61,7 +62,7 @@ server = [
6162
"aiohttp",
6263
"cryptography",
6364
"fastapi[standard]",
64-
"ispyb", # Responsible for setting requirements for SQLAlchemy and mysql-connector-python; v10.0.0: sqlalchemy <2, mysql-connector-python >=8.0.32
65+
"ispyb>=10.2.4", # Responsible for setting requirements for SQLAlchemy and mysql-connector-python;
6566
"jinja2",
6667
"mrcfile",
6768
"numpy<2",
@@ -73,7 +74,7 @@ server = [
7374
"sqlalchemy[postgresql]", # Add as explicit dependency
7475
"sqlmodel",
7576
"stomp-py<=8.1.0", # 8.1.1 (released 2024-04-06) doesn't work with our project
76-
"zocalo",
77+
"zocalo>=1",
7778
]
7879
[project.urls]
7980
Bug-Tracker = "https://github.com/DiamondLightSource/python-murfey/issues"

src/murfey/client/contexts/spa.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -506,7 +506,8 @@ def post_transfer(
506506
except Exception as e:
507507
# try to continue if position information gathering fails so that movie is processed anyway
508508
logger.warning(
509-
f"Unable to register foil hole for {str(file_transferred_to)}. Exception: {str(e)}"
509+
f"Unable to register foil hole for {str(file_transferred_to)}. Exception: {str(e)}",
510+
exc_info=True,
510511
)
511512
foil_hole = None
512513

src/murfey/client/contexts/tomo.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ def register_tomography_data_collections(
173173
)
174174

175175
except Exception as e:
176-
logger.error(f"ERROR {e}, {self.data_collection_parameters}")
176+
logger.error(f"ERROR {e}, {self.data_collection_parameters}", exc_info=True)
177177

178178
def _file_transferred_to(
179179
self, environment: MurfeyInstanceEnvironment, source: Path, file_path: Path
@@ -533,7 +533,9 @@ def gather_metadata(
533533
try:
534534
for_parsing = xml.read()
535535
except Exception:
536-
logger.warning(f"Failed to parse file {metadata_file}")
536+
logger.warning(
537+
f"Failed to parse file {metadata_file}", exc_info=True
538+
)
537539
return OrderedDict({})
538540
data = xmltodict.parse(for_parsing)
539541
try:
@@ -628,7 +630,9 @@ def gather_metadata(
628630
/ int(mdoc_metadata["num_eer_frames"])
629631
)
630632
except Exception as e:
631-
logger.error(f"Exception encountered in metadata gathering: {str(e)}")
633+
logger.error(
634+
f"Exception encountered in metadata gathering: {str(e)}", exc_info=True
635+
)
632636
return OrderedDict({})
633637

634638
return mdoc_metadata

src/murfey/client/instance_environment.py

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

11-
from pydantic import BaseModel
11+
from pydantic import BaseModel, ConfigDict
1212

1313
from murfey.client.watchdir import DirWatcher
1414

@@ -56,9 +56,7 @@ class MurfeyInstanceEnvironment(BaseModel):
5656
samples: Dict[Path, SampleInfo] = {}
5757
rsync_url: str = ""
5858

59-
class Config:
60-
validate_assignment: bool = True
61-
arbitrary_types_allowed: bool = True
59+
model_config = ConfigDict(arbitrary_types_allowed=True)
6260

6361
def clear(self):
6462
self.sources = []

src/murfey/client/tui/screens.py

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

src/murfey/instrument_server/api.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -335,14 +335,14 @@ def register_processing_parameters(
335335
session_id: MurfeySessionID, proc_param_block: ProcessingParameterBlock
336336
):
337337
data_collection_parameters[proc_param_block.label] = {}
338-
for k, v in proc_param_block.params.dict().items():
338+
for k, v in proc_param_block.params.model_dump().items():
339339
if v is not None:
340340
data_collection_parameters[proc_param_block.label][k] = v
341341
if controllers.get(session_id):
342342
controllers[session_id].data_collection_parameters.update(
343343
data_collection_parameters[proc_param_block.label]
344344
)
345-
for k, v in proc_param_block.params.dict().items():
345+
for k, v in proc_param_block.params.model_dump().items():
346346
if v is not None and hasattr(controllers[session_id]._environment, k):
347347
setattr(controllers[session_id]._environment, k, v)
348348
return {"success": True}

src/murfey/server/api/clem.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
from backports.entry_points_selectable import entry_points
1212
from fastapi import APIRouter
13-
from pydantic import BaseModel, validator
13+
from pydantic import BaseModel, field_validator
1414
from sqlalchemy.exc import NoResultFound
1515
from sqlmodel import Session, select
1616

@@ -820,10 +820,8 @@ class AlignAndMergeParams(BaseModel):
820820
flatten: Literal["mean", "min", "max", ""] = ""
821821
align_across: Literal["enabled", ""] = ""
822822

823-
@validator(
824-
"images",
825-
pre=True,
826-
)
823+
@field_validator("images", mode="before")
824+
@classmethod
827825
def parse_stringified_list(cls, value):
828826
if isinstance(value, str):
829827
try:

src/murfey/server/api/prometheus.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ def increment_rsync_file_count(
3939
logger.error(
4040
f"Failed to find rsync instance for visit {sanitise(visit_name)} "
4141
"with the following properties: \n"
42-
f"{rsyncer_info.dict()}",
42+
f"{rsyncer_info.model_dump()}",
4343
exc_info=True,
4444
)
4545
return None

src/murfey/server/api/session_control.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ def get_current_visits(instrument_name: str, db=ispyb_db):
9696

9797

9898
class SessionInfo(BaseModel):
99-
session_id: Optional[int]
99+
session_id: Optional[int] = None
100100
session_name: str = ""
101101
rescale: bool = True
102102

src/murfey/server/api/workflow.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ class DCGroupParameters(BaseModel):
8181
tag: str
8282
atlas: str = ""
8383
sample: Optional[int] = None
84-
atlas_pixel_size: int = 0
84+
atlas_pixel_size: float = 0
8585

8686

8787
@router.post("/visits/{visit_name}/{session_id}/register_data_collection_group")
@@ -346,13 +346,13 @@ class SPAProcessFile(BaseModel):
346346
tag: str
347347
path: str
348348
description: str
349-
processing_job: Optional[int]
350-
data_collection_id: Optional[int]
349+
processing_job: Optional[int] = None
350+
data_collection_id: Optional[int] = None
351351
image_number: int
352-
autoproc_program_id: Optional[int]
353-
foil_hole_id: Optional[int]
354-
pixel_size: Optional[float]
355-
dose_per_frame: Optional[float]
352+
autoproc_program_id: Optional[int] = None
353+
foil_hole_id: Optional[int] = None
354+
pixel_size: Optional[float] = None
355+
dose_per_frame: Optional[float] = None
356356
mc_binning: Optional[int] = 1
357357
gain_ref: Optional[str] = None
358358
extract_downscale: bool = True
@@ -608,9 +608,9 @@ class TomoProcessFile(BaseModel):
608608
tag: str
609609
image_number: int
610610
pixel_size: float
611-
dose_per_frame: Optional[float]
611+
dose_per_frame: Optional[float] = None
612612
frame_count: int
613-
tilt_axis: Optional[float]
613+
tilt_axis: Optional[float] = None
614614
mc_uuid: Optional[int] = None
615615
voltage: float = 300
616616
mc_binning: int = 1
@@ -894,7 +894,7 @@ class Sample(BaseModel):
894894
sample_group_id: int
895895
sample_id: int
896896
subsample_id: int
897-
image_path: Optional[Path]
897+
image_path: Optional[Path] = None
898898

899899

900900
@correlative_router.get("/visit/{visit_name}/samples")

0 commit comments

Comments
 (0)