New builtin types implementation 2026 - brython-dev/brython GitHub Wiki
This page describes the implementation of Python builtin types after a complete rewriting in 2026.
The Brython namespace is defined in the Javascript object __BRYTHON__, abbreviated as $B in Brython scripts.
Python builtins are defined in the attribute __BRYTHON__.builtins, abbreviated as _b_ in Brython scripts. For instance, the builtin type bytearray is stored as _b_.bytearray.
The builtin types are all initialized in script init_builtin_types.js before their features are defined in the rest of the scripts. This script itself is generated by the Python program scripts/get_info_from_cpython.py.
For instance, set is initialized as the Javascript object
{
tp_name: "set",
tp_flags: 4216066,
tp_base: _b_.object,
tp_doc: `Build an unordered collection of unique elements.`,
tp_bases: [_b_.object]
}The types that are available in Python builtins (such as object, int, etc.) are defined as attributes of _b_ (_b_.object, _b_.int...). The other builtin types such as the type of functions, generators, etc. are attributes of $B ($B.function, $B.generator, etc.)
As in CPython, builtin types have attributes of different kinds:
-
slots: the attributes defined for usual dunder methods; for instance, the slot for the dunder method
__new__istp_new. The dunder method exposed to Python programs is a wrapper around the slot. A complete list of type slots is available in the documentation -
methods: similar to regular methods in a user-defined class. For instance,
set.add()is implemented as a method - classmethods and staticmethods: same for classmethods and staticmethods
- members: for attributes that are not stored in the instance dictionary, but directly on the instance itself
- getset descriptors: for the attributes of instances of the type that are computed, set or deleted using a function
The features for a specific type are defined in a Brython script. For instance, type is defined in py_type.js, set in py_set.js, etc.
For a given type cls, the features are defined in different ways:
-
cls.ob_typeis the type ofcls(the result oftype(cls)in Python) - slots are implemented as attributes of
cls: for instance slottp_initis defined ascls.tp_init - methods, classmethods and staticmethods are defined as attributes of an object
cls.tp_funcs, aliased ascls_funcsin the scripts. For instance, methodint.to_bytes()is implemented asint_funcs.to_bytes(). The list of method names is stored in the attributescls.tp_methods,cls.classmethodsandcls.staticmethods - members are defined as a list
cls.tp_membersof 4-element lists, one for each member. For instance, the attributesnameandobjof anAttributeErrorinstance are defined by the list
_b_.AttributeError.tp_members = [
["name", $B.TYPES.OBJECT, "name", 0],
["obj", $B.TYPES.OBJECT, "obj", 0]
]- getset descriptors are implemented by 2 functions, one to get the attribute, one to set or delete it. For instance, the attribute
__defaults__of a function is obtained by function__defaults___get(obj)and can be set / deleted by__defaults___set(func, value). The list of getset descriptors is stored incls.tp_getset
When all built-in types have been defined, the script finalize_builtin_types.js scans all the builtin types. It creates a dictionary for each type, and sets its keys / values.
For instance, if a type cls has an attribute mp_length, it defines cls.dict['__len__'] as a specific object, an instance of the internal class $B.wrapper_descriptor, which references the underlying function cls.mp_length.
- when using Javascript BigInt inside a Python program, adding it to an integer or a number no longer raises TypeError
- as before, "safe integers" (< 2 ** 53 - 1) are implemented as JS objects of type "number", but non-safe integers are implemented as JS objects of type "bigint" instead of being wrapped inside a JS object
{class: $B.long_int, value: <bigint>}