rustpython_vm/builtins/
singletons.rs

1use super::{PyStrRef, PyType, PyTypeRef};
2use crate::{
3    class::PyClassImpl,
4    convert::ToPyObject,
5    protocol::PyNumberMethods,
6    types::{AsNumber, Constructor, Representable},
7    Context, Py, PyObjectRef, PyPayload, PyResult, VirtualMachine,
8};
9
10#[pyclass(module = false, name = "NoneType")]
11#[derive(Debug)]
12pub struct PyNone;
13
14impl PyPayload for PyNone {
15    fn class(ctx: &Context) -> &'static Py<PyType> {
16        ctx.types.none_type
17    }
18}
19
20// This allows a built-in function to not return a value, mapping to
21// Python's behavior of returning `None` in this situation.
22impl ToPyObject for () {
23    fn to_pyobject(self, vm: &VirtualMachine) -> PyObjectRef {
24        vm.ctx.none()
25    }
26}
27
28impl<T: ToPyObject> ToPyObject for Option<T> {
29    fn to_pyobject(self, vm: &VirtualMachine) -> PyObjectRef {
30        match self {
31            Some(x) => x.to_pyobject(vm),
32            None => vm.ctx.none(),
33        }
34    }
35}
36
37impl Constructor for PyNone {
38    type Args = ();
39
40    fn py_new(_: PyTypeRef, _args: Self::Args, vm: &VirtualMachine) -> PyResult {
41        Ok(vm.ctx.none.clone().into())
42    }
43}
44
45#[pyclass(with(Constructor, AsNumber, Representable))]
46impl PyNone {
47    #[pymethod(magic)]
48    fn bool(&self) -> bool {
49        false
50    }
51}
52
53impl Representable for PyNone {
54    #[inline]
55    fn repr(_zelf: &Py<Self>, vm: &VirtualMachine) -> PyResult<PyStrRef> {
56        Ok(vm.ctx.names.None.to_owned())
57    }
58
59    #[cold]
60    fn repr_str(_zelf: &Py<Self>, _vm: &VirtualMachine) -> PyResult<String> {
61        unreachable!("use repr instead")
62    }
63}
64
65impl AsNumber for PyNone {
66    fn as_number() -> &'static PyNumberMethods {
67        static AS_NUMBER: PyNumberMethods = PyNumberMethods {
68            boolean: Some(|_number, _vm| Ok(false)),
69            ..PyNumberMethods::NOT_IMPLEMENTED
70        };
71        &AS_NUMBER
72    }
73}
74
75#[pyclass(module = false, name = "NotImplementedType")]
76#[derive(Debug)]
77pub struct PyNotImplemented;
78
79impl PyPayload for PyNotImplemented {
80    fn class(ctx: &Context) -> &'static Py<PyType> {
81        ctx.types.not_implemented_type
82    }
83}
84
85impl Constructor for PyNotImplemented {
86    type Args = ();
87
88    fn py_new(_: PyTypeRef, _args: Self::Args, vm: &VirtualMachine) -> PyResult {
89        Ok(vm.ctx.not_implemented.clone().into())
90    }
91}
92
93#[pyclass(with(Constructor))]
94impl PyNotImplemented {
95    // TODO: As per https://bugs.python.org/issue35712, using NotImplemented
96    // in boolean contexts will need to raise a DeprecationWarning in 3.9
97    // and, eventually, a TypeError.
98    #[pymethod(magic)]
99    fn bool(&self) -> bool {
100        true
101    }
102
103    #[pymethod(magic)]
104    fn reduce(&self, vm: &VirtualMachine) -> PyStrRef {
105        vm.ctx.names.NotImplemented.to_owned()
106    }
107}
108
109impl Representable for PyNotImplemented {
110    #[inline]
111    fn repr(_zelf: &Py<Self>, vm: &VirtualMachine) -> PyResult<PyStrRef> {
112        Ok(vm.ctx.names.NotImplemented.to_owned())
113    }
114
115    #[cold]
116    fn repr_str(_zelf: &Py<Self>, _vm: &VirtualMachine) -> PyResult<String> {
117        unreachable!("use repr instead")
118    }
119}
120
121pub fn init(context: &Context) {
122    PyNone::extend_class(context, context.types.none_type);
123    PyNotImplemented::extend_class(context, context.types.not_implemented_type);
124}
Morty Proxy This is a proxified and sanitized view of the page, visit original site.