@@ -185,9 +185,17 @@ def same(a: Any, b: Any) -> bool:
185185 return type (a ) is type (b ) and a == b
186186
187187
188+ # An expected value meaning the key must not be there at all (suite 1.17).
189+ ABSENT = {"$absent" : True }
190+
191+
188192def match (expected : Any , actual : Any , path : str ) -> None :
189193 if isinstance (expected , dict ) and isinstance (actual , dict ) and not is_pattern (expected ):
190194 for k , v in expected .items ():
195+ if v == ABSENT :
196+ if k in actual :
197+ raise Fail ("%s.%s: expected no such key, got %s" % (path , k , short (actual [k ])))
198+ continue
191199 if k not in actual :
192200 raise Fail ("%s.%s: missing (expected %s)" % (path , k , short (v )))
193201 if k in EXACT :
@@ -202,6 +210,14 @@ def match(expected: Any, actual: Any, path: str) -> None:
202210 raise Fail ("%s: expected %s, got %s" % (path , short (expected ), short (actual )))
203211
204212
213+ def match_batch (expected : Any , batch : Any , path : str ) -> None :
214+ """A batch compares as sent; a key expected absent is neither sent nor a field of Batch."""
215+ match (expected , batch .raw , path )
216+ for k , v in expected .items () if isinstance (expected , dict ) else ():
217+ if v == ABSENT and hasattr (batch , k ):
218+ raise Fail ("%s.%s: expected no such field on Batch, got %s" % (path , k , short (getattr (batch , k ))))
219+
220+
205221def pointer (doc : Any , ptr : str ) -> Tuple [bool , Any ]:
206222 cur = doc
207223 for raw in ptr [1 :].split ("/" ) if ptr else []:
@@ -761,7 +777,7 @@ def check_outcome(spec: Dict[str, Any], result: Any, path: str) -> None:
761777 elif kind == "batch" :
762778 if not isinstance (result , dn .Batch ):
763779 raise Fail ("%s: expected a Batch, got %r" % (path , result ))
764- match (spec .get ("batch" , {}), result . raw , path + ".batch" )
780+ match_batch (spec .get ("batch" , {}), result , path + ".batch" )
765781 elif kind == "batch_page" :
766782 if not isinstance (result , dn .BatchPage ):
767783 raise Fail ("%s: expected a BatchPage, got %r" % (path , result ))
@@ -771,7 +787,7 @@ def check_outcome(spec: Dict[str, Any], result: Any, path: str) -> None:
771787 elif kind == "batch_run" :
772788 if not isinstance (result , dn .BatchRun ):
773789 raise Fail ("%s: expected a BatchRun, got %r" % (path , result ))
774- match (spec .get ("batch" , {}), result .batch . raw , path + ".batch" )
790+ match_batch (spec .get ("batch" , {}), result .batch , path + ".batch" )
775791 check_results_spec (spec , result .results , path )
776792 elif kind in COLLECTION_KINDS :
777793 check_collection_result (kind , spec .get (kind , {}), result , path + "." + kind )
@@ -1068,7 +1084,7 @@ async def run_response(case: Dict[str, Any], mock: Mock, mode: str, env: pytest.
10681084 raise Fail ("raw: expected %s, got %s" % (short (exp ["raw" ]), short (result )))
10691085 elif "batch" in exp :
10701086 assert isinstance (result , dn .Batch )
1071- match (exp ["batch" ], result . raw , "batch" )
1087+ match_batch (exp ["batch" ], result , "batch" )
10721088 elif "batch_page" in exp :
10731089 assert isinstance (result , dn .BatchPage )
10741090 match (exp ["batch_page" ], result .raw , "batch_page" )
0 commit comments