@@ -125,19 +125,24 @@ class _LazyValue(Lazy):
125125 fixture and therefore can neither be parametrized nor depend on fixtures. It should have no mandatory argument.
126126 """
127127 if pytest53 :
128- __slots__ = 'valuegetter' , '_id' , '_marks'
128+ __slots__ = 'valuegetter' , '_id' , '_marks' , 'retrieved' , 'value'
129129 _field_names = __slots__
130130 else :
131- # we can not define __slots__ since we extend int,
131+ # we can not define __slots__ since we'll extend int in a subclass
132132 # see https://docs.python.org/3/reference/datamodel.html?highlight=__slots__#notes-on-using-slots
133- _field_names = 'valuegetter' , '_id' , '_marks'
133+ _field_names = 'valuegetter' , '_id' , '_marks' , 'retrieved' , 'value'
134134
135135 @classmethod
136136 def copy_from (cls ,
137137 obj # type: _LazyValue
138138 ):
139139 """Creates a copy of this _LazyValue"""
140- return cls (valuegetter = obj .valuegetter , id = obj ._id , marks = obj ._marks )
140+ new_obj = cls (valuegetter = obj .valuegetter , id = obj ._id , marks = obj ._marks )
141+ # make sure the copy will not need to retrieve the result if already done
142+ new_obj .retrieved = obj .retrieved
143+ if new_obj .retrieved :
144+ new_obj .value = obj .value
145+ return new_obj
141146
142147 # noinspection PyMissingConstructor
143148 def __init__ (self ,
@@ -151,6 +156,8 @@ def __init__(self,
151156 self ._marks = marks
152157 else :
153158 self ._marks = (marks , )
159+ self .retrieved = False
160+ self .value = None
154161
155162 def get_marks (self , as_decorators = False ):
156163 """
@@ -186,13 +193,24 @@ def get_id(self):
186193 return vg .__name__
187194
188195 def get (self ):
189- return self .valuegetter ()
196+ """ Call the underlying value getter, then return the result value (not self). With a cache mechanism """
197+ if not self .retrieved :
198+ # retrieve
199+ self .value = self .valuegetter ()
200+ self .retrieved = True
201+
202+ return self .value
190203
191204 def as_lazy_tuple (self , nb_params ):
192- return LazyTuple (self , nb_params )
205+ res = LazyTuple (self , nb_params )
206+ if self .retrieved :
207+ # make sure the tuple will not need to retrieve the result if already done
208+ res .retrieved = True
209+ res .value = self .value
210+ return res
193211
194212 def as_lazy_items_list (self , nb_params ):
195- return [v for v in LazyTuple ( self , nb_params )]
213+ return [v for v in self . as_lazy_tuple ( nb_params )]
196214
197215
198216class _LazyTupleItem (Lazy ):
@@ -203,7 +221,7 @@ class _LazyTupleItem(Lazy):
203221 __slots__ = 'host' , 'item'
204222 _field_names = __slots__
205223 else :
206- # we can not define __slots__ since we extend int,
224+ # we can not define __slots__ since we'll extend int in a subclass
207225 # see https://docs.python.org/3/reference/datamodel.html?highlight=__slots__#notes-on-using-slots
208226 _field_names = 'host' , 'item'
209227
@@ -258,6 +276,7 @@ def copy_from(cls,
258276 obj # type: LazyTuple
259277 ):
260278 new_obj = cls (valueref = obj .value , theoretical_size = obj .theoretical_size )
279+ # make sure the copy will not need to retrieve the result if already done
261280 new_obj .retrieved = obj .retrieved
262281 if new_obj .retrieved :
263282 new_obj .value = obj .value
@@ -281,7 +300,7 @@ def get_id(self):
281300 return self .valuegetter .get_id ()
282301
283302 def get (self ):
284- """ Call the underlying value getter, then return the tuple (not self) """
303+ """ Call the underlying value getter, then return the result tuple (not self). With a cache mechanism """
285304 if not self .retrieved :
286305 # retrieve
287306 self .value = self .valuegetter .get ()
0 commit comments