"""Interface to numpy arrays"""fromtypingimportAny,Literal,UnionfrompydanticimportSerializationInfofromnumpydantic.interface.interfaceimportInterface,JsonDicttry:importnumpyasnpfromnumpyimportndarrayENABLED=TrueexceptImportError:# pragma: no coverENABLED=Falsendarray=Nonenp=None
[docs]classNumpyJsonDict(JsonDict):""" JSON-able roundtrip representation of numpy array """type:Literal["numpy"]dtype:strvalue:list
[docs]defto_array_input(self)->ndarray:""" Construct a numpy array """returnnp.array(self.value,dtype=self.dtype)
[docs]classNumpyInterface(Interface):""" Numpy :class:`~numpy.ndarray` s! """name="numpy"input_types=(ndarray,list)return_type=ndarrayjson_model=NumpyJsonDictpriority=-999""" The numpy interface is usually the interface of last resort. We want to use any more specific interface that we might have, because the numpy interface checks for anything that could be coerced to a numpy array (see :meth:`.NumpyInterface.check` ) """
[docs]@classmethoddefcheck(cls,array:Any)->bool:""" Check that this is in fact a numpy ndarray or something that can be coerced to one """ifisinstance(array,ndarray):returnTrueelifisinstance(array,dict):returnNumpyJsonDict.is_valid(array)else:try:_=np.array(array)returnTrueexceptException:returnFalse
[docs]defbefore_validation(self,array:Any)->ndarray:""" Coerce to an ndarray. We have already checked if coercion is possible in :meth:`.check` """ifnotisinstance(array,ndarray):array=np.array(array)returnarray
[docs]@classmethoddefenabled(cls)->bool:"""Check that numpy is present in the environment"""returnENABLED
[docs]@classmethoddefto_json(cls,array:ndarray,info:SerializationInfo=None)->Union[list,JsonDict]:""" Convert an array of :attr:`.return_type` to a JSON-compatible format using base python types """ifnotisinstance(array,np.ndarray):# pragma: no coverarray=np.array(array)json_array=array.tolist()ifinfo.round_trip:json_array=NumpyJsonDict(type=cls.name,dtype=str(array.dtype),value=json_array)returnjson_array