Search code examples
pythonsequencepython-c-api

Which members of PySequenceMethods are optional?


I'd like to allow my extension objects to be passed into Python's len() function, and I understand the way to do this is to implement the sq_length member of PySequenceMethods, but right now I don't have time to implement all the methods of the sequence protocol, and I can't figure out which of the methods are optional and which (if any) are required.

The documentation for tp_as_sequence does not mention anything about optional members.

The documentation for PySequenceMethods explicitly states that sq_item, sq_ass_item, sq_contains, sq_inplace_concat, and sq_inplace_repeat can be left to NULL.

Further, the documentation for sq_item implies that sq_length can also be left to NULL:

If sq_length is NULL, the index is passed as is [...]

Which leaves sq_concat and sq_repeat. I'd be surprised if it weren't safe to also set these to NULL, given that you can do so for all the other members (including sq_item, and sq_length, both of which seem more fundamental to the concept of a sequence than the others), but is this assumption actually correct?

If it's not safe to leave them NULL, is it safe to implement them simply to set an error stating that these two functions are not supported and return NULL?


Solution

  • All of them are optional.

    Setting sq_item to NULL means that PySequence_Check() fails, and so it isn't really a sequence - I don't know how "optional" you want to consider that.

    All of the PySequence_* methods check for NULL pointers and will just set a Python TypeError rather than crashing, so it's safe to set these members to NULL. Just to show the two you were unsure about:

    PySequence_Concat and PySequence_Repeat both have code of the form:

    if (m && m->sq_repeat)
        return m->sq_repeat(o, count);
    

    It's pretty straightforward to go through the rest of the functions and see that they use the same pattern.