enthought / envisage

Envisage is a Python-based framework for building applications whose functionalities can be extended by adding "plug-ins".
http://docs.enthought.com/envisage/
Other
82 stars 26 forks source link

Test failure in `test_zmq_sockets_closed` with latest packages from PyPI #469

Closed mdickinson closed 2 years ago

mdickinson commented 2 years ago

The PyPI workflow is failing on Python 3.6 with the following failure, which I can also reproduce locally:

======================================================================
ERROR: test_zmq_sockets_closed (envisage.plugins.ipython_kernel.tests.test_internal_ipkernel.TestInternalIPKernel)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/mdickinson/.venvs/envisage/lib/python3.6/site-packages/envisage/plugins/ipython_kernel/tests/test_internal_ipkernel.py", line 200, in test_zmq_sockets_closed
    sockets = self.objects_of_type(zmq.Socket)
  File "/Users/mdickinson/.venvs/envisage/lib/python3.6/site-packages/envisage/plugins/ipython_kernel/tests/test_internal_ipkernel.py", line 279, in objects_of_type
    return [obj for obj in gc.get_objects() if isinstance(obj, type)]
  File "/Users/mdickinson/.venvs/envisage/lib/python3.6/site-packages/envisage/plugins/ipython_kernel/tests/test_internal_ipkernel.py", line 279, in <listcomp>
    return [obj for obj in gc.get_objects() if isinstance(obj, type)]
  File "/opt/local/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/typing.py", line 1162, in __instancecheck__
    return issubclass(instance.__class__, self)
AttributeError: 'functools._lru_list_elem' object has no attribute '__class__'

----------------------------------------------------------------------

The main issue here is that with the relevant versions of the packages, zmq.Socket is not a type:

ipdb> zmq.__version__
'23.1.0'
ipdb> type(zmq.Socket)
<class 'typing.GenericMeta'>

That the internal functools._lru_list_elem object doesn't have a __class__ attribute is a secondary issue. Either or both of these may be fixed in a later version of Python; I haven't yet checked.

mdickinson commented 2 years ago

The missing __class__ appears to be fixed in Python 3.7 and later. I'm testing using this script:

import functools, gc

@functools.lru_cache()
def square(x):
    return x*x

# Make sure there are entries in the cache
square(3)

len([obj.__class__ for obj in gc.get_objects()])

Under Python 3.6, I get:

(envisage) mdickinson@mirzakhani temp % python3.6 test.py
Traceback (most recent call last):
  File "test.py", line 10, in <module>
    len([obj.__class__ for obj in gc.get_objects()])
  File "test.py", line 10, in <listcomp>
    len([obj.__class__ for obj in gc.get_objects()])
AttributeError: 'functools._lru_list_elem' object has no attribute '__class__'

Under Python 3.7 and later (tested with 3.7 through 3.11 inclusive), the script completes with no error (or output):

(envisage) mdickinson@mirzakhani temp % python3.7 test.py

So if we can't find a better solution, it may be reasonable to simply skip this test on Python 3.6.

mdickinson commented 2 years ago

So if we can't find a better solution

Another possible quick-and-dirty solution may be to limit the zmq version on Python 3.6.