@@ -93,6 +93,36 @@ class InOrder:
9393
9494 """
9595
96+ def __init__ (self , * objects : object ) -> None :
97+ self ._core = InOrderImpl (* objects )
98+
99+ def verify (
100+ self ,
101+ obj : object ,
102+ times = None ,
103+ atleast = None ,
104+ atmost = None ,
105+ between = None ,
106+ ):
107+ return self ._core .verify (
108+ obj ,
109+ times = times ,
110+ atleast = atleast ,
111+ atmost = atmost ,
112+ between = between ,
113+ )
114+
115+ def __enter__ (self ):
116+ self ._core .__enter__ ()
117+ return self
118+
119+ def __exit__ (self , exc_type , exc_val , exc_tb ):
120+ self ._core .__exit__ (exc_type , exc_val , exc_tb )
121+
122+
123+ class InOrderImpl :
124+ """Internal implementation behind the public `InOrder` facade."""
125+
96126
97127 def __init__ (self , * objects : object ):
98128 objects_ : list [object ] = []
@@ -221,11 +251,12 @@ def _guess_object_labels_from_callsite(self, count: int) -> list[str | None]:
221251 return [None ]
222252
223253 frame = inspect .currentframe ()
224- caller_frame = (
225- frame .f_back .f_back
226- if frame and frame .f_back and frame .f_back .f_back
227- else None
228- )
254+ # Start at the direct caller and then walk out of our own module.
255+ # This is important because public `InOrder` delegates to `InOrderImpl`,
256+ # so the first stack frames are internal wrappers.
257+ caller_frame = frame .f_back if frame else None
258+ while caller_frame and caller_frame .f_code .co_filename == __file__ :
259+ caller_frame = caller_frame .f_back
229260
230261 if caller_frame is None :
231262 return [None ] * count
@@ -292,7 +323,7 @@ def _is_inorder_constructor_call(self, node: ast.Call) -> bool:
292323
293324
294325class InOrderVerifiableInvocation (VerifiableInvocation ):
295- def __init__ (self , mock , method_name , verification , inorder : InOrder ):
326+ def __init__ (self , mock , method_name , verification , inorder : InOrderImpl ):
296327 super ().__init__ (mock , method_name , verification )
297328 self ._inorder = inorder
298329
0 commit comments