Description
This RFC is intended to supersede #635, #636, #637, and #638, based on initial consortium feedback, and proposes to consolidate inspection APIs into a single non-public namespace.
Proposal
info = xp.__array_namespace_info__()
Returns a namespace with Array API namespace inspection utilities.
Note: the x.__array_namespace__()
API supports a version
kwarg. We don't follow suit here, as we assume backward compatibility, whereby a consumer may ask for a particular version of the array API standard and a conforming library may return a newer version. That version should still be compliant with the older specified version (backward compat guarantee), and thus, the inspection API return values should still be applicable. Stated more succinctly: conforming array libraries are expected to be "evergreen" and only have a single Array API implementation, not separate implementations for each revision of the standard.
Methods
info.capabilities() -> dict[str,bool]
info.capabilities() -> dict[str,bool]
Returns a dictionary of static "capabilities", such as whether a conforming library supports boolean indexing or data-dependent output shapes.
Key values should be either False
(does not support) or True
(does support). For example,
{
'boolean_indexing': False | True,
'data_dependent_shapes': False | True
}
info.default_device() -> device
info.default_device()
Returns an object for the default device.
info.default_dtypes( /, *, device: device) -> dict[str, dtype]
info.default_dtypes() -> dict[str, dtype]
info.default_dtypes(device: device) -> dict[str, dtype]
Returns a dictionary having the following keys:
- real floating: default real floating-point dtype.
- complex floating: default complex floating-point dtype.
- integral: default integral dtype.
- indexing: default index dtype.
>>> info.default_dtypes()
{
'real floating': <dtype>,
'complex floating': <dtype>,
'integral': <dtype>,
'indexing': <dtype>
}
>>> info.default_dtypes(device=<device>)
{
'real floating': <dtype>,
'complex floating': <dtype>,
'integral': <dtype>,
'indexing': <dtype>
}
More keys could be added in the future, depending on evolution of the standard.
If not provided a device
argument, the function would return a dictionary based on the current device (context). If provided a device
argument, the function would return a dictionary as described above, but specific to the specified device.
info.dtypes( /, *, device: device, kind: Union[str, Tuple[str, ...]]) -> dict[str,dtype]
info.dtypes() -> dict[str,dtype]
info.dtypes(device: device) -> dict[str,dtype]
info.dtypes(kind: Union[dtype, str, Tuple[Union[dtype, str], ...]]) -> dict[str,dtype]
info.dtypes(kind: Union[dtype, str, Tuple[Union[dtype, str], ...]], device: device) -> dict[str,dtype]
Returns a dictionary of supported Array API data types (in canonical form; e.g., float64
, float32
, int32
, etc).
>>> info.dtypes()
{"float64": xp.float64, "float32": xp.float32, "int32": xp.int32, ...}
Similar to the isdtype
API, the function would support a "kind" kwarg for returning a dictionary of supported Array API data types belonging to the specified kind. The following kinds should be supported, matching the isdtype
API:
'bool'
: boolean data types (e.g., bool).'signed integer'
: signed integer data types (e.g., int8, int16, int32, int64).'unsigned integer'
: unsigned integer data types (e.g., uint8, uint16, uint32, uint64).'integral'
: integer data types. Shorthand for ('signed integer', 'unsigned integer').'real floating'
: real-valued floating-point data types (e.g., float32, float64).'complex floating'
: complex floating-point data types (e.g., complex64, complex128).'numeric'
: numeric data types. Shorthand for ('integral', 'real floating', 'complex floating').
>>> info.dtypes(kind="real floating")
{"float64": xp.float64, "float32": xp.float32}
If not provided a device
argument, the function should return a dictionary of supported data types for the current device (context). If provided a device
argument, the function should return a dictionary of supported data types for the specified device.
>>> info.dtypes(device=<device>)
{"float32": xp.float32, "int32": xp.int32, "int8": xp.int8, "uint8": xp.uint8, ...}
>>> info.dtypes(kind="real floating", device=<device>)
{"float32": xp.float32}
Note: a hasattr
check is not sufficient as a means of determining dtype support, as dtype support can vary depending on the device. A conforming array library may be fully compliant for its default device, but unable to be fully compliant on other supported devices. In which case, simply checking whether a dtype
object exists in the main namespace is insufficient to determine whether a downstream consumer can actually use a specific dtype
object for a particular device/execution context.
info.devices()
info.devices() -> List[device]
Returns a list of supported devices.