question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Reliably Positional-Only `self` in `__call__`

See original GitHub issue

The C version of CallableObjectProxy.__call__ already has self be a positional-only argument, but the Python version doesn’t.

Here’s a good way to fix that which works on all old Python versions that wrapt still supports:

 class CallableObjectProxy(ObjectProxy):
-    def __call__(self, *args, **kwargs):
+    def __call__(*args, **kwargs):
+        def __call__(self, *args):
+            return self, args
+        self, args = __call__(*args)
         return self.__wrapped__(*args, **kwargs)

(Using a nested function with the same name is a good way to get a native exception with the same message that you normally would if you go out of your way to call CallableObjectProxy.__call__ directly.)

Issue Analytics

  • State:open
  • Created a year ago
  • Comments:8 (3 by maintainers)

github_iconTop GitHub Comments

2reactions
GrahamDumpletoncommented, Jun 24, 2022

It will take me a while to read and digest that wall of text. Am not in the right frame of mind right now so haven’t even tried to read it through.

One point I will make is that there are various cases where things implemented as pure Python don’t work the same as when done using C APIs. That is just how CPython is. I am not going out of my way to make them different, it just happens when you do things in the normally accepted ways using the respective APIs, they will not behave the same or it can’t be done in the same way, which in the case of trying to support both is always a problem as far as uniformity. I have tried very hard to make them work the same, but there are still some cases where it isn’t possible because the C API lacks features, or has strange limitations.

Anyway, I have perhaps not been understanding what the problem is you are trying to solve here, which is why was asking for the actual use cases. On first quick glance it seemed to be you were trying to side step binding semantics which is always a red flag for something being done wrong.

So I will look at this some more, I just will not get to it immediately.

0reactions
mentalisttraceurcommented, Sep 3, 2022

Actually I want to take emphasis off CallableObjectProxy.__call__ and refocus onto stuff like FunctionWrapper.__call__.

CallableObjectProxy.__call__ is so simple that I can trivially make sure my code polyfills the desired behavior on top of the pure-Python version:

from wrapt import CallableObjectProxy as _CallableObjectProxy

...

try:
    _CallableObjectProxy(lambda self: None)(self=None)
except TypeError:
    class _CallableObjectProxy(_CallableObjectProxy):
        def __call__(self, /, *args, **kwargs):
            return self.__wrapped__(*args, **kwargs)

But FunctionWrapper.__call__ has much more logic, and seems like the kind of problem where consumer code can’t self-provide a fix without duplicating all of __call__.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Positional-Only Arguments
In this lesson, you'll learn about how to add positional-only arguments to your functions in Python 3.8. The built-in function float() can be...
Read more >
Confusing behavior when Table() isn't given positional ...
So like a good boy I wrote the following bit of code: some_table = sqlalchemy.Table( name='le_table_name', metadata=sqlalchemy.MetaData(bind= ...
Read more >
10 Examples to Master *args and **kwargs in Python
Positional arguments are declared by a name only. Keyword arguments are declared by a name and a default value. When a function is...
Read more >
PEP 570 – Python Positional-Only Parameters
When a function accepting positional-only parameters is called, positional ... in C usually take self as a positional-only parameter:.
Read more >
How to fix the problem “missing 1 required positional ...
when ever you call a method using class object “self” should be your first argument. it is referring to your object. which object...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found