collections.abc mixin

29 views
Skip to first unread message

Amulet Editor

unread,
Jun 4, 2024, 8:24:14 AMJun 4
to cython-users
I want to use collections.abc.Sequence on top of some C++ data.
What is the best way to do this?
The only way I have found is to have a cdef class and a normal python class that inherits the cdef class and the mixin. This creates two classes.

The following is what I have tried and the results.

# cython: language_level=3, boundscheck=False, wraparound=False
# distutils: language = c++

from collections.abc import Sequence
from libcpp.vector cimport vector
from libc.stdint cimport int64_t


cdef class _MySequence:
    cdef vector[int64_t] v

    def __init__(self, *v: int):
        self.v = v

    def __getitem__(self, item):
        return tuple(self.v)[item]

    def __len__(self) -> int:
        return self.v.size()


class MySequence1(_MySequence, Sequence[int]):
    pass


# First base of 'MySequence2' is not an extension type
# cdef class MySequence2(Sequence[int]):
#     cdef vector[int64_t] v
#
#     def __init__(self, *v: int):
#         self.v = v
#
#     def __getitem__(self, item):
#         return tuple(self.v)[item]
#
#     def __len__(self) -> int:
#         return self.v.size()



# Compiles fine but errors when importing
# TypeError: type() doesn't support MRO entry resolution; use types.new_class()
# cdef class MySequence3(object, Sequence[int]):
#     cdef vector[int64_t] v
#
#     def __init__(self, *v: int):
#         self.v = v
#
#     def __getitem__(self, item):
#         return tuple(self.v)[item]
#
#     def __len__(self) -> int:
#         return self.v.size()


# cdef class BaseClass:
#     pass
#
#
# # Same as 3
# # TypeError: type() doesn't support MRO entry resolution; use types.new_class()
# cdef class MySequence4(BaseClass, Sequence[int]):
#     cdef vector[int64_t] v
#
#     def __init__(self, *v: int):
#         self.v = v
#
#     def __getitem__(self, item):
#         return tuple(self.v)[item]
#
#     def __len__(self) -> int:
#         return self.v.size()

da-woods

unread,
Jun 4, 2024, 2:08:37 PMJun 4
to cython...@googlegroups.com
What you can do is register it after the fact:

see what we do to our own memoryview classes for example (https://github.com/cython/cython/blob/965d7aa3485b8ba0497803c5b54cacf3f4acdbb0/Cython/Utility/MemoryView.pyx#L985) but essentially you call collections.abc.Sequence.register(MySequence1).

The one limitation is that this *doesn't* make it usable in `match` statements in Python because it can't set the type flag on an immutable type. There isn't a good way to do that at the moment - a while ago I proposed a PR to add a directive to do that (https://github.com/cython/cython/pull/5030).

Providing you don't want them to be usable in that context "register" works fine though.
--

---
You received this message because you are subscribed to the Google Groups "cython-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cython-users...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/cython-users/16fea85b-a35f-41f9-9edf-7cd6b2226896n%40googlegroups.com.


Reply all
Reply to author
Forward
0 new messages