Stub Function in Python

Stub Function in Python

Swaroop Kumar Yadav

What is Stub?

Stub files stored in the typeshed repository to determine the types of standard library and third-party library functions, classes, and other definitions. You can also create your own stubs that will be used to type check your code. The basic properties of stubs were introduced back in Library stubs and typeshed.


How to Create a Stub File?

Here is an overview of how to create a stub file:

• Write a stub file for the library (or an arbitrary module) and store it as a .pyi file in the same directory as the library module.

• Alternatively, put your stubs (.pyi files) in a directory reserved for stubs (e.g., myproject/stubs). For example:

Use the normal Python file name conventions for modules, e.g. csv.pyi for module csv. Use a subdirectory with __init__.pyi for packages. Note that PEP 561 stub-only packages must be installed.

If a directory contains both a .py and a .pyi file for the same module, the .pyi file takes precedence. This way you can easily add annotations for a module even if you don’t want to modify the source code. This can be useful, for example, if you use 3rd party open source libraries in your program (and there are no stubs in typeshed yet).

That’s it!


Stub File Syntax

Stub files are written in normal Python 3 syntax, but generally leaving out runtime logic like variable initializers, function bodies, and default arguments.

If it is not possible to completely leave out some piece of runtime logic, the recommended convention is to replace or elide them with ellipsis expressions (...). Each ellipsis below is literally written in the stub file as three dots:

# Variables with annotations do not need to be assigned a value.
# So by convention, we omit them in the stub file.
x: int

# Function bodies cannot be completely removed. By convention,
# we replace them with `...` instead of the `pass` statement.
def func_1(code: str) -> int: ...

# We can do the same with default arguments.
def func_2(a: int, b: int = ...) -> int: ...

Using Stub file syntax at runtime

You may also occasionally need to elide actual logic in regular Python code – for example, when writing methods in overload variants or custom protocols.

The recommended style is to use ellipses to do so, just like in stub files. It is also considered stylistically acceptable to throw a NotImplementedError in cases where the user of the code may accidentally call functions with no actual logic.

You can also elide default arguments as long as the function body also contains no runtime logic: the function body only contains a single ellipsis, the pass statement, or a raise NotImplementedError(). It is also acceptable for the function body to contain a docstring. For example:

from typing_extensions import Protocol

class Resource(Protocol):
def ok_1(self, foo: list[str] = ...) -> None: ...

def ok_2(self, foo: list[str] = ...) -> None:
raise NotImplementedError()

def ok_3(self, foo: list[str] = ...) -> None:
"""Some docstring"""
pass

# Error: Incompatible default for argument "foo" (default has
# type "ellipsis", argument has type "list[str]")
def not_ok(self, foo: list[str] = ...) -> None:
print(foo)

How to Create Stub File in Python using PyCharm ?


Answer this Quiz


Report Page