@@ -107,6 +107,9 @@ def delete_func(self):
107107 # define as needed in the child protocol classes
108108 #t.__pprint_funcs__ = {} - disabled here to keep the base class lightweight
109109
110+ # placeholder for __public_fields__, a class attribute used in __repr__ and pprint()
111+ t .__public_fields__ = None
112+
110113 return t
111114
112115
@@ -138,7 +141,6 @@ class Packet(_MetaPacket("Temp", (object,), {})):
138141 >>> Foo('hello, world!')
139142 Foo(baz=' wor', foo=1751477356L, bar=28460, data='ld!')
140143 """
141-
142144 def __init__ (self , * args , ** kwargs ):
143145 """Packet constructor with ([buf], [field=val,...]) prototype.
144146
@@ -169,9 +171,31 @@ def __init__(self, *args, **kwargs):
169171 if hasattr (self , '__hdr_fmt__' ):
170172 self ._pack_hdr = partial (struct .pack , self .__hdr_fmt__ )
171173
172- # construct __public_fields__ to be used inside __repr__ and pprint
173- # once auto-formed here in __init__, the list can be customized in
174- # child classes to include or remove fields to display, as needed
174+ def __len__ (self ):
175+ return self .__hdr_len__ + len (self .data )
176+
177+ # legacy
178+ def __iter__ (self ):
179+ return iter ((fld , getattr (self , fld )) for fld in self .__class__ .__hdr_fields__ )
180+
181+ def __getitem__ (self , kls ):
182+ """Return the 1st occurence of the underlying <kls> data layer, raise KeyError otherwise."""
183+ dd = self .data
184+ while isinstance (dd , Packet ):
185+ if dd .__class__ == kls :
186+ return dd
187+ dd = dd .data
188+ raise KeyError (kls )
189+
190+ def __contains__ (self , kls ):
191+ """Return True is the given <kls> data layer is present in the stack."""
192+ try :
193+ return bool (self .__getitem__ (kls ))
194+ except KeyError :
195+ return False
196+
197+ def _create_public_fields (self ):
198+ """Construct __public_fields__ to be used inside __repr__ and pprint"""
175199 l_ = []
176200 for field_name , _ , _ in getattr (self , '__hdr__' , []):
177201 # public fields defined in __hdr__; "public" means not starting with an underscore
@@ -202,32 +226,12 @@ def __init__(self, *args, **kwargs):
202226
203227 # check for duplicates, there shouldn't be any
204228 assert len (l_ ) == len (set (l_ ))
205- self .__public_fields__ = l_
206-
207- def __len__ (self ):
208- return self .__hdr_len__ + len (self .data )
209-
210- # legacy
211- def __iter__ (self ):
212- return iter ((fld , getattr (self , fld )) for fld in self .__class__ .__hdr_fields__ )
213-
214- def __getitem__ (self , kls ):
215- """Return the 1st occurence of the underlying <kls> data layer, raise KeyError otherwise."""
216- dd = self .data
217- while isinstance (dd , Packet ):
218- if dd .__class__ == kls :
219- return dd
220- dd = dd .data
221- raise KeyError (kls )
222-
223- def __contains__ (self , kls ):
224- """Return True is the given <kls> data layer is present in the stack."""
225- try :
226- return bool (self .__getitem__ (kls ))
227- except KeyError :
228- return False
229+ self .__class__ .__public_fields__ = l_ # store it in the class attribute
229230
230231 def __repr__ (self ):
232+ if self .__public_fields__ is None :
233+ self ._create_public_fields ()
234+
231235 # Collect and display protocol fields in order:
232236 # 1. public fields defined in __hdr__, unless their value is default
233237 # 2. properties derived from _private fields defined in __hdr__ and __bit_fields__
@@ -236,7 +240,7 @@ def __repr__(self):
236240 l_ = []
237241
238242 # (1) and (2) are done via __public_fields__; just filter out defaults here
239- for field_name in getattr ( self , ' __public_fields__' , []) :
243+ for field_name in self . __public_fields__ :
240244 field_value = getattr (self , field_name )
241245
242246 if (hasattr (self , '__hdr_defaults__' ) and
@@ -264,6 +268,9 @@ def __repr__(self):
264268
265269 def pprint (self , indent = 1 ):
266270 """Human friendly pretty-print."""
271+ if self .__public_fields__ is None :
272+ self ._create_public_fields ()
273+
267274 l_ = []
268275
269276 def add_field (fn , fv ):
@@ -273,7 +280,7 @@ def add_field(fn, fv):
273280 except (AttributeError , KeyError ):
274281 l_ .append ('%s=%r,' % (fn , fv ))
275282
276- for field_name in getattr ( self , ' __public_fields__' , []) :
283+ for field_name in self . __public_fields__ :
277284 add_field (field_name , getattr (self , field_name ))
278285
279286 for attr_name , attr_value in iteritems (self .__dict__ ):
0 commit comments