Skip to content

Commit 8c53ac2

Browse files
authored
[MNT] update marshmallow (#1172)
* update neurostore to marshmallow 4.0 * update compose to use marshmallow 4.0 * style
1 parent 48dcf06 commit 8c53ac2

File tree

10 files changed

+177
-129
lines changed

10 files changed

+177
-129
lines changed

compose/backend/neurosynth_compose/resources/analysis.py

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -317,21 +317,21 @@ def insert_data(self, id, data):
317317

318318

319319
LIST_USER_ARGS = {
320-
"search": fields.String(missing=None),
321-
"sort": fields.String(missing="created_at"),
322-
"page": fields.Int(missing=1),
323-
"desc": fields.Boolean(missing=True),
324-
"page_size": fields.Int(missing=20, validate=lambda val: val < 100),
325-
"source_id": fields.String(missing=None),
326-
"source": fields.String(missing=None),
327-
"unique": fields.Boolean(missing=False),
328-
"nested": fields.Boolean(missing=False),
329-
"user_id": fields.String(missing=None),
330-
"dataset_id": fields.String(missing=None),
331-
"export": fields.Boolean(missing=False),
332-
"data_type": fields.String(missing=None),
333-
"info": fields.Boolean(missing=False),
334-
"ids": fields.List(fields.String(), missing=None),
320+
"search": fields.String(load_default=None),
321+
"sort": fields.String(load_default="created_at"),
322+
"page": fields.Int(load_default=1),
323+
"desc": fields.Boolean(load_default=True),
324+
"page_size": fields.Int(load_default=20, validate=lambda val: val < 100),
325+
"source_id": fields.String(load_default=None),
326+
"source": fields.String(load_default=None),
327+
"unique": fields.Boolean(load_default=False),
328+
"nested": fields.Boolean(load_default=False),
329+
"user_id": fields.String(load_default=None),
330+
"dataset_id": fields.String(load_default=None),
331+
"export": fields.Boolean(load_default=False),
332+
"data_type": fields.String(load_default=None),
333+
"info": fields.Boolean(load_default=False),
334+
"ids": fields.List(fields.String(), load_default=None),
335335
}
336336

337337

@@ -702,8 +702,8 @@ def db_validation(self, data):
702702
def post(self):
703703
clone_args = parser.parse(
704704
{
705-
"source_id": fields.String(missing=None),
706-
"copy_annotations": fields.Boolean(missing=True),
705+
"source_id": fields.String(load_default=None),
706+
"copy_annotations": fields.Boolean(load_default=True),
707707
},
708708
request,
709709
location="query",

compose/backend/neurosynth_compose/schemas/analysis.py

Lines changed: 40 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,13 @@
88
NS_BASE = "https://neurostore.org/api"
99

1010

11+
class ContextSchema(Schema):
12+
def __init__(self, *args, **kwargs):
13+
context = kwargs.pop("context", {})
14+
super().__init__(*args, **kwargs)
15+
self.context = context or {}
16+
17+
1118
class BytesField(fields.Field):
1219
def _deserialize(self, value, attr, data, **kwargs):
1320
if isinstance(value, str):
@@ -29,7 +36,7 @@ def _deserialize(self, value, attr, data, **kwargs):
2936
return result.replace("\x00", "\uFFFD")
3037

3138

32-
class ResultInitSchema(Schema):
39+
class ResultInitSchema(ContextSchema):
3340
meta_analysis_id = fields.String(load_only=True)
3441
meta_analysis = fields.Pluck(
3542
"MetaAnalysisSchema", "id", attribute="meta_analysis", dump_only=True
@@ -39,15 +46,15 @@ class ResultInitSchema(Schema):
3946
specification_snapshot = fields.Dict()
4047

4148

42-
class ResultUploadSchema(Schema):
43-
statistical_maps = fields.Raw(
44-
metadata={"type": "string", "format": "binary"}, many=True
49+
class ResultUploadSchema(ContextSchema):
50+
statistical_maps = fields.List(
51+
fields.Raw(metadata={"type": "string", "format": "binary"})
4552
)
46-
cluster_tables = fields.Raw(
47-
metadata={"type": "string", "format": "binary"}, many=True
53+
cluster_tables = fields.List(
54+
fields.Raw(metadata={"type": "string", "format": "binary"})
4855
)
49-
diagnostic_tables = fields.Raw(
50-
metadata={"type": "string", "format": "binary"}, many=True
56+
diagnostic_tables = fields.List(
57+
fields.Raw(metadata={"type": "string", "format": "binary"})
5158
)
5259
method_description = fields.String()
5360

@@ -59,6 +66,23 @@ class StringOrNested(fields.Nested):
5966
"invalid_utf8": "Not a valid utf-8 string.",
6067
}
6168

69+
def __init__(self, nested, *args, **kwargs):
70+
super().__init__(nested, **kwargs)
71+
self._explicit_context = {}
72+
73+
@property
74+
def context(self):
75+
if self._explicit_context:
76+
return self._explicit_context
77+
parent = getattr(self, "parent", None)
78+
if parent is not None and hasattr(parent, "context"):
79+
return parent.context
80+
return {}
81+
82+
@context.setter
83+
def context(self, value):
84+
self._explicit_context = value or {}
85+
6286
def _serialize(self, value, attr, obj, **kwargs):
6387
if value is None:
6488
return None
@@ -127,7 +151,7 @@ def _deserialize(self, value, attr, data, **kwargs):
127151
raise self.make_error("invalid_utf8") from error
128152

129153

130-
class BaseSchema(Schema):
154+
class BaseSchema(ContextSchema):
131155
id = PGSQLString(metadata={"info_field": True})
132156
created_at = fields.DateTime()
133157
updated_at = fields.DateTime(allow_none=True)
@@ -137,7 +161,7 @@ class BaseSchema(Schema):
137161
)
138162

139163

140-
class ConditionSchema(Schema):
164+
class ConditionSchema(ContextSchema):
141165
id = PGSQLString()
142166
created_at = fields.DateTime()
143167
updated_at = fields.DateTime(allow_none=True)
@@ -147,15 +171,15 @@ class ConditionSchema(Schema):
147171

148172
class SpecificationConditionSchema(BaseSchema):
149173
condition = fields.Pluck(ConditionSchema, "name")
150-
weight = fields.Number()
174+
weight = fields.Float()
151175

152176

153-
class EstimatorSchema(Schema):
177+
class EstimatorSchema(ContextSchema):
154178
type = fields.String()
155179
args = fields.Dict()
156180

157181

158-
class StudysetReferenceSchema(Schema):
182+
class StudysetReferenceSchema(ContextSchema):
159183
id = PGSQLString()
160184
created_at = fields.DateTime()
161185
updated_at = fields.DateTime(allow_none=True)
@@ -168,7 +192,7 @@ class StudysetReferenceSchema(Schema):
168192
)
169193

170194

171-
class AnnotationReferenceSchema(Schema):
195+
class AnnotationReferenceSchema(ContextSchema):
172196
id = PGSQLString()
173197

174198

@@ -177,6 +201,8 @@ class SpecificationSchema(BaseSchema):
177201
mask = PGSQLString(allow_none=True)
178202
transformer = PGSQLString(allow_none=True)
179203
estimator = fields.Nested("EstimatorSchema")
204+
name = PGSQLString(allow_none=True)
205+
description = PGSQLString(allow_none=True)
180206
database_studyset = PGSQLString(allow_none=True)
181207
contrast = PGSQLString(allow_none=True)
182208
filter = PGSQLString(allow_none=True)
@@ -208,10 +234,6 @@ class SpecificationSchema(BaseSchema):
208234
attribute="weights",
209235
)
210236

211-
class Meta:
212-
additional = ("name", "description")
213-
allow_none = ("name", "description")
214-
215237
@post_dump
216238
def to_bool(self, data, **kwargs):
217239
conditions = data.get("conditions", None)

compose/backend/neurosynth_compose/schemas/users.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@
77

88

99
class UserSchema(BaseSchema):
10-
name = fields.Str(description="User full name")
11-
external_id = fields.Str(description="External authentication service user ID")
10+
name = fields.Str(metadata={"description": "User full name"})
11+
external_id = fields.Str(
12+
metadata={"description": "External authentication service user ID"}
13+
)
1214

1315
class Meta:
1416
unknown = EXCLUDE

compose/backend/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ dependencies = [
2424
"flask-sqlalchemy~=3.1",
2525
"gunicorn~=23.0",
2626
"ipython~=9.6",
27-
"marshmallow~=3.0",
27+
"marshmallow~=4.0",
2828
"pandas~=2.0",
2929
"psycopg2-binary~=2.8",
3030
"pyld~=2.0",

store/backend/neurostore/resources/data.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -506,6 +506,11 @@ def load_from_neurostore(cls, source_id, data=None):
506506
schema = cls._schema(context=context)
507507
tmp_data = schema.dump(annotation)
508508
data = schema.load(tmp_data)
509+
# Ensure cloned payload does not reference original primary keys
510+
data.pop("id", None)
511+
for note in data.get("annotation_analyses") or []:
512+
if isinstance(note, dict):
513+
note.pop("id", None)
509514
data["source"] = "neurostore"
510515
data["source_id"] = source_id
511516
data["source_updated_at"] = annotation.updated_at or annotation.created_at

store/backend/neurostore/resources/pipeline.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,10 @@ class PipelineStudyResultsView(ObjectView, ListView):
9696
"feature_flatten": fields.Bool(load_default=False),
9797
"feature_display": fields.List(
9898
fields.String(),
99-
description="List of pipeline results. format: pipeline_name[:version]",
10099
load_default=[],
100+
metadata={
101+
"description": "List of pipeline results. format: pipeline_name[:version]"
102+
},
101103
),
102104
}
103105

0 commit comments

Comments
 (0)