Page MenuHomePhabricator

'instancemethod' object has no attribute '__full_name__'
Closed, ResolvedPublic

Description

Tried to login from a debian 8 machine to a non wmf wiki with this version of pwb:

Pywikibot: [https] wikimedia-pywikibot.git (6f79910, g9698, 2018/06/16, 06:46:05, OUTDATED)
Release version: 3.1.dev0
requests version: 2.11.1
  cacerts: /etc/ssl/certs/ca-certificates.crt
    certificate test: ok
Python: 2.7.9 (default, Jun 29 2016, 13:08:31)

Returns this exception, which I have no clue to do with:

Traceback (most recent call last):
  File "pwb.py", line 251, in <module>
    if not main():
  File "pwb.py", line 244, in main
    run_python_file(filename, [filename] + args, argvu, file_package)
  File "pwb.py", line 115, in run_python_file
    main_mod.__dict__)
  File "./scripts/login.py", line 196, in <module>
    main()
  File "./scripts/login.py", line 167, in main
    site = pywikibot.Site()
  File "/home/user1/user2/pywikibot/pywikibot/__init__.py", line 1245, in Site
    fam = Family.load(fam)
  File "/home/user1/user2/pywikibot/pywikibot/tools/__init__.py", line 1446, in wrapper
    return obj(*__args, **__kw)
  File "/home/user1/user2/pywikibot/pywikibot/family.py", line 996, in load
    cls = mod.Family.instance
  File "/home/user1/user2/pywikibot/pywikibot/tools/__init__.py", line 156, in __get__
    return self.method(owner)
  File "/home/user1/user2/pywikibot/pywikibot/family.py", line 79, in instance
    return cls()
  File "/home/user1/user2/pywikibot/pywikibot/family.py", line 64, in __new__
    cls.__init__ = deprecated(cls.__init__)
  File "/home/user1/user2/pywikibot/pywikibot/tools/__init__.py", line 1261, in outer_wrapper
    add_decorated_full_name(outer_args[0])
  File "/home/user1/user2/pywikibot/pywikibot/tools/__init__.py", line 1174, in add_decorated_full_name
    obj.__name__)
AttributeError: 'instancemethod' object has no attribute '__full_name__'
<type 'exceptions.AttributeError'>
CRITICAL: Closing network session.

Event Timeline

This error is from attempting to [[https://github.com/wikimedia/pywikibot/blob/c2603c8a90ca6f1e6c762000e737856a01c1c9c2/pywikibot/tools/__init__.py#L1172|assign __full_name__ attribute]] to a built-in object of type instancemethod.

I guess cls.__init__ is a method bound to the class:

>>> (lambda: None).__get__(object()).__class__
<type 'instancemethod'>

so we could use __func__ to obtain the original function and deprecate it:

>>> (lambda: None).__get__(object()).__func__
<function <lambda> at 0x7f98ba39f668>

But this breaks in python 3 when trying to access as a class attribute:

# python2
>>> meth = (lambda: None).__get__(object(), object); meth; meth.__class__; meth.__func__
<bound method object.<lambda> of <object object at 0x7f6e9f33e080>>
<type 'instancemethod'>
<function <lambda> at 0x7f6e9f31a5f0>
>>> meth = (lambda: None).__get__(None, object); meth; meth.__class__; meth.__func__
<unbound method object.<lambda>>
<type 'instancemethod'>
<function <lambda> at 0x7f6e9f31a668>
>>> 
# python3
>>> meth = (lambda: None).__get__(object(), object); meth; meth.__class__; meth.__func__
<bound method <lambda> of <object object at 0x7f5d5f5a5080>>
<class 'method'>
<function <lambda> at 0x7f5d5f4829d8>
>>> meth = (lambda: None).__get__(None, object); meth; meth.__class__; meth.__func__
<function <lambda> at 0x7f5d5f482a60>
<class 'function'>
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'function' object has no attribute '__func__'
>>>

Python 3 returns the function directly as a class attribute, whereas Python 2 returns a wrapper. The function does not have the __func__ attribute to get itself.

We could either use a try-except-AttributeError, or fetch the function from the __dict__, since we verified its existence anyways.

Change 440725 had a related patch set uploaded (by Zhuyifei1999; owner: Zhuyifei1999):
[pywikibot/core@master] family: read __init__ from __dict__ and deprecate

https://gerrit.wikimedia.org/r/440725

I tried your patched version, no error now, works like a charm.

Well, yeah, but note that since families became singletons use of __init__ to initialize the instance is deprecated.

I am a noob programer, what is the outcome for me? That it might change again in the future?

I am a noob programer, what is the outcome for me? That it might change again in the future?

That the family may get broken in the very far future and you may need to modify your family files or re-generate them. See cc4a95f for examples of such modification.

Dalba claimed this task.
Dalba triaged this task as High priority.
Dalba subscribed.

Thanks, @Wesalius, for reporting the issue and testing the patch.

Change 440725 merged by jenkins-bot:
[pywikibot/core@master] family: read __init__ from __dict__ and deprecate

https://gerrit.wikimedia.org/r/440725

Vvjjkkii renamed this task from 'instancemethod' object has no attribute '__full_name__' to esaaaaaaaa.Jul 1 2018, 1:04 AM
Vvjjkkii reopened this task as Open.
Vvjjkkii removed zhuyifei1999 as the assignee of this task.
Vvjjkkii updated the task description. (Show Details)
Vvjjkkii removed subscribers: gerritbot, Aklapper.