Skip to content

Commit aae19be

Browse files
rchen152facebook-github-bot
authored andcommitted
Move dataclass_from_dataclass_transform calculation into its own function
Reviewed By: grievejia Differential Revision: D80371741 fbshipit-source-id: 3608a2cfe919d79dc6f53a241e98a25f2d555e5c
1 parent 77fc5f0 commit aae19be

File tree

1 file changed

+55
-37
lines changed

1 file changed

+55
-37
lines changed

pyrefly/lib/alt/class/class_metadata.rs

Lines changed: 55 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -156,26 +156,6 @@ impl<'a, Ans: LookupAnswer> AnswersSolver<'a, Ans> {
156156
// this does not turn the class into a dataclass! Instead, it becomes a special base class
157157
// (or metaclass) that turns child classes into dataclasses.
158158
let mut dataclass_transform_metadata = dataclass_defaults_from_base_class.clone();
159-
// This is set when we should apply dataclass-like transformations to the class. The class
160-
// should be transformed if:
161-
// - it inherits from a base class decorated with `dataclass_transform(...)`, or
162-
// - it inherits from a base class whose metaclass is decorated with `dataclass_transform(...)`, or
163-
// - it is decorated with a decorator that is decorated with `dataclass_transform(...)`.
164-
// - is a Pydantic model
165-
let mut dataclass_from_dataclass_transform = None;
166-
if let Some(defaults) = dataclass_defaults_from_base_class {
167-
// This class inherits from a dataclass_transform-ed base class, so its keywords are
168-
// interpreted as dataclass keywords.
169-
let map = keywords.clone().into_iter().collect::<OrderedMap<_, _>>();
170-
let mut kws = DataclassKeywords::from_type_map(&TypeMap(map), &defaults);
171-
172-
// Inject frozen data from pydantic model
173-
if let Some(pydantic) = pydantic_metadata.clone() {
174-
kws.frozen = pydantic.frozen || kws.frozen;
175-
}
176-
177-
dataclass_from_dataclass_transform = Some((kws, defaults.field_specifiers));
178-
}
179159
let is_typed_dict = has_typed_dict_base_class
180160
|| bases_with_metadata
181161
.iter()
@@ -256,26 +236,15 @@ impl<'a, Ans: LookupAnswer> AnswersSolver<'a, Ans> {
256236
dataclass_transform_metadata =
257237
Some(DataclassTransformKeywords::from_type_map(&call.keywords));
258238
}
259-
// `@foo` where `foo` is decorated with `@dataclass_transform(...)`
260-
_ if let Some(defaults) = decorator_ty.dataclass_transform_metadata() => {
261-
dataclass_from_dataclass_transform = Some((
262-
DataclassKeywords::from_type_map(&TypeMap::new(), &defaults),
263-
defaults.field_specifiers,
264-
));
265-
}
266-
// `@foo(...)` where `foo` is decorated with `@dataclass_transform(...)`
267-
_ if let Type::KwCall(call) = decorator_ty
268-
&& let Some(defaults) =
269-
&call.func_metadata.flags.dataclass_transform_metadata =>
270-
{
271-
dataclass_from_dataclass_transform = Some((
272-
DataclassKeywords::from_type_map(&call.keywords, defaults),
273-
defaults.field_specifiers.clone(),
274-
));
275-
}
276239
_ => {}
277240
}
278241
}
242+
let dataclass_from_dataclass_transform = self.dataclass_from_dataclass_transform(
243+
&keywords,
244+
&decorators,
245+
dataclass_defaults_from_base_class,
246+
pydantic_metadata.as_ref(),
247+
);
279248
let dataclass_metadata = self.dataclass_metadata(
280249
cls,
281250
&decorators,
@@ -504,6 +473,55 @@ impl<'a, Ans: LookupAnswer> AnswersSolver<'a, Ans> {
504473
}
505474
}
506475

476+
fn dataclass_from_dataclass_transform(
477+
&self,
478+
keywords: &[(Name, Type)],
479+
decorators: &[(Arc<TypeInfo>, TextRange)],
480+
dataclass_defaults_from_base_class: Option<DataclassTransformKeywords>,
481+
pydantic_metadata: Option<&PydanticMetadata>,
482+
) -> Option<(DataclassKeywords, Vec<CalleeKind>)> {
483+
// This is set when we should apply dataclass-like transformations to the class. The class
484+
// should be transformed if:
485+
// - it inherits from a base class decorated with `dataclass_transform(...)`, or
486+
// - it inherits from a base class whose metaclass is decorated with `dataclass_transform(...)`, or
487+
// - it is decorated with a decorator that is decorated with `dataclass_transform(...)`.
488+
// - is a Pydantic model
489+
let mut dataclass_from_dataclass_transform = None;
490+
if let Some(defaults) = dataclass_defaults_from_base_class {
491+
// This class inherits from a dataclass_transform-ed base class, so its keywords are
492+
// interpreted as dataclass keywords.
493+
let map = keywords.iter().cloned().collect::<OrderedMap<_, _>>();
494+
let mut kws = DataclassKeywords::from_type_map(&TypeMap(map), &defaults);
495+
496+
// Inject frozen data from pydantic model
497+
if let Some(pydantic) = pydantic_metadata {
498+
kws.frozen = pydantic.frozen || kws.frozen;
499+
}
500+
501+
dataclass_from_dataclass_transform = Some((kws, defaults.field_specifiers));
502+
}
503+
for (decorator, _) in decorators {
504+
let decorator_ty = decorator.ty();
505+
// `@foo` where `foo` is decorated with `@dataclass_transform(...)`
506+
if let Some(defaults) = decorator_ty.dataclass_transform_metadata() {
507+
dataclass_from_dataclass_transform = Some((
508+
DataclassKeywords::from_type_map(&TypeMap::new(), &defaults),
509+
defaults.field_specifiers,
510+
));
511+
}
512+
// `@foo(...)` where `foo` is decorated with `@dataclass_transform(...)`
513+
else if let Type::KwCall(call) = decorator_ty
514+
&& let Some(defaults) = &call.func_metadata.flags.dataclass_transform_metadata
515+
{
516+
dataclass_from_dataclass_transform = Some((
517+
DataclassKeywords::from_type_map(&call.keywords, defaults),
518+
defaults.field_specifiers.clone(),
519+
));
520+
}
521+
}
522+
dataclass_from_dataclass_transform
523+
}
524+
507525
fn dataclass_metadata(
508526
&self,
509527
cls: &Class,

0 commit comments

Comments
 (0)