Skip to main content

rustpython_vm/vm/
context.rs

1use crate::{
2    AsObject, PyObject,
3    builtins::{
4        PyByteArray, PyBytes, PyCapsule, PyComplex, PyDict, PyDictRef, PyEllipsis, PyFloat,
5        PyFrozenSet, PyInt, PyIntRef, PyList, PyListRef, PyNone, PyNotImplemented, PyStr,
6        PyStrInterned, PyTuple, PyTupleRef, PyType, PyTypeRef, PyUtf8Str,
7        bool_::PyBool,
8        code::{self, PyCode},
9        descriptor::{
10            MemberAccess, MemberKind, PyDescriptorOwned, PyMemberDef, PyMemberDescriptor,
11            PyMemberFlags,
12        },
13        getset::PyGetSet,
14        object, pystr,
15        type_::PyAttributes,
16    },
17    class::StaticType,
18    common::rc::PyRc,
19    exceptions,
20    function::{
21        HeapMethodDef, IntoPyGetterFunc, IntoPyNativeFn, IntoPySetterFunc, ItemDoc, PyMethodDef,
22        PyMethodFlags, plain_doc,
23    },
24    intern::{InternableString, MaybeInternedString, StringPool},
25    object::{Py, PyObjectPayload, PyObjectRef, PyPayload, PyRef},
26    types::{PyTypeFlags, PyTypeSlots, TypeZoo},
27};
28use core::ffi::{CStr, c_void};
29use malachite_bigint::BigInt;
30use num_complex::Complex64;
31use num_traits::ToPrimitive;
32use rustpython_common::lock::PyRwLock;
33
34#[derive(Debug)]
35pub struct Context {
36    pub true_value: PyRef<PyBool>,
37    pub false_value: PyRef<PyBool>,
38    pub none: PyRef<PyNone>,
39    pub empty_tuple: PyTupleRef,
40    pub empty_frozenset: PyRef<PyFrozenSet>,
41    pub empty_str: &'static PyStrInterned,
42    pub empty_bytes: PyRef<PyBytes>,
43    pub ellipsis: PyRef<PyEllipsis>,
44    pub not_implemented: PyRef<PyNotImplemented>,
45
46    pub typing_no_default: PyRef<crate::stdlib::_typing::NoDefault>,
47
48    pub types: TypeZoo,
49    pub exceptions: exceptions::ExceptionZoo,
50    pub int_cache_pool: Vec<PyIntRef>,
51    pub(crate) latin1_char_cache: Vec<PyRef<PyStr>>,
52    pub(crate) ascii_char_cache: Vec<PyRef<PyStr>>,
53    // there should only be exact objects of str in here, no non-str objects and no subclasses
54    pub(crate) string_pool: StringPool,
55    pub(crate) slot_new_wrapper: PyMethodDef,
56    pub names: ConstName,
57    // GC module state (callbacks and garbage lists)
58}
59
60macro_rules! declare_const_name {
61    ($($name:ident$(: $s:literal)?,)*) => {
62        #[derive(Debug, Clone, Copy)]
63        #[allow(non_snake_case)]
64        pub struct ConstName {
65            $(pub $name: &'static PyStrInterned,)*
66        }
67
68        impl ConstName {
69            unsafe fn new(pool: &StringPool, typ: &Py<PyType>) -> Self {
70                Self {
71                    $($name: unsafe { pool.intern(declare_const_name!(@string $name $($s)?), typ.to_owned()) },)*
72                }
73            }
74        }
75    };
76    (@string $name:ident) => { stringify!($name) };
77    (@string $name:ident $string:literal) => { $string };
78}
79
80declare_const_name! {
81    True,
82    False,
83    None,
84    NotImplemented,
85    Ellipsis,
86
87    // magic methods
88    __abs__,
89    __abstractmethods__,
90    __add__,
91    __aenter__,
92    __aexit__,
93    __aiter__,
94    __alloc__,
95    __all__,
96    __and__,
97    __anext__,
98    __annotate__,
99    __annotate_func__,
100    __annotations__,
101    __annotations_cache__,
102    __args__,
103    __await__,
104    __bases__,
105    __bool__,
106    __buffer__,
107    __build_class__,
108    __builtins__,
109    __bytes__,
110    __cached__,
111    __call__,
112    __ceil__,
113    __cformat__,
114    __class__,
115    __class_getitem__,
116    __classcell__,
117    __classdictcell__,
118    __complex__,
119    __contains__,
120    __copy__,
121    __deepcopy__,
122    __del__,
123    __delattr__,
124    __delete__,
125    __delitem__,
126    __dict__,
127    __dir__,
128    __div__,
129    __divmod__,
130    __doc__,
131    __enter__,
132    __eq__,
133    __exit__,
134    __file__,
135    __firstlineno__,
136    __float__,
137    __floor__,
138    __floordiv__,
139    __format__,
140    __fspath__,
141    __ge__,
142    __get__,
143    __getattr__,
144    __getattribute__,
145    __getformat__,
146    __getitem__,
147    __getnewargs__,
148    __getnewargs_ex__,
149    __getstate__,
150    __gt__,
151    __hash__,
152    __iadd__,
153    __iand__,
154    __idiv__,
155    __ifloordiv__,
156    __ilshift__,
157    __imatmul__,
158    __imod__,
159    __import__,
160    __imul__,
161    __index__,
162    __init__,
163    __init_subclass__,
164    __instancecheck__,
165    __int__,
166    __invert__,
167    __ior__,
168    __ipow__,
169    __irshift__,
170    __isub__,
171    __iter__,
172    __itruediv__,
173    __ixor__,
174    __jit__,  // RustPython dialect
175    __le__,
176    __len__,
177    __length_hint__,
178    __lshift__,
179    __lt__,
180    __main__,
181    __match_args__,
182    __matmul__,
183    __missing__,
184    __mod__,
185    __module__,
186    __mro_entries__,
187    __mul__,
188    __name__,
189    __ne__,
190    __neg__,
191    __new__,
192    __next__,
193    __objclass__,
194    __or__,
195    __orig_bases__,
196    __orig_class__,
197    __origin__,
198    __parameters__,
199    __pos__,
200    __pow__,
201    __prepare__,
202    __qualname__,
203    __radd__,
204    __rand__,
205    __rdiv__,
206    __rdivmod__,
207    __reduce__,
208    __reduce_ex__,
209    __release_buffer__,
210    __repr__,
211    __reversed__,
212    __rfloordiv__,
213    __rlshift__,
214    __rmatmul__,
215    __rmod__,
216    __rmul__,
217    __ror__,
218    __round__,
219    __rpow__,
220    __rrshift__,
221    __rshift__,
222    __rsub__,
223    __rtruediv__,
224    __rxor__,
225    __set__,
226    __setattr__,
227    __setitem__,
228    __setstate__,
229    __set_name__,
230    __slots__,
231    __slotnames__,
232    __str__,
233    __sub__,
234    __subclasscheck__,
235    __subclasshook__,
236    __subclasses__,
237    __sizeof__,
238    __truediv__,
239    __trunc__,
240    __type_params__,
241    __typing_subst__,
242    __typing_is_unpacked_typevartuple__,
243    __typing_prepare_subst__,
244    __typing_unpacked_tuple_args__,
245    __weakref__,
246    __xor__,
247
248    // common names
249    _attributes,
250    _fields,
251    _defaultaction,
252    _onceregistry,
253    _showwarnmsg,
254    defaultaction,
255    onceregistry,
256    filters,
257    backslashreplace,
258    close,
259    copy,
260    decode,
261    encode,
262    flush,
263    ignore,
264    items,
265    keys,
266    modules,
267    mro,
268    n_fields,
269    n_sequence_fields,
270    n_unnamed_fields,
271    namereplace,
272    replace,
273    strict,
274    surrogateescape,
275    surrogatepass,
276    update,
277    utf_8: "utf-8",
278    values,
279    version,
280    WarningMessage,
281    xmlcharrefreplace,
282}
283
284// Basic objects:
285impl Context {
286    pub const INT_CACHE_POOL_RANGE: core::ops::RangeInclusive<i32> = (-5)..=256;
287    const INT_CACHE_POOL_MIN: i32 = *Self::INT_CACHE_POOL_RANGE.start();
288
289    #[must_use]
290    pub fn genesis() -> &'static PyRc<Self> {
291        rustpython_common::static_cell! {
292            static CONTEXT: PyRc<Context>;
293        }
294        CONTEXT.get_or_init(|| {
295            let ctx = PyRc::new(Self::init_genesis());
296            // SAFETY: ctx is heap-allocated via PyRc and will be stored in
297            // the CONTEXT static cell, so the Context lives for 'static.
298            let ctx_ref: &'static Self = unsafe { &*PyRc::as_ptr(&ctx) };
299            crate::types::TypeZoo::extend(ctx_ref);
300            crate::exceptions::ExceptionZoo::extend(ctx_ref);
301            ctx
302        })
303    }
304
305    fn init_genesis() -> Self {
306        flame_guard!("init Context");
307        let (types, empty_tuple) = TypeZoo::init();
308        let exceptions = exceptions::ExceptionZoo::init();
309
310        #[inline]
311        fn create_object<T: PyObjectPayload>(payload: T, cls: &'static Py<PyType>) -> PyRef<T> {
312            PyRef::new_ref(payload, cls.to_owned(), None)
313        }
314
315        let none = create_object(PyNone, PyNone::static_type());
316        let ellipsis = create_object(PyEllipsis, PyEllipsis::static_type());
317        let not_implemented = create_object(PyNotImplemented, PyNotImplemented::static_type());
318
319        let typing_no_default = create_object(
320            crate::stdlib::_typing::NoDefault,
321            crate::stdlib::_typing::NoDefault::static_type(),
322        );
323
324        let int_cache_pool = Self::INT_CACHE_POOL_RANGE
325            .map(|v| {
326                PyRef::new_ref(
327                    PyInt::from(BigInt::from(v)),
328                    types.int_type.to_owned(),
329                    None,
330                )
331            })
332            .collect::<Vec<PyIntRef>>();
333
334        let string_pool = StringPool::default();
335
336        // The one-character latin-1 strings are interned, so that every route
337        // to one of them lands on the same object.
338        let latin1_char_cache = (u8::MIN..=u8::MAX)
339            .map(|b| {
340                let s = unsafe {
341                    string_pool.intern(char::from(b).to_string(), types.str_type.to_owned())
342                };
343                s.to_owned()
344            })
345            .collect::<Vec<PyRef<PyStr>>>();
346
347        let ascii_char_cache = latin1_char_cache[..128].to_vec();
348
349        let true_value = create_object(PyBool(PyInt::from(1)), types.bool_type);
350        let false_value = create_object(PyBool(PyInt::from(0)), types.bool_type);
351
352        let empty_frozenset = PyRef::new_ref(
353            PyFrozenSet::default(),
354            types.frozenset_type.to_owned(),
355            None,
356        );
357
358        let names = unsafe { ConstName::new(&string_pool, types.str_type) };
359
360        let slot_new_wrapper = PyMethodDef::new_const(
361            names.__new__.as_str(),
362            PyType::__new__,
363            PyMethodFlags::METHOD,
364            ItemDoc::static_text(
365                "__new__($type, /, *args, **kwargs)\n--\n\nCreate and return a new object.  See help(type) for accurate signature.",
366            ),
367        );
368        let empty_str = unsafe { string_pool.intern("", types.str_type.to_owned()) };
369        let empty_bytes = create_object(PyBytes::from(Vec::new()), types.bytes_type);
370
371        // Everything above is created once and kept by this `Context` for the
372        // life of the process, so none of it can ever be deallocated. Saying
373        // so in the refcount word turns every reference operation on a
374        // singleton — the `True`/`False` a `TO_BOOL` pushes and a
375        // `POP_JUMP_IF_*` pops, the `None` behind every bare `return`, the
376        // small ints a `LOAD_CONST` hands out — from an atomic
377        // read-modify-write into a branch.
378        for obj in [
379            none.as_object(),
380            ellipsis.as_object(),
381            not_implemented.as_object(),
382            typing_no_default.as_object(),
383            true_value.as_object(),
384            false_value.as_object(),
385            empty_tuple.as_object(),
386            empty_frozenset.as_object(),
387            empty_bytes.as_object(),
388            empty_str.as_object(),
389        ] {
390            obj.make_immortal();
391        }
392        for int in &int_cache_pool {
393            int.as_object().make_immortal();
394        }
395        // The interned one-character strings. `StringPool::intern` already
396        // immortalized these; stating it here keeps the singletons from
397        // depending on that.
398        for s in &latin1_char_cache {
399            s.as_object().make_immortal();
400        }
401
402        // GC callbacks and garbage lists
403
404        Self {
405            true_value,
406            false_value,
407            none,
408            empty_tuple,
409            empty_frozenset,
410            empty_str,
411            empty_bytes,
412            ellipsis,
413
414            not_implemented,
415            typing_no_default,
416
417            types,
418            exceptions,
419            int_cache_pool,
420            latin1_char_cache,
421            ascii_char_cache,
422            string_pool,
423            slot_new_wrapper,
424            names,
425        }
426    }
427
428    pub fn intern_str<S: InternableString>(&self, s: S) -> &'static PyStrInterned {
429        unsafe { self.string_pool.intern(s, self.types.str_type.to_owned()) }
430    }
431
432    pub fn interned_str<S: MaybeInternedString + ?Sized>(
433        &self,
434        s: &S,
435    ) -> Option<&'static PyStrInterned> {
436        self.string_pool.interned(s)
437    }
438
439    #[inline(always)]
440    pub fn none(&self) -> PyObjectRef {
441        self.none.clone().into()
442    }
443
444    #[inline(always)]
445    pub fn not_implemented(&self) -> PyObjectRef {
446        self.not_implemented.clone().into()
447    }
448
449    #[inline]
450    pub fn empty_tuple_typed<T>(&self) -> &Py<PyTuple<T>> {
451        let py: &Py<PyTuple> = &self.empty_tuple;
452        unsafe { core::mem::transmute(py) }
453    }
454
455    // universal pyref constructor
456    pub fn new_pyref<T, P>(&self, value: T) -> PyRef<P>
457    where
458        T: Into<P>,
459        P: PyPayload + core::fmt::Debug,
460    {
461        value.into().into_ref(self)
462    }
463
464    // shortcuts for common type
465
466    #[inline]
467    pub fn new_int<T: Into<BigInt> + ToPrimitive>(&self, i: T) -> PyIntRef {
468        if let Some(i) = i.to_i32()
469            && Self::INT_CACHE_POOL_RANGE.contains(&i)
470        {
471            let inner_idx = (i - Self::INT_CACHE_POOL_MIN) as usize;
472            return self.int_cache_pool[inner_idx].clone();
473        }
474        PyInt::from(i).into_ref(self)
475    }
476
477    /// Borrow a cached small integer whose lifetime is tied to this context.
478    #[inline(always)]
479    pub(crate) fn cached_int(&self, i: i32) -> &Py<PyInt> {
480        debug_assert!(Self::INT_CACHE_POOL_RANGE.contains(&i));
481        let inner_idx = (i - Self::INT_CACHE_POOL_MIN) as usize;
482        &self.int_cache_pool[inner_idx]
483    }
484
485    #[inline]
486    pub fn new_bigint(&self, i: &BigInt) -> PyIntRef {
487        if let Some(i) = i.to_i32()
488            && Self::INT_CACHE_POOL_RANGE.contains(&i)
489        {
490            let inner_idx = (i - Self::INT_CACHE_POOL_MIN) as usize;
491            return self.int_cache_pool[inner_idx].clone();
492        }
493        PyInt::from(i.clone()).into_ref(self)
494    }
495
496    #[inline]
497    pub fn new_float(&self, value: f64) -> PyRef<PyFloat> {
498        PyFloat::from(value).into_ref(self)
499    }
500
501    #[inline]
502    pub fn new_complex(&self, value: Complex64) -> PyRef<PyComplex> {
503        PyComplex::from(value).into_ref(self)
504    }
505
506    #[inline]
507    pub fn latin1_char(&self, ch: u8) -> PyRef<PyStr> {
508        self.latin1_char_cache[ch as usize].clone()
509    }
510
511    #[inline]
512    fn latin1_singleton_index(s: &PyStr) -> Option<u8> {
513        let mut cps = s.as_wtf8().code_points();
514        let cp = cps.next()?;
515
516        cps.next()
517            .is_none()
518            .then(|| u8::try_from(cp.to_u32()).ok())?
519    }
520
521    #[inline]
522    pub fn new_str(&self, s: impl Into<pystr::PyStr>) -> PyRef<PyStr> {
523        let s = s.into();
524        if s.is_empty() {
525            self.empty_str.to_owned()
526        } else if let Some(ch) = Self::latin1_singleton_index(&s) {
527            self.latin1_char(ch)
528        } else {
529            s.into_ref(self)
530        }
531    }
532
533    #[inline]
534    pub fn new_utf8_str(&self, s: impl Into<PyUtf8Str>) -> PyRef<PyUtf8Str> {
535        s.into().into_ref(self)
536    }
537
538    pub fn interned_or_new_str<S, M>(&self, s: S) -> PyRef<PyStr>
539    where
540        S: Into<PyStr> + AsRef<M>,
541        M: MaybeInternedString,
542    {
543        if let Some(s) = self.interned_str(s.as_ref()) {
544            s.to_owned()
545        } else {
546            self.new_str(s)
547        }
548    }
549
550    #[inline]
551    pub fn new_bytes(&self, data: Vec<u8>) -> PyRef<PyBytes> {
552        if data.is_empty() {
553            self.empty_bytes.clone()
554        } else {
555            PyBytes::from(data).into_ref(self)
556        }
557    }
558
559    #[inline]
560    pub fn new_bytearray(&self, data: Vec<u8>) -> PyRef<PyByteArray> {
561        PyByteArray::from(data).into_ref(self)
562    }
563
564    #[inline(always)]
565    pub fn new_bool(&self, b: bool) -> PyRef<PyBool> {
566        let value = if b {
567            &self.true_value
568        } else {
569            &self.false_value
570        };
571        value.to_owned()
572    }
573
574    #[inline(always)]
575    pub fn new_tuple(&self, elements: Vec<PyObjectRef>) -> PyTupleRef {
576        PyTuple::new_ref(elements, self)
577    }
578
579    #[inline(always)]
580    pub fn new_list(&self, elements: Vec<PyObjectRef>) -> PyListRef {
581        PyList::from(elements).into_ref(self)
582    }
583
584    #[inline(always)]
585    pub fn new_dict(&self) -> PyDictRef {
586        PyDict::default().into_ref(self)
587    }
588
589    pub fn new_class(
590        &self,
591        module: Option<&str>,
592        name: &str,
593        base: PyTypeRef,
594        slots: PyTypeSlots,
595    ) -> PyTypeRef {
596        let mut attrs = PyAttributes::default();
597        if let Some(module) = module {
598            attrs.insert(identifier!(self, __module__), self.new_str(module).into());
599        };
600        PyType::new_heap(
601            name,
602            vec![base],
603            attrs,
604            slots,
605            self.types.type_type.to_owned(),
606            self,
607        )
608        .unwrap()
609    }
610
611    pub fn new_exception_type(
612        &self,
613        module: &str,
614        name: &str,
615        bases: Option<Vec<PyTypeRef>>,
616    ) -> PyTypeRef {
617        self.new_exception_type_with_doc(module, name, bases, ItemDoc::NONE)
618    }
619
620    /// Like `new_exception_type`, with `doc` as the new type's `__doc__`.
621    pub fn new_exception_type_with_doc(
622        &self,
623        module: &str,
624        name: &str,
625        bases: Option<Vec<PyTypeRef>>,
626        doc: ItemDoc,
627    ) -> PyTypeRef {
628        let bases = bases.unwrap_or_else(|| vec![self.exceptions.exception_type.to_owned()]);
629        let mut attrs = PyAttributes::default();
630        attrs.insert(identifier!(self, __module__), self.new_str(module).into());
631        if let Some(text) = plain_doc(doc) {
632            attrs.insert(identifier!(self, __doc__), self.new_str(text).into());
633        }
634
635        let interned_name = self.intern_str(name);
636        let slots = PyTypeSlots {
637            name: interned_name.as_str(),
638            basicsize: 0,
639            flags: crate::types::AtomicPyTypeFlags::from_plain(PyTypeFlags::HEAP_TYPE_WITH_DICT),
640            ..PyTypeSlots::default()
641        };
642        PyType::new_heap(
643            name,
644            bases,
645            attrs,
646            slots,
647            self.types.type_type.to_owned(),
648            self,
649        )
650        .unwrap()
651    }
652
653    pub fn new_method_def<F, FKind>(
654        &self,
655        name: &'static str,
656        f: F,
657        flags: PyMethodFlags,
658        doc: ItemDoc,
659    ) -> PyRef<HeapMethodDef>
660    where
661        F: IntoPyNativeFn<FKind>,
662    {
663        let def = PyMethodDef {
664            name,
665            func: Box::leak(Box::new(f.into_func())),
666            flags,
667            #[cfg(feature = "doc")]
668            doc_off: doc.offset,
669            #[cfg(feature = "doc")]
670            doc_len: doc.len,
671            #[cfg(feature = "doc")]
672            doc_body_pending: false,
673            doc: doc.text,
674        };
675        let payload = HeapMethodDef::new(def);
676        PyRef::new_ref(payload, self.types.method_def.to_owned(), None)
677    }
678
679    #[inline]
680    pub fn new_member(
681        &self,
682        name: &str,
683        kind: MemberKind,
684        offset: isize,
685        flags: PyMemberFlags,
686        class: &'static Py<PyType>,
687        doc: ItemDoc,
688    ) -> PyRef<PyMemberDescriptor> {
689        let member_descriptor = PyMemberDescriptor {
690            common: PyDescriptorOwned {
691                typ: class.to_owned(),
692                name: self.intern_str(name),
693                qualname: PyRwLock::new(None),
694            },
695            member: PyMemberDef {
696                name: name.to_owned(),
697                kind,
698                offset,
699                flags,
700                doc,
701            },
702            access: MemberAccess::Offset,
703        };
704        member_descriptor.into_ref(self)
705    }
706
707    pub fn new_readonly_tuple_member(
708        &self,
709        name: &str,
710        class: &'static Py<PyType>,
711        index: usize,
712        doc: ItemDoc,
713    ) -> PyRef<PyMemberDescriptor> {
714        let member_descriptor = PyMemberDescriptor {
715            common: PyDescriptorOwned {
716                typ: class.to_owned(),
717                name: self.intern_str(name),
718                qualname: PyRwLock::new(None),
719            },
720            member: PyMemberDef {
721                name: name.to_owned(),
722                kind: MemberKind::Object,
723                offset: index as isize,
724                flags: PyMemberFlags::READONLY,
725                doc,
726            },
727            access: MemberAccess::TupleItem,
728        };
729        member_descriptor.into_ref(self)
730    }
731
732    pub fn new_readonly_getset<F, T>(
733        &self,
734        name: &str,
735        class: &'static Py<PyType>,
736        f: F,
737    ) -> PyRef<PyGetSet>
738    where
739        F: IntoPyGetterFunc<T>,
740    {
741        let getset = PyGetSet::new(name, class, self).with_get(f);
742        PyRef::new_ref(getset, self.types.getset_type.to_owned(), None)
743    }
744
745    pub fn new_static_getset<G, S, T, U>(
746        &self,
747        name: &str,
748        class: &'static Py<PyType>,
749        g: G,
750        s: S,
751    ) -> PyRef<PyGetSet>
752    where
753        G: IntoPyGetterFunc<T>,
754        S: IntoPySetterFunc<U>,
755    {
756        let getset = PyGetSet::new(name, class, self).with_get(g).with_set(s);
757        PyRef::new_ref(getset, self.types.getset_type.to_owned(), None)
758    }
759
760    /// Creates a new [`PyGetSet`] with a heap type.
761    pub fn new_getset<G, S, T, U>(
762        &self,
763        name: &str,
764        class: &Py<PyType>,
765        g: G,
766        s: S,
767    ) -> PyRef<PyGetSet>
768    where
769        G: IntoPyGetterFunc<T>,
770        S: IntoPySetterFunc<U>,
771    {
772        let getset = PyGetSet::new(name, class, self).with_get(g).with_set(s);
773        PyRef::new_ref(getset, self.types.getset_type.to_owned(), None)
774    }
775
776    pub fn new_base_object(&self, class: PyTypeRef, dict: Option<PyDictRef>) -> PyObjectRef {
777        debug_assert_eq!(
778            class.slots.flags.has_feature(PyTypeFlags::HAS_DICT),
779            dict.is_some()
780        );
781        PyRef::new_ref(object::PyBaseObject, class, dict).into()
782    }
783
784    pub fn new_code(&self, code: impl code::IntoCodeObject) -> PyRef<PyCode> {
785        let code = code.into_code_object(self);
786        PyRef::new_ref(PyCode::new(code), self.types.code_type.to_owned(), None)
787    }
788
789    pub fn new_capsule(
790        &self,
791        ptr: *mut c_void,
792        name: Option<&'static CStr>,
793        destructor: Option<unsafe extern "C" fn(_: *mut PyObject)>,
794    ) -> PyRef<PyCapsule> {
795        PyCapsule::new(ptr, name, destructor).into_ref(self)
796    }
797}
798
799impl AsRef<Self> for Context {
800    fn as_ref(&self) -> &Self {
801        self
802    }
803}