@@ -93,7 +93,7 @@ struct PyStructSeqMeta {
9393}
9494
9595impl ItemMeta for PyStructSeqMeta {
96- const ALLOWED_NAMES : & ' static [ & ' static str ] = & [ "name" , "module" ] ;
96+ const ALLOWED_NAMES : & ' static [ & ' static str ] = & [ "name" , "module" , "try_from_object" ] ;
9797
9898 fn from_inner ( inner : ItemMetaInner ) -> Self {
9999 Self { inner }
@@ -155,6 +155,32 @@ impl PyStructSeqMeta {
155155 Ok ( None )
156156 }
157157 }
158+
159+ fn try_from_object ( & self ) -> Result < bool > {
160+ const KEY : & str = "try_from_object" ;
161+ let inner = self . inner ( ) ;
162+ if let Some ( ( _, meta) ) = inner. meta_map . get ( KEY ) {
163+ match meta {
164+ Meta :: NameValue ( syn:: MetaNameValue {
165+ value :
166+ syn:: Expr :: Lit ( syn:: ExprLit {
167+ lit : syn:: Lit :: Bool ( lit) ,
168+ ..
169+ } ) ,
170+ ..
171+ } ) => return Ok ( lit. value ( ) ) ,
172+ Meta :: Path ( _) => return Ok ( true ) , // #[pystructseq(try_from_object)] means true
173+ _ => { }
174+ }
175+ bail_span ! (
176+ inner. meta_ident,
177+ "#[pystructseq({KEY}=value)] expects a boolean value"
178+ )
179+ } else {
180+ // Default: true for backward compatibility
181+ Ok ( true )
182+ }
183+ }
158184}
159185
160186/// New attribute macro: #[pystructseq(name = "...", module = "...")]
@@ -164,11 +190,13 @@ pub(crate) fn impl_pystructseq(attr: PunctuatedNestedMeta, item: Item) -> Result
164190 } ;
165191
166192 let data_ident = struct_item. ident . clone ( ) ;
193+ let data_vis = struct_item. vis . clone ( ) ;
167194 let fake_ident = Ident :: new ( "pystructseq" , data_ident. span ( ) ) ;
168195 let meta = PyStructSeqMeta :: from_nested ( data_ident. clone ( ) , fake_ident, attr. into_iter ( ) ) ?;
169196
170197 let class_name = meta. class_name ( ) ?;
171198 let module_name = meta. module ( ) ?;
199+ let try_from_object = meta. try_from_object ( ) ?;
172200 let pytype_ident = derive_pytype_name ( & data_ident) ;
173201
174202 // Parse fields from struct
@@ -204,6 +232,28 @@ pub(crate) fn impl_pystructseq(attr: PunctuatedNestedMeta, item: Item) -> Result
204232 class_name. clone ( )
205233 } ;
206234
235+ // Generate TryFromObject impl if requested
236+ let try_from_object_impl = if try_from_object {
237+ quote ! {
238+ // TryFromObject for Data struct
239+ impl :: rustpython_vm:: TryFromObject for #data_ident {
240+ fn try_from_object( vm: & :: rustpython_vm:: VirtualMachine , seq: :: rustpython_vm:: PyObjectRef ) -> :: rustpython_vm:: PyResult <Self > {
241+ let seq = <#pytype_ident as :: rustpython_vm:: types:: PyStructSequence >:: try_elements_from( seq, vm) ?;
242+ let mut iter = seq. into_iter( ) ;
243+ Ok ( Self {
244+ #( #not_skipped_fields: iter. next( ) . unwrap( ) . clone( ) . try_into_value( vm) ?, ) *
245+ #( #skipped_fields: match iter. next( ) {
246+ Some ( v) => v. clone( ) . try_into_value( vm) ?,
247+ None => vm. ctx. none( ) ,
248+ } , ) *
249+ } )
250+ }
251+ }
252+ }
253+ } else {
254+ quote ! { }
255+ } ;
256+
207257 // Generate the output
208258 let output = quote ! {
209259 // Original Data struct (with #[pystruct] attrs removed from fields)
@@ -239,24 +289,11 @@ pub(crate) fn impl_pystructseq(attr: PunctuatedNestedMeta, item: Item) -> Result
239289 }
240290 }
241291
242- // TryFromObject for Data struct
243- impl :: rustpython_vm:: TryFromObject for #data_ident {
244- fn try_from_object( vm: & :: rustpython_vm:: VirtualMachine , seq: :: rustpython_vm:: PyObjectRef ) -> :: rustpython_vm:: PyResult <Self > {
245- let seq = <#pytype_ident as :: rustpython_vm:: types:: PyStructSequence >:: try_elements_from( seq, vm) ?;
246- let mut iter = seq. into_iter( ) ;
247- Ok ( Self {
248- #( #not_skipped_fields: iter. next( ) . unwrap( ) . clone( ) . try_into_value( vm) ?, ) *
249- #( #skipped_fields: match iter. next( ) {
250- Some ( v) => v. clone( ) . try_into_value( vm) ?,
251- None => vm. ctx. none( ) ,
252- } , ) *
253- } )
254- }
255- }
292+ #try_from_object_impl
256293
257294 // Empty Python type struct
258295 #[ doc( hidden) ]
259- pub struct #pytype_ident;
296+ #data_vis struct #pytype_ident;
260297
261298 // PyClassDef for Python type
262299 impl :: rustpython_vm:: class:: PyClassDef for #pytype_ident {
0 commit comments