File tree 4 files changed +37
-2
lines changed
Filter options
4 files changed +37
-2
lines changed
Original file line number Diff line number Diff line change @@ -2345,11 +2345,25 @@ Functions and decorators
2345
2345
case _ as unreachable:
2346
2346
assert_never(unreachable)
2347
2347
2348
+ Here, the annotations allow the type checker to infer that the
2349
+ last case can never execute, because ``arg `` is either
2350
+ an :class: `int ` or a :class: `str `, and both options are covered by
2351
+ earlier cases.
2348
2352
If a type checker finds that a call to ``assert_never() `` is
2349
- reachable, it will emit an error.
2353
+ reachable, it will emit an error. For example, if the type annotation
2354
+ for ``arg `` was instead ``int | str | float ``, the type checker would
2355
+ emit an error pointing out that ``unreachable `` is of type :class: `float `.
2356
+ For a call to ``assert_never `` to succeed, the inferred type of
2357
+ the argument passed in must be the bottom type, :data: `Never `, and nothing
2358
+ else.
2350
2359
2351
2360
At runtime, this throws an exception when called.
2352
2361
2362
+ .. seealso ::
2363
+ `Unreachable Code and Exhaustiveness Checking
2364
+ <https://typing.readthedocs.io/en/latest/source/unreachable.html>_ ` has more
2365
+ information about exhaustiveness checking with static typing.
2366
+
2353
2367
.. versionadded :: 3.11
2354
2368
2355
2369
.. function :: reveal_type(obj)
Original file line number Diff line number Diff line change @@ -223,6 +223,19 @@ def test_exception(self):
223
223
with self .assertRaises (AssertionError ):
224
224
assert_never (None )
225
225
226
+ value = "some value"
227
+ with self .assertRaisesRegex (AssertionError , value ):
228
+ assert_never (value )
229
+
230
+ # Make sure a huge value doesn't get printed in its entirety
231
+ huge_value = "a" * 10000
232
+ with self .assertRaises (AssertionError ) as cm :
233
+ assert_never (huge_value )
234
+ self .assertLess (
235
+ len (cm .exception .args [0 ]),
236
+ typing ._ASSERT_NEVER_REPR_MAX_LENGTH * 2 ,
237
+ )
238
+
226
239
227
240
class SelfTests (BaseTestCase ):
228
241
def test_equality (self ):
Original file line number Diff line number Diff line change @@ -2382,6 +2382,9 @@ class Film(TypedDict):
2382
2382
return isinstance (tp , _TypedDictMeta )
2383
2383
2384
2384
2385
+ _ASSERT_NEVER_REPR_MAX_LENGTH = 100
2386
+
2387
+
2385
2388
def assert_never (arg : Never , / ) -> Never :
2386
2389
"""Statically assert that a line of code is unreachable.
2387
2390
@@ -2402,7 +2405,10 @@ def int_or_str(arg: int | str) -> None:
2402
2405
At runtime, this throws an exception when called.
2403
2406
2404
2407
"""
2405
- raise AssertionError ("Expected code to be unreachable" )
2408
+ value = repr (arg )
2409
+ if len (value ) > _ASSERT_NEVER_REPR_MAX_LENGTH :
2410
+ value = value [:_ASSERT_NEVER_REPR_MAX_LENGTH ] + '...'
2411
+ raise AssertionError (f"Expected code to be unreachable, but got: { value } " )
2406
2412
2407
2413
2408
2414
def no_type_check (arg ):
Original file line number Diff line number Diff line change
1
+ Include the passed value in the exception thrown by
2
+ :func: `typing.assert_never `. Patch by Jelle Zijlstra.
You can’t perform that action at this time.
0 commit comments