@@ -330,7 +330,9 @@ pub fn impl_py_method_def(
330
330
} ;
331
331
let methoddef = spec. get_methoddef ( quote ! { #cls:: #wrapper_ident } , doc, ctx) ;
332
332
let method_def = quote ! {
333
- #pyo3_path:: class:: PyMethodDefType :: #methoddef_type( #methoddef #add_flags)
333
+ #pyo3_path:: impl_:: pyclass:: MaybeRuntimePyMethodDef :: Static (
334
+ #pyo3_path:: class:: PyMethodDefType :: #methoddef_type( #methoddef #add_flags)
335
+ )
334
336
} ;
335
337
Ok ( MethodAndMethodDef {
336
338
associated_method,
@@ -511,12 +513,14 @@ fn impl_py_class_attribute(
511
513
} ;
512
514
513
515
let method_def = quote ! {
514
- #pyo3_path:: class:: PyMethodDefType :: ClassAttribute ( {
515
- #pyo3_path:: class:: PyClassAttributeDef :: new(
516
- #python_name,
517
- #cls:: #wrapper_ident
518
- )
519
- } )
516
+ #pyo3_path:: impl_:: pyclass:: MaybeRuntimePyMethodDef :: Static (
517
+ #pyo3_path:: class:: PyMethodDefType :: ClassAttribute ( {
518
+ #pyo3_path:: class:: PyClassAttributeDef :: new(
519
+ #python_name,
520
+ #cls:: #wrapper_ident
521
+ )
522
+ } )
523
+ )
520
524
} ;
521
525
522
526
Ok ( MethodAndMethodDef {
@@ -701,11 +705,13 @@ pub fn impl_py_setter_def(
701
705
702
706
let method_def = quote ! {
703
707
#cfg_attrs
704
- #pyo3_path:: class:: PyMethodDefType :: Setter (
705
- #pyo3_path:: class:: PySetterDef :: new(
706
- #python_name,
707
- #cls:: #wrapper_ident,
708
- #doc
708
+ #pyo3_path:: impl_:: pyclass:: MaybeRuntimePyMethodDef :: Static (
709
+ #pyo3_path:: class:: PyMethodDefType :: Setter (
710
+ #pyo3_path:: class:: PySetterDef :: new(
711
+ #python_name,
712
+ #cls:: #wrapper_ident,
713
+ #doc
714
+ )
709
715
)
710
716
)
711
717
} ;
@@ -750,102 +756,107 @@ pub fn impl_py_getter_def(
750
756
let python_name = property_type. null_terminated_python_name ( ctx) ?;
751
757
let doc = property_type. doc ( ctx) ;
752
758
759
+ let mut cfg_attrs = TokenStream :: new ( ) ;
760
+ if let PropertyType :: Descriptor { field, .. } = & property_type {
761
+ for attr in field
762
+ . attrs
763
+ . iter ( )
764
+ . filter ( |attr| attr. path ( ) . is_ident ( "cfg" ) )
765
+ {
766
+ attr. to_tokens ( & mut cfg_attrs) ;
767
+ }
768
+ }
769
+
753
770
let mut holders = Holders :: new ( ) ;
754
- let body = match property_type {
771
+ match property_type {
755
772
PropertyType :: Descriptor {
756
773
field_index, field, ..
757
774
} => {
758
- let slf = SelfType :: Receiver {
759
- mutable : false ,
760
- span : Span :: call_site ( ) ,
761
- }
762
- . receiver ( cls, ExtractErrorMode :: Raise , & mut holders, ctx) ;
763
- let field_token = if let Some ( ident) = & field. ident {
764
- // named struct field
775
+ let ty = & field. ty ;
776
+ let field = if let Some ( ident) = & field. ident {
765
777
ident. to_token_stream ( )
766
778
} else {
767
- // tuple struct field
768
779
syn:: Index :: from ( field_index) . to_token_stream ( )
769
780
} ;
770
- quotes:: map_result_into_ptr (
771
- quotes:: ok_wrap (
772
- quote ! {
773
- :: std:: clone:: Clone :: clone( & ( #slf. #field_token) )
774
- } ,
775
- ctx,
776
- ) ,
777
- ctx,
778
- )
781
+
782
+ // TODO: on MSRV 1.77+, we can use `::std::mem::offset_of!` here, and it should
783
+ // make it possible for the `MaybeRuntimePyMethodDef` to be a `Static` variant.
784
+ let method_def = quote_spanned ! { ty. span( ) =>
785
+ #cfg_attrs
786
+ {
787
+ #[ allow( unused_imports) ] // might not be used if all probes are positve
788
+ use #pyo3_path:: impl_:: pyclass:: Probe ;
789
+
790
+ struct Offset ;
791
+ unsafe impl #pyo3_path:: impl_:: pyclass:: OffsetCalculator <#cls, #ty> for Offset {
792
+ fn offset( ) -> usize {
793
+ #pyo3_path:: impl_:: pyclass:: class_offset:: <#cls>( ) +
794
+ #pyo3_path:: impl_:: pyclass:: offset_of!( #cls, #field)
795
+ }
796
+ }
797
+
798
+ const GENERATOR : #pyo3_path:: impl_:: pyclass:: PyClassGetterGenerator :: <
799
+ #cls,
800
+ #ty,
801
+ Offset ,
802
+ { #pyo3_path:: impl_:: pyclass:: IsPyT :: <#ty>:: VALUE } ,
803
+ { #pyo3_path:: impl_:: pyclass:: IsToPyObject :: <#ty>:: VALUE } ,
804
+ > = unsafe { #pyo3_path:: impl_:: pyclass:: PyClassGetterGenerator :: new( ) } ;
805
+ #pyo3_path:: impl_:: pyclass:: MaybeRuntimePyMethodDef :: Runtime (
806
+ || GENERATOR . generate( #python_name, #doc)
807
+ )
808
+ }
809
+ } ;
810
+
811
+ Ok ( MethodAndMethodDef {
812
+ associated_method : quote ! { } ,
813
+ method_def,
814
+ } )
779
815
}
780
816
// Forward to `IntoPyCallbackOutput`, to handle `#[getter]`s returning results.
781
817
PropertyType :: Function {
782
818
spec, self_type, ..
783
819
} => {
820
+ let wrapper_ident = format_ident ! ( "__pymethod_get_{}__" , spec. name) ;
784
821
let call = impl_call_getter ( cls, spec, self_type, & mut holders, ctx) ?;
785
- quote ! {
822
+ let body = quote ! {
786
823
#pyo3_path:: callback:: convert( py, #call)
787
- }
788
- }
789
- } ;
824
+ } ;
790
825
791
- let wrapper_ident = match property_type {
792
- PropertyType :: Descriptor {
793
- field : syn:: Field {
794
- ident : Some ( ident) , ..
795
- } ,
796
- ..
797
- } => {
798
- format_ident ! ( "__pymethod_get_{}__" , ident)
799
- }
800
- PropertyType :: Descriptor { field_index, .. } => {
801
- format_ident ! ( "__pymethod_get_field_{}__" , field_index)
802
- }
803
- PropertyType :: Function { spec, .. } => {
804
- format_ident ! ( "__pymethod_get_{}__" , spec. name)
805
- }
806
- } ;
826
+ let init_holders = holders. init_holders ( ctx) ;
827
+ let check_gil_refs = holders. check_gil_refs ( ) ;
828
+ let associated_method = quote ! {
829
+ #cfg_attrs
830
+ unsafe fn #wrapper_ident(
831
+ py: #pyo3_path:: Python <' _>,
832
+ _slf: * mut #pyo3_path:: ffi:: PyObject
833
+ ) -> #pyo3_path:: PyResult <* mut #pyo3_path:: ffi:: PyObject > {
834
+ #init_holders
835
+ let result = #body;
836
+ #check_gil_refs
837
+ result
838
+ }
839
+ } ;
807
840
808
- let mut cfg_attrs = TokenStream :: new ( ) ;
809
- if let PropertyType :: Descriptor { field, .. } = & property_type {
810
- for attr in field
811
- . attrs
812
- . iter ( )
813
- . filter ( |attr| attr. path ( ) . is_ident ( "cfg" ) )
814
- {
815
- attr. to_tokens ( & mut cfg_attrs) ;
816
- }
817
- }
841
+ let method_def = quote ! {
842
+ #cfg_attrs
843
+ #pyo3_path:: impl_:: pyclass:: MaybeRuntimePyMethodDef :: Static (
844
+ #pyo3_path:: class:: PyMethodDefType :: Getter (
845
+ #pyo3_path:: class:: PyGetterDef :: new(
846
+ #python_name,
847
+ #cls:: #wrapper_ident,
848
+ #doc
849
+ )
850
+ )
851
+ )
852
+ } ;
818
853
819
- let init_holders = holders. init_holders ( ctx) ;
820
- let check_gil_refs = holders. check_gil_refs ( ) ;
821
- let associated_method = quote ! {
822
- #cfg_attrs
823
- unsafe fn #wrapper_ident(
824
- py: #pyo3_path:: Python <' _>,
825
- _slf: * mut #pyo3_path:: ffi:: PyObject
826
- ) -> #pyo3_path:: PyResult <* mut #pyo3_path:: ffi:: PyObject > {
827
- #init_holders
828
- let result = #body;
829
- #check_gil_refs
830
- result
854
+ Ok ( MethodAndMethodDef {
855
+ associated_method,
856
+ method_def,
857
+ } )
831
858
}
832
- } ;
833
-
834
- let method_def = quote ! {
835
- #cfg_attrs
836
- #pyo3_path:: class:: PyMethodDefType :: Getter (
837
- #pyo3_path:: class:: PyGetterDef :: new(
838
- #python_name,
839
- #cls:: #wrapper_ident,
840
- #doc
841
- )
842
- )
843
- } ;
844
-
845
- Ok ( MethodAndMethodDef {
846
- associated_method,
847
- method_def,
848
- } )
859
+ }
849
860
}
850
861
851
862
/// Split an argument of pyo3::Python from the front of the arg list, if present
0 commit comments