Issue2476

classification
Title: Functions reflected from Java are missing attributes (used to break functools.wraps())
Type: Severity: normal
Components: Core Versions: Jython 2.7
Milestone: Jython 2.7.2
process
Status: open Resolution: accepted
Dependencies: Superseder:
Assigned To: Nosy List: seletz, stefan.richthofer, zyasoft
Priority: high Keywords:

Created on 2016-02-24.12:54:18 by seletz, last changed 2017-02-07.02:26:28 by stefan.richthofer.

Messages
msg10777 (view) Author: Stefan Eletzhofer (seletz) Date: 2016-02-24.12:54:18
The standard functools.py package breaks on functools.fraps():

Jython 2.7.1b3 (default:df42d5d6be04, Feb 3 2016, 03:22:46)
[Java HotSpot(TM) 64-Bit Server VM (Oracle Corporation)] on java1.7.0_60
Type "help", "copyright", "credits" or "license" for more information.
>>> import pathlib2
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/seletz/develop/jython/jython271b3/Lib/site-packages/pathlib2.py", line 476, in <module>
    class _NormalAccessor(_Accessor):
  File "/Users/seletz/develop/jython/jython271b3/Lib/site-packages/pathlib2.py", line 494, in _NormalAccessor
    open = _wrap_strfunc(os.open)
  File "/Users/seletz/develop/jython/jython271b3/Lib/site-packages/pathlib2.py", line 479, in _wrap_strfunc
    @functools.wraps(strfunc)
  File "/Users/seletz/develop/jython/jython271b3/Lib/functools.py", line 33, in update_wrapper
    setattr(wrapper, attr, getattr(wrapped, attr))
AttributeError: 'reflectedfunction' object has no attribute '__module__'


The same is happening on Jython 2.7.0
msg10778 (view) Author: Stefan Eletzhofer (seletz) Date: 2016-02-24.12:59:41
Better test case:

-----------------<8----------------
import os
import functools


@functools.wraps(os.open)
def foo():
    pass
------------------>8-------------

$ bin/jython foo.py                                                                                                                                                                                                  Traceback (most recent call last):
  File "foo.py", line 5, in <module>
    @functools.wraps(os.open)
  File "/Users/seletz/develop/jython/jython271b3/Lib/functools.py", line 33, in update_wrapper
    setattr(wrapper, attr, getattr(wrapped, attr))
AttributeError: 'reflectedfunction' object has no attribute '__module__'
msg10787 (view) Author: Jim Baker (zyasoft) Date: 2016-02-24.22:46:44
This is because os.open is a reflected function, that is one that is implemented in Java without being exposed using Python type system. Currently no __module__ attribute is defined:

$ dist/bin/jython
Jython 2.7.1b3 (default:08b7720fd321+, Feb 24 2016, 08:19:22)
[Java HotSpot(TM) 64-Bit Server VM (Oracle Corporation)] on java1.7.0_75
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> dir(os.open)
['__call__', '__class__', '__delattr__', '__doc__', '__ensure_finalizer__', '__format__', '__getattribute__', '__hash__', '__init__', '__name__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', '__subclasshook__', '_doget', 'addMethod', 'argslist', 'copy', 'handles', 'isPackagedProtected', 'nargs', 'printArgs', 'refersDirectlyTo', 'toString', 'traverse']

functools.wraps expects these attributes to be defined:

WRAPPER_ASSIGNMENTS = ('__module__', '__name__', '__doc__')
WRAPPER_UPDATES = ('__dict__',)
msg10788 (view) Author: Jim Baker (zyasoft) Date: 2016-02-24.22:56:18
org.python.core.PyReflectedFunction should use Jython's type expose mechanism, as seen in PyFunction. Probably the easiest thing to do is make PyReflectedFunction simply a subclass of PyFunction (much like PyFunction subclasses PyObject).
msg10789 (view) Author: Jim Baker (zyasoft) Date: 2016-02-24.22:57:35
Should also speed things up in Jython with Java integration.
msg11059 (view) Author: Stefan Richthofer (stefan.richthofer) Date: 2017-02-02.02:08:53
Backlinking to #2475, which now seems to depend on this issue.
msg11077 (view) Author: Stefan Richthofer (stefan.richthofer) Date: 2017-02-06.17:26:46
I would like to fix breakage of wraps by 'simply' adding a __module__ field to PyReflectedFunction and filling it appropriately in PyJavaType. (Remember to adjust PyReflectedFunction.copy and PyReflectedFunction.traverse accordingly).

In long term, Jim's solution is more complete, but is also a wider change and might take some time to be done right. Given that e.g. wraps is frequently used we should maybe add __module__ as a quick fix and improve on this later on.
Maybe an 'easy', preliminary "full fix" for custom attributes of PyReflectedFunction would be to let PyReflectedFunction have __dict__ (maybe lazily, on demand).
msg11078 (view) Author: Stefan Richthofer (stefan.richthofer) Date: 2017-02-07.02:26:28
Fixed workability of functools.wraps() as of https://github.com/jythontools/jython/commit/1452e07de33fd894dc4e9ddc815389f990758e83.
(by adding __module__ to PyReflectedFunction)
History
Date User Action Args
2017-02-07 02:26:28stefan.richthofersetmessages: + msg11078
title: Functions reflected from Java are missing attributes (breaks functools.wraps()) -> Functions reflected from Java are missing attributes (used to break functools.wraps())
2017-02-06 17:26:47stefan.richthofersetmessages: + msg11077
2017-02-02 02:08:53stefan.richthofersetmessages: + msg11059
2017-01-20 05:20:53stefan.richthofersetnosy: + stefan.richthofer
2016-02-24 22:57:35zyasoftsetmessages: + msg10789
title: functools.wraps() broken -> Functions reflected from Java are missing attributes (breaks functools.wraps())
2016-02-24 22:56:18zyasoftsetpriority: high
resolution: accepted
messages: + msg10788
milestone: Jython 2.7.2
2016-02-24 22:46:45zyasoftsetnosy: + zyasoft
messages: + msg10787
2016-02-24 12:59:42seletzsetmessages: + msg10778
2016-02-24 12:54:18seletzcreate