Bug 1899952 - python-brother fails to build with Python 3.10: AttributeError: module 'asyncio' has no attribute 'async'
Summary: python-brother fails to build with Python 3.10: AttributeError: module 'async...
Keywords:
Status: NEW
Alias: None
Product: Fedora
Classification: Fedora
Component: python-brother
Version: rawhide
Hardware: Unspecified
OS: Unspecified
unspecified
unspecified
Target Milestone: ---
Assignee: Fabian Affolter
QA Contact: Fedora Extras Quality Assurance
URL:
Whiteboard:
Depends On:
Blocks: PYTHON3.10
TreeView+ depends on / blocked
 
Reported: 2020-11-20 13:03 UTC by Tomáš Hrnčiar
Modified: 2021-02-09 16:24 UTC (History)
3 users (show)

Fixed In Version:
Doc Type: If docs needed, set a value
Doc Text:
Clone Of:
Environment:
Last Closed:
Type: Bug


Attachments (Terms of Use)

Description Tomáš Hrnčiar 2020-11-20 13:03:17 UTC
python-brother fails to build with Python 3.10.0a2.

=================================== FAILURES ===================================
_______________________________ test_snmp_error ________________________________

self = <pysnmp.carrier.asyncio.dgram.udp.UdpAsyncioTransport object at 0x7f29982511c0>
iface = None

    def openClientMode(self, iface=None):
        try:
            c = self.loop.create_datagram_endpoint(
                lambda: self, local_addr=iface, family=self.sockFamily
            )
            # Avoid deprecation warning for asyncio.async()
            if IS_PYTHON_344_PLUS:
              self._lport = asyncio.ensure_future(c)
            else: # pragma: no cover
>             self._lport = getattr(asyncio, 'async')(c)
E             AttributeError: module 'asyncio' has no attribute 'async'

/usr/lib/python3.10/site-packages/pysnmp/carrier/asyncio/dgram/base.py:93: AttributeError

During handling of the above exception, another exception occurred:

self = <brother.Brother object at 0x7f29982ac670>

    async def _get_data(self):
        """Retreive data from printer."""
        raw_data = {}
    
        if not self._snmp_engine:
            self._snmp_engine = hlapi.SnmpEngine()
    
        try:
            request_args = [
                self._snmp_engine,
                hlapi.CommunityData("public", mpModel=0),
                hlapi.UdpTransportTarget(
                    (self._host, self._port), timeout=2, retries=10
                ),
                hlapi.ContextData(),
            ]
>           errindication, errstatus, errindex, restable = await hlapi.getCmd(
                *request_args, *self._oids
            )

../../BUILDROOT/python-brother-0.1.17-1.fc34.x86_64/usr/lib/python3.10/site-packages/brother/__init__.py:196: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

args = (SnmpEngine(snmpEngineID=<SnmpEngineID value object, tagSet <TagSet object, tags 0:0:4>, subtypeSpec <ConstraintsInter...traintsIntersection object, consts <SingleValueConstraint object, consts b''>>, encoding iso-8859-1, payload []>), ...)
kw = {}

    @functools.wraps(func)
    def coro(*args, **kw):
>       res = func(*args, **kw)

/usr/lib64/python3.10/asyncio/coroutines.py:124: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

snmpEngine = SnmpEngine(snmpEngineID=<SnmpEngineID value object, tagSet <TagSet object, tags 0:0:4>, subtypeSpec <ConstraintsInters...535>, <ValueSizeConstraint object, consts 5, 32>>, encoding iso-8859-1, payload [0x80004fb8056330...343562390086c640]>)
authData = CommunityData(communityIndex='s6132166685333635612', communityName=<COMMUNITY>, mpModel=0, contextEngineId=None, contextName=b'', tag=b'', securityName='s6132166685333635612')
transportTarget = UdpTransportTarget(('127.0.0.1', 161), timeout=2, retries=10, tagList=b'')
contextData = ContextData(contextEngineId=None, contextName=b'')
varBinds = (ObjectType(ObjectIdentity('1.3.6.1.2.1.43.7.1.1.4.1.1'), <Null value object, tagSet <TagSet object, tags 0:0:5>, subt...traintsIntersection object, consts <SingleValueConstraint object, consts b''>>, encoding iso-8859-1, payload []>), ...)
options = {}, __cbFun = <function getCmd.<locals>.__cbFun at 0x7f29981deee0>

    @asyncio.coroutine
    def getCmd(snmpEngine, authData, transportTarget, contextData,
               *varBinds, **options):
        """Creates a generator to perform SNMP GET query.
    
        When iterator gets advanced by :py:mod:`asyncio` main loop,
        SNMP GET request is send (:RFC:`1905#section-4.2.1`).
        The iterator yields :py:class:`asyncio.Future` which gets done whenever
        response arrives or error occurs.
    
        Parameters
        ----------
        snmpEngine : :py:class:`~pysnmp.hlapi.SnmpEngine`
            Class instance representing SNMP engine.
    
        authData : :py:class:`~pysnmp.hlapi.CommunityData` or :py:class:`~pysnmp.hlapi.UsmUserData`
            Class instance representing SNMP credentials.
    
        transportTarget : :py:class:`~pysnmp.hlapi.asyncio.UdpTransportTarget` or :py:class:`~pysnmp.hlapi.asyncio.Udp6TransportTarget`
            Class instance representing transport type along with SNMP peer address.
    
        contextData : :py:class:`~pysnmp.hlapi.ContextData`
            Class instance representing SNMP ContextEngineId and ContextName values.
    
        \*varBinds : :py:class:`~pysnmp.smi.rfc1902.ObjectType`
            One or more class instances representing MIB variables to place
            into SNMP request.
    
        Other Parameters
        ----------------
        \*\*options :
            Request options:
    
                * `lookupMib` - load MIB and resolve response MIB variables at
                  the cost of slightly reduced performance. Default is `True`.
    
        Yields
        ------
        errorIndication : str
            True value indicates SNMP engine error.
        errorStatus : str
            True value indicates SNMP PDU error.
        errorIndex : int
            Non-zero value refers to `varBinds[errorIndex-1]`
        varBinds : tuple
            A sequence of :py:class:`~pysnmp.smi.rfc1902.ObjectType` class
            instances representing MIB variables returned in SNMP response.
    
        Raises
        ------
        PySnmpError
            Or its derivative indicating that an error occurred while
            performing SNMP operation.
    
        Examples
        --------
        >>> import asyncio
        >>> from pysnmp.hlapi.asyncio import *
        >>>
        >>> @asyncio.coroutine
        ... def run():
        ...     errorIndication, errorStatus, errorIndex, varBinds = yield from getCmd(
        ...         SnmpEngine(),
        ...         CommunityData('public'),
        ...         UdpTransportTarget(('demo.snmplabs.com', 161)),
        ...         ContextData(),
        ...         ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0))
        ...     )
        ...     print(errorIndication, errorStatus, errorIndex, varBinds)
        >>>
        >>> asyncio.get_event_loop().run_until_complete(run())
        (None, 0, 0, [ObjectType(ObjectIdentity(ObjectName('1.3.6.1.2.1.1.1.0')), DisplayString('SunOS zeus.snmplabs.com 4.1.3_U1 1 sun4m'))])
        >>>
    
        """
    
        def __cbFun(snmpEngine, sendRequestHandle,
                    errorIndication, errorStatus, errorIndex,
                    varBinds, cbCtx):
            lookupMib, future = cbCtx
            if future.cancelled():
                return
            try:
                varBindsUnmade = vbProcessor.unmakeVarBinds(snmpEngine, varBinds,
                                                            lookupMib)
            except Exception:
                ex = sys.exc_info()[1]
                future.set_exception(ex)
            else:
                future.set_result(
                    (errorIndication, errorStatus, errorIndex, varBindsUnmade)
                )
    
>       addrName, paramsName = lcd.configure(
            snmpEngine, authData, transportTarget, contextData.contextName)

/usr/lib/python3.10/site-packages/pysnmp/hlapi/asyncio/cmdgen.py:151: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <pysnmp.hlapi.lcd.CommandGeneratorLcdConfigurator object at 0x7f29983244c0>
snmpEngine = SnmpEngine(snmpEngineID=<SnmpEngineID value object, tagSet <TagSet object, tags 0:0:4>, subtypeSpec <ConstraintsInters...535>, <ValueSizeConstraint object, consts 5, 32>>, encoding iso-8859-1, payload [0x80004fb8056330...343562390086c640]>)
authData = CommunityData(communityIndex='s6132166685333635612', communityName=<COMMUNITY>, mpModel=0, contextEngineId=None, contextName=b'', tag=b'', securityName='s6132166685333635612')
transportTarget = UdpTransportTarget(('127.0.0.1', 161), timeout=2, retries=10, tagList=b'')
contextName = b'', options = {}
cache = {'addr': {}, 'auth': {}, 'parm': {}, 'tran': {}}
paramsKey = ('s6132166685333635612', 'noAuthNoPriv', 0)
paramsName = 'p2630354224'

    def configure(self, snmpEngine, authData, transportTarget, contextName, **options):
        cache = self._getCache(snmpEngine)
        if isinstance(authData, CommunityData):
            if authData.communityIndex not in cache['auth']:
                config.addV1System(
                    snmpEngine,
                    authData.communityIndex,
                    authData.communityName,
                    authData.contextEngineId,
                    authData.contextName,
                    authData.tag,
                    authData.securityName
                )
                cache['auth'][authData.communityIndex] = authData
        elif isinstance(authData, UsmUserData):
            authDataKey = authData.userName, authData.securityEngineId
            if authDataKey not in cache['auth']:
                config.addV3User(
                    snmpEngine,
                    authData.userName,
                    authData.authProtocol, authData.authKey,
                    authData.privProtocol, authData.privKey,
                    securityEngineId=authData.securityEngineId,
                    securityName=authData.securityName,
                    authKeyType=authData.authKeyType,
                    privKeyType=authData.privKeyType
                )
                cache['auth'][authDataKey] = authData
        else:
            raise error.PySnmpError('Unsupported authentication object')
    
        paramsKey = (authData.securityName,
                     authData.securityLevel,
                     authData.mpModel)
        if paramsKey in cache['parm']:
            paramsName, useCount = cache['parm'][paramsKey]
            cache['parm'][paramsKey] = paramsName, useCount + 1
        else:
            paramsName = 'p%s' % self.nextID()
            config.addTargetParams(
                snmpEngine, paramsName,
                authData.securityName, authData.securityLevel, authData.mpModel
            )
            cache['parm'][paramsKey] = paramsName, 1
    
        if transportTarget.transportDomain in cache['tran']:
            transport, useCount = cache['tran'][transportTarget.transportDomain]
            transportTarget.verifyDispatcherCompatibility(snmpEngine)
            cache['tran'][transportTarget.transportDomain] = transport, useCount + 1
        elif config.getTransport(snmpEngine, transportTarget.transportDomain):
            transportTarget.verifyDispatcherCompatibility(snmpEngine)
        else:
>           transport = transportTarget.openClientMode()

/usr/lib/python3.10/site-packages/pysnmp/hlapi/lcd.py:91: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = UdpTransportTarget(('127.0.0.1', 161), timeout=2, retries=10, tagList=b'')

    def openClientMode(self):
>       self.transport = self.protoTransport().openClientMode(self.iface)

/usr/lib/python3.10/site-packages/pysnmp/hlapi/transport.py:53: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <pysnmp.carrier.asyncio.dgram.udp.UdpAsyncioTransport object at 0x7f29982511c0>
iface = None

    def openClientMode(self, iface=None):
        try:
            c = self.loop.create_datagram_endpoint(
                lambda: self, local_addr=iface, family=self.sockFamily
            )
            # Avoid deprecation warning for asyncio.async()
            if IS_PYTHON_344_PLUS:
              self._lport = asyncio.ensure_future(c)
            else: # pragma: no cover
              self._lport = getattr(asyncio, 'async')(c)
    
        except Exception:
>           raise error.CarrierError(';'.join(traceback.format_exception(*sys.exc_info())))
E           pysnmp.carrier.error.CarrierError: Traceback (most recent call last):
E           ;  File "/usr/lib/python3.10/site-packages/pysnmp/carrier/asyncio/dgram/base.py", line 93, in openClientMode
E               self._lport = getattr(asyncio, 'async')(c)
E           ;AttributeError: module 'asyncio' has no attribute 'async'
E           caused by <class 'AttributeError'>: module 'asyncio' has no attribute 'async'

/usr/lib/python3.10/site-packages/pysnmp/carrier/asyncio/dgram/base.py:96: CarrierError

During handling of the above exception, another exception occurred:

    @pytest.mark.asyncio
    async def test_snmp_error():
        """Test with raise SnmpError."""
        with pytest.raises(SnmpError):
    
            brother = Brother(HOST)
>           await brother.async_update()

tests/test_base.py:237: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
../../BUILDROOT/python-brother-0.1.17-1.fc34.x86_64/usr/lib/python3.10/site-packages/brother/__init__.py:67: in async_update
    raw_data = await self._get_data()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <brother.Brother object at 0x7f29982ac670>

    async def _get_data(self):
        """Retreive data from printer."""
        raw_data = {}
    
        if not self._snmp_engine:
            self._snmp_engine = hlapi.SnmpEngine()
    
        try:
            request_args = [
                self._snmp_engine,
                hlapi.CommunityData("public", mpModel=0),
                hlapi.UdpTransportTarget(
                    (self._host, self._port), timeout=2, retries=10
                ),
                hlapi.ContextData(),
            ]
            errindication, errstatus, errindex, restable = await hlapi.getCmd(
                *request_args, *self._oids
            )
        except PySnmpError as error:
            self.data = {}
>           raise ConnectionError(error)
E           ConnectionError: Traceback (most recent call last):
E           ;  File "/usr/lib/python3.10/site-packages/pysnmp/carrier/asyncio/dgram/base.py", line 93, in openClientMode
E               self._lport = getattr(asyncio, 'async')(c)
E           ;AttributeError: module 'asyncio' has no attribute 'async'
E           caused by <class 'AttributeError'>: module 'asyncio' has no attribute 'async'

../../BUILDROOT/python-brother-0.1.17-1.fc34.x86_64/usr/lib/python3.10/site-packages/brother/__init__.py:201: ConnectionError

---------- coverage: platform linux, python 3.10.0-alpha-2 -----------
Name                  Stmts   Miss  Cover   Missing
---------------------------------------------------
brother/__init__.py     139    139     0%   5-301
brother/const.py         75     75     0%   2-184
---------------------------------------------------
TOTAL                   214    214     0%

=========================== short test summary info ============================
FAILED tests/test_base.py::test_snmp_error - ConnectionError: Traceback (most...
=================== 1 failed, 12 passed, 7 warnings in 0.58s ===================
error: Bad exit status from /var/tmp/rpm-tmp.9d6eDv (%check)
    Bad exit status from /var/tmp/rpm-tmp.9d6eDv (%check)



For the build logs, see:
https://copr-be.cloud.fedoraproject.org/results/@python/python3.10/fedora-rawhide-x86_64/01773060-python-brother/

For all our attempts to build python-brother with Python 3.10, see:
https://copr.fedorainfracloud.org/coprs/g/python/python3.10/package/python-brother/

Testing and mass rebuild of packages is happening in copr. You can follow these instructions to test locally in mock if your package builds with Python 3.10:
https://copr.fedorainfracloud.org/coprs/g/python/python3.10/

Let us know here if you have any questions.

Python 3.10 will be included in Fedora 35. To make that update smoother, we're building Fedora packages with early pre-releases of Python 3.10.
A build failure prevents us from testing all dependent packages (transitive [Build]Requires), so if this package is required a lot, it's important for us to get it fixed soon.
We'd appreciate help from the people who know this package best, but if you don't want to work on this now, let us know so we can try to work around it on our side.

Comment 1 Ben Cotton 2021-02-09 15:26:38 UTC
This bug appears to have been reported against 'rawhide' during the Fedora 34 development cycle.
Changing version to 34.


Note You need to log in before you can comment on or make changes to this bug.