Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot implement __len__ classmethod (0.21+) #4640

Closed
timkpaine opened this issue Oct 22, 2024 · 6 comments · Fixed by #4654
Closed

Cannot implement __len__ classmethod (0.21+) #4640

timkpaine opened this issue Oct 22, 2024 · 6 comments · Fixed by #4654
Labels

Comments

@timkpaine
Copy link

timkpaine commented Oct 22, 2024

Bug Description

This used to work in pyo3<0.21:

    #[classmethod]
    fn __len__(cls: &Bound<'_, PyType>) -> PyResult<usize> {
        Ok(0)
    }
error[E0425]: cannot find value `_slf_ref` in this scope
  --> lib1-py/src/lib.rs:15:1
   |
15 | #[pymethods]
   | ^^^^^^^^^^^^ not found in this scope

Steps to Reproduce

Include the above block in any #[pymethods] block

Backtrace

error[E0425]: cannot find value `_slf_ref` in this scope
  --> lib1-py/src/lib.rs:15:1
   |
15 | #[pymethods]
   | ^^^^^^^^^^^^ not found in this scope

Your operating system and version

macOS 15.0.1

Your Python version (python --version)

Python 3.11.10

Your Rust version (rustc --version)

rustc 1.79.0 (129f3b996 2024-06-10)

Your PyO3 version

0.22.5

How did you install python? Did you use a virtualenv?

brew install [email protected], pip install pyo3

Additional Info

No response

@timkpaine timkpaine added the bug label Oct 22, 2024
@LilyFoote
Copy link
Contributor

Defining __len__ as a @classmethod seems very unusual to me. What's your use case?

@timkpaine
Copy link
Author

timkpaine commented Oct 24, 2024

Not unusual at all for certain types:

from enum import Enum, auto

class MyEnum(Enum):
    A = auto()
    B = auto()
    
print(len(MyEnum))  # > 2

My use case is the same, creating a class in rust representing an enum (where len is the enumeration of static members, very similar to the pure python example above).

@LilyFoote
Copy link
Contributor

In the Enum case, __len__ is defined on the EnumType metaclass, not the Enum class.

https://github.com/python/cpython/blob/4b55d53316f607fdd83831e92f585288842c8988/Lib/enum.py#L803-L807

I think you'll need #906 to be implemented to achieve this in PyO3.

@timkpaine
Copy link
Author

I think you'll need #906 to be implemented to achieve this in PyO3.

Or downgrade to 0.19, which is the more annoying bit as this used to work fine

@davidhewitt
Copy link
Member

Agreed this is a legitimate bug.

From a quick test, it seems like Python allows most (all?) the dunder methods to be @classmethod or even @staticmethod, so this is simply just a case which we should add tests for and support 👍

@Icxolu
Copy link
Contributor

Icxolu commented Oct 25, 2024

I attempted a fix in #4654.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants