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

Fix __str__ call for all Python objects #342

Open
tooruu opened this issue Jul 9, 2024 · 4 comments
Open

Fix __str__ call for all Python objects #342

tooruu opened this issue Jul 9, 2024 · 4 comments

Comments

@tooruu
Copy link

tooruu commented Jul 9, 2024

boost::python::object utf8Text = o.attr("__str__")();

Naively calling __str__() on an object assumes it is bound, which is not the case for non-instantiated classes.
Would it be possible to use Python's str builtin?

@Ekopalypse
Copy link
Contributor

Can you explain when this is a problem when using PythonScript?

@tooruu
Copy link
Author

tooruu commented Jul 11, 2024

Can you explain when this is a problem when using PythonScript?

Let's take editor.write for example. Its C++ signature expects a boost::python::api::object.
As I understand, we can pass any Python object and you convert it to string via ScintillaWrapper::getStringFromObject by calling o.__str__().
This works because you usually pass an instantiated class object, meaning you don't need to manually pass self to its methods (like __str__), so a call without arguments works.
But it breaks if you pass an uninstantiated class object (class itself). It doesn't bind self, so it expects you to pass something to the __str__ method.

>>> editor.write('text')  # 'text'.__str__() == 'text'
>>> editor.write(42)  # (42).__str__() == '42'

So far it looks fine with instances of str and int class (return values are omitted for brevity). Let's try a custom class.

>>> class Foo:
...     def __str__(self):
...         return __class__.__name__.lower()
...
>>> editor.write(Foo())  # Foo().__str__() == 'foo'
>>> editor.write(Foo)  # There is no `self` to auto insert into the `__str__` call.
Traceback (most recent call last):
  File "<console>", line 1, in <module>
TypeError: Foo.__str__() missing 1 required positional argument: 'self'

One might expect the value of str(Foo) to be written into the editor, but it wants us to pass something to __str__.

P.S. In this example str(Foo) == "<class '__main__.Foo'>". Not the most common use case, but you never know what the user is up to!

>>> class Meta(type):
...     def __str__(cls):
...         return cls.__name__.upper()
... 
>>> class Bar(metaclass=Meta):
...     pass
... 
>>> str(Bar)
'BAR'
>>> editor.write(Bar)
Traceback (most recent call last):
  File "<console>", line 1, in <module>
TypeError: descriptor '__str__' of 'object' object needs an argument

@Ekopalypse
Copy link
Contributor

I understand what you mean, but usually PythonScript is used to manipulate Notepad++, Scintilla and the buffer content, but

but you never know what the user is up to!

I guess you're right

@tooruu
Copy link
Author

tooruu commented Jul 12, 2024

This isn't high priority, or might not even get addressed. Regardless, it is a bug so I had to bring it to your attention.

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

No branches or pull requests

2 participants