@@ -405,6 +405,64 @@ common mistakes like unintentionally passing in ``None``.
405
405
406
406
If in doubt, consider asking the library maintainers about their intent.
407
407
408
+ Common Patterns
409
+ ===============
410
+
411
+ .. _stub-patterns :
412
+
413
+ This section documents common patterns that are useful in stub files.
414
+
415
+ Overloads and Flags
416
+ -------------------
417
+
418
+ .. _overloads-and-flags :
419
+
420
+ Sometimes a function or method has a flag argument that changes the return type
421
+ or other accepted argument types. For example, take the following function::
422
+
423
+ def open(name: str, mode: Literal["r", "w"] = "r") -> Reader | Writer:
424
+ ...
425
+
426
+ We can express this case easily with two overloads::
427
+
428
+ @overload
429
+ def open(name: str, mode: Literal["r"] = "r") -> Reader: ...
430
+ @overload
431
+ def open(name: str, mode: Literal["w"]) -> Writer: ...
432
+
433
+ The first overload is picked when the mode is ``"r" `` or not given, and the
434
+ second overload is picked when the mode is ``"w" ``. But what if the first
435
+ argument is optional?
436
+
437
+ ::
438
+
439
+ def open(name: str | None = None, mode: Literal["r", "w"] = "r") -> Reader | Writer:
440
+ ...
441
+
442
+ Ideally we would be able to use the following overloads::
443
+
444
+ @overload
445
+ def open(name: str | None = None, mode: Literal["r"] = "r") -> Reader: ...
446
+ @overload
447
+ def open(name: str | None = None, mode: Literal["w"]) -> Writer: ...
448
+
449
+ And while the first overload is fine, the second is a syntax error in Python,
450
+ because non-default arguments cannot follow default arguments. To work around
451
+ this, we need an extra overload::
452
+
453
+ @overload
454
+ def open(name: str | None = None, mode: Literal["r"] = "r") -> Reader: ...
455
+ @overload
456
+ def open(name: str | None, mode: Literal["w"]) -> Writer: ...
457
+ @overload
458
+ def open(*, mode: Literal["w"]) -> Writer: ...
459
+
460
+ As before, the first overload is picked when the mode is ``"r" `` or not given.
461
+ Otherwise, the second overload is used when ``open `` is called with an explicit
462
+ ``name ``, e.g. ``open("file.txt", "w") `` or ``open(None, "w") ``. The third
463
+ overload is used when ``open `` is called without a name , e.g.
464
+ ``open(mode="w") ``.
465
+
408
466
Style Guide
409
467
===========
410
468
0 commit comments