@@ -156,26 +156,6 @@ impl<'a, Ans: LookupAnswer> AnswersSolver<'a, Ans> {
156
156
// this does not turn the class into a dataclass! Instead, it becomes a special base class
157
157
// (or metaclass) that turns child classes into dataclasses.
158
158
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
- }
179
159
let is_typed_dict = has_typed_dict_base_class
180
160
|| bases_with_metadata
181
161
. iter ( )
@@ -256,26 +236,15 @@ impl<'a, Ans: LookupAnswer> AnswersSolver<'a, Ans> {
256
236
dataclass_transform_metadata =
257
237
Some ( DataclassTransformKeywords :: from_type_map ( & call. keywords ) ) ;
258
238
}
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
- }
276
239
_ => { }
277
240
}
278
241
}
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
+ ) ;
279
248
let dataclass_metadata = self . dataclass_metadata (
280
249
cls,
281
250
& decorators,
@@ -504,6 +473,55 @@ impl<'a, Ans: LookupAnswer> AnswersSolver<'a, Ans> {
504
473
}
505
474
}
506
475
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
+
507
525
fn dataclass_metadata (
508
526
& self ,
509
527
cls : & Class ,
0 commit comments