diff --git a/.python-eventlet.metadata b/.python-eventlet.metadata new file mode 100644 index 0000000..abed2d2 --- /dev/null +++ b/.python-eventlet.metadata @@ -0,0 +1,2 @@ +c0e45f875a64534ce3756d3f7e4de6633788bb28 SOURCES/v0.30.2.zip +88fd1703aa8abb825799d08b624308c655d1307a SOURCES/dnspython-1.16.0.zip diff --git a/SOURCES/715.patch b/SOURCES/715.patch new file mode 100644 index 0000000..874d896 --- /dev/null +++ b/SOURCES/715.patch @@ -0,0 +1,242 @@ +From beb705719827843940ecebe48ef8b8ba65d2b91c Mon Sep 17 00:00:00 2001 +From: Tim Burke +Date: Wed, 9 Jun 2021 14:40:13 -0700 +Subject: [PATCH 1/6] Only wrap socket.timeout on Python < 3.10 + +On py310, socket.timeout is TimeoutError, which our is_timeout() helper +func already knows is a timeout. + +Note that this doesn't get us to py310 support (not by a long shot), but +it's a step along the way. + +Closes #687 +--- + eventlet/greenio/base.py | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/eventlet/greenio/base.py b/eventlet/greenio/base.py +index 2eed86966..51a7ae13e 100644 +--- a/eventlet/greenio/base.py ++++ b/eventlet/greenio/base.py +@@ -29,7 +29,10 @@ + _original_socket = eventlet.patcher.original('socket').socket + + +-socket_timeout = eventlet.timeout.wrap_is_timeout(socket.timeout) ++if sys.version_info >= (3, 10): ++ socket_timeout = socket.timeout # Really, TimeoutError ++else: ++ socket_timeout = eventlet.timeout.wrap_is_timeout(socket.timeout) + + + def socket_connect(descriptor, address): + +From c22a27ace90a55d14e8c60ff37f9832e76266441 Mon Sep 17 00:00:00 2001 +From: Tim Burke +Date: Fri, 11 Jun 2021 12:56:07 -0700 +Subject: [PATCH 2/6] Get a working greenio._open on py310 + +_pyio.open is now a staticmethod, which means we can't get at the +function code to wrap it up with a new environment. + +Instead, create a new wrapper function which swaps out FileIO for +GreenFileIO in the function's __globals__ before calling and replaces +it in a finally. +--- + eventlet/greenio/py3.py | 30 +++++++++++++++++++++++------- + 1 file changed, 23 insertions(+), 7 deletions(-) + +diff --git a/eventlet/greenio/py3.py b/eventlet/greenio/py3.py +index 7a75b52c0..c7f0aef50 100644 +--- a/eventlet/greenio/py3.py ++++ b/eventlet/greenio/py3.py +@@ -2,6 +2,7 @@ + import errno + import os as _original_os + import socket as _original_socket ++import sys + from io import ( + BufferedRandom as _OriginalBufferedRandom, + BufferedReader as _OriginalBufferedReader, +@@ -19,6 +20,7 @@ + SOCKET_BLOCKING, + ) + from eventlet.hubs import notify_close, notify_opened, IOClosed, trampoline ++from eventlet.semaphore import Semaphore + from eventlet.support import get_errno + import six + +@@ -182,21 +184,35 @@ def __exit__(self, *args): + self.close() + + +-_open_environment = dict(globals()) +-_open_environment.update(dict( ++_open_patching = dict( + BufferedRandom=_OriginalBufferedRandom, + BufferedWriter=_OriginalBufferedWriter, + BufferedReader=_OriginalBufferedReader, + TextIOWrapper=_OriginalTextIOWrapper, + FileIO=GreenFileIO, + os=_original_os, +-)) +- +-_open = FunctionType( +- six.get_function_code(_original_pyio.open), +- _open_environment, + ) + ++if sys.version_info < (3, 10): ++ _open_environment = dict(globals()) ++ _open_environment.update(_open_patching) ++ _open = FunctionType( ++ six.get_function_code(_original_pyio.open), ++ _open_environment, ++ ) ++else: ++ _open_lock = Semaphore() ++ _open_originals = {k: _original_pyio.open.__func__.__globals__[k] ++ for k in _open_patching} ++ ++ def _open(*a, **kw): ++ with _open_lock: ++ try: ++ _original_pyio.open.__func__.__globals__.update(_open_patching) ++ return _original_pyio.open(*a, **kw) ++ finally: ++ _original_pyio.open.__func__.__globals__.update(_open_originals) ++ + + def GreenPipe(name, mode="r", buffering=-1, encoding=None, errors=None, + newline=None, closefd=True, opener=None): + +From ab4f8aaa704eb56b1e15730268fffbc8724c53ea Mon Sep 17 00:00:00 2001 +From: Tim Burke +Date: Fri, 11 Jun 2021 13:02:52 -0700 +Subject: [PATCH 3/6] Test using eventlet.is_timeout + +...rather than requiring an is_timeout attribute on errors. + +TimeoutErrors (which are covered by is_timeout) can't necessarily have +attributes added to them. +--- + tests/__init__.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tests/__init__.py b/tests/__init__.py +index c0b64fd9e..188366774 100644 +--- a/tests/__init__.py ++++ b/tests/__init__.py +@@ -383,7 +383,7 @@ def run_isolated(path, prefix='tests/isolated/', **kwargs): + + def check_is_timeout(obj): + value_text = getattr(obj, 'is_timeout', '(missing)') +- assert obj.is_timeout, 'type={0} str={1} .is_timeout={2}'.format(type(obj), str(obj), value_text) ++ assert eventlet.is_timeout(obj), 'type={0} str={1} .is_timeout={2}'.format(type(obj), str(obj), value_text) + + + @contextlib.contextmanager + +From ceef941b6b730add07eff4a3d4da5d203e255a71 Mon Sep 17 00:00:00 2001 +From: Tim Burke +Date: Fri, 11 Jun 2021 13:07:09 -0700 +Subject: [PATCH 4/6] Fix backdoor tests on py310 + +Python 3.10 started including build info on the version line, so the +expectation in tests had to change. Also, start printing the banner as +we read it to aid in future debugging. +--- + tests/backdoor_test.py | 17 +++++++++++++---- + 1 file changed, 13 insertions(+), 4 deletions(-) + +diff --git a/tests/backdoor_test.py b/tests/backdoor_test.py +index 03a569259..67a817947 100644 +--- a/tests/backdoor_test.py ++++ b/tests/backdoor_test.py +@@ -1,5 +1,6 @@ + import os + import os.path ++import sys + + import eventlet + +@@ -21,10 +22,18 @@ def test_server(self): + + def _run_test_on_client_and_server(self, client, server_thread): + f = client.makefile('rw') +- assert 'Python' in f.readline() +- f.readline() # build info +- f.readline() # help info +- assert 'InteractiveConsole' in f.readline() ++ line = f.readline() ++ print(line.strip('\r\n')) ++ assert 'Python' in line ++ if sys.version_info < (3, 10): ++ # Starting in py310, build info is included in version line ++ line = f.readline() # build info ++ print(line.strip('\r\n')) ++ line = f.readline() # help info ++ print(line.strip('\r\n')) ++ line = f.readline() ++ print(line.strip('\r\n')) ++ assert 'InteractiveConsole' in line + self.assertEqual('>>> ', f.read(4)) + f.write('print("hi")\n') + f.flush() + +From aa6720a44cda816d1ac0a183ff94ebd51b6b1e53 Mon Sep 17 00:00:00 2001 +From: Tim Burke +Date: Fri, 11 Jun 2021 13:12:36 -0700 +Subject: [PATCH 5/6] Tolerate __builtins__ being a dict (rather than module) + in is_timeout + +I'm still not sure how this happens, but somehow it does in +socket_test.test_error_is_timeout. As a result, is_timeout wouldn't get +a reference to TimeoutError, so the socket error would not be correctly +identified as a timeout. +--- + eventlet/timeout.py | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/eventlet/timeout.py b/eventlet/timeout.py +index 6e1e08f63..969fdbcbd 100644 +--- a/eventlet/timeout.py ++++ b/eventlet/timeout.py +@@ -175,5 +175,8 @@ def fun(*args, **kwargs): + + + def is_timeout(obj): +- py3err = getattr(__builtins__, 'TimeoutError', Timeout) ++ if isinstance(__builtins__, dict): # seen when running tests on py310, but HOW?? ++ py3err = __builtins__.get('TimeoutError', Timeout) ++ else: ++ py3err = getattr(__builtins__, 'TimeoutError', Timeout) + return bool(getattr(obj, 'is_timeout', False)) or isinstance(obj, py3err) + +From 900c8e195154efdae526ee7901469152141ab9d2 Mon Sep 17 00:00:00 2001 +From: Tim Burke +Date: Fri, 11 Jun 2021 13:33:00 -0700 +Subject: [PATCH 6/6] wsgi_test: Cap TLS version at 1.2 + +On py310, tests may attempt to use TLS 1.3 which apparently doesn't like +the abrupt disconnect. Instead, it would complain: + + ssl.SSLEOFError: EOF occurred in violation of protocol +--- + tests/wsgi_test.py | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/tests/wsgi_test.py b/tests/wsgi_test.py +index 1dd754bba..4173bcefa 100644 +--- a/tests/wsgi_test.py ++++ b/tests/wsgi_test.py +@@ -579,7 +579,8 @@ def wsgi_app(environ, start_response): + sock = eventlet.wrap_ssl( + eventlet.listen(('localhost', 0)), + certfile=certificate_file, keyfile=private_key_file, +- server_side=True) ++ server_side=True, ++ ssl_version=ssl.PROTOCOL_TLSv1_2) + server_coro = eventlet.spawn(server, sock, wsgi_app, self.logfile) + + client = eventlet.connect(('localhost', sock.getsockname()[1])) diff --git a/SOURCES/switch_to_python_cryptography.patch b/SOURCES/switch_to_python_cryptography.patch new file mode 100644 index 0000000..a5ced51 --- /dev/null +++ b/SOURCES/switch_to_python_cryptography.patch @@ -0,0 +1,343 @@ +From 087df702931f32eeb3a29957a8fe3fa31749d642 Mon Sep 17 00:00:00 2001 +From: Simo Sorce +Date: Tue, 28 Apr 2020 10:08:02 +0200 +Subject: [PATCH] Switch to python cryptography + +Original patch: https://github.com/simo5/dnspython/commit/bfe84d523bd4fde7b2655857d78bba85ed05f43c +The same change in master: https://github.com/rthalley/dnspython/pull/449 +--- + dns/dnssec.py | 168 ++++++++++++++++++++----------------------- + setup.py | 2 +- + tests/test_dnssec.py | 12 +--- + 3 files changed, 79 insertions(+), 103 deletions(-) + +diff --git a/dns/dnssec.py b/dns/dnssec.py +index 35da6b5..73e92da 100644 +--- a/dns/dnssec.py ++++ b/dns/dnssec.py +@@ -17,6 +17,7 @@ + + """Common DNSSEC-related functions and constants.""" + ++import hashlib # used in make_ds() to avoid pycrypto dependency + from io import BytesIO + import struct + import time +@@ -165,10 +166,10 @@ def make_ds(name, key, algorithm, origin=None): + + if algorithm.upper() == 'SHA1': + dsalg = 1 +- hash = SHA1.new() ++ hash = hashlib.sha1() + elif algorithm.upper() == 'SHA256': + dsalg = 2 +- hash = SHA256.new() ++ hash = hashlib.sha256() + else: + raise UnsupportedAlgorithm('unsupported algorithm "%s"' % algorithm) + +@@ -214,7 +215,7 @@ def _is_dsa(algorithm): + + + def _is_ecdsa(algorithm): +- return _have_ecdsa and (algorithm in (ECDSAP256SHA256, ECDSAP384SHA384)) ++ return (algorithm in (ECDSAP256SHA256, ECDSAP384SHA384)) + + + def _is_md5(algorithm): +@@ -240,18 +241,26 @@ def _is_sha512(algorithm): + + def _make_hash(algorithm): + if _is_md5(algorithm): +- return MD5.new() ++ return hashes.MD5() + if _is_sha1(algorithm): +- return SHA1.new() ++ return hashes.SHA1() + if _is_sha256(algorithm): +- return SHA256.new() ++ return hashes.SHA256() + if _is_sha384(algorithm): +- return SHA384.new() ++ return hashes.SHA384() + if _is_sha512(algorithm): +- return SHA512.new() ++ return hashes.SHA512() ++ if algorithm == ED25519: ++ return hashes.SHA512() ++ if algorithm == ED448: ++ return hashes.SHAKE256(114) + raise ValidationFailure('unknown hash for algorithm %u' % algorithm) + + ++def _bytes_to_long(b): ++ return int.from_bytes(b, 'big') ++ ++ + def _make_algorithm_id(algorithm): + if _is_md5(algorithm): + oid = [0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05] +@@ -316,8 +325,6 @@ def _validate_rrsig(rrset, rrsig, keys, origin=None, now=None): + if rrsig.inception > now: + raise ValidationFailure('not yet valid') + +- hash = _make_hash(rrsig.algorithm) +- + if _is_rsa(rrsig.algorithm): + keyptr = candidate_key.key + (bytes_,) = struct.unpack('!B', keyptr[0:1]) +@@ -328,9 +335,9 @@ def _validate_rrsig(rrset, rrsig, keys, origin=None, now=None): + rsa_e = keyptr[0:bytes_] + rsa_n = keyptr[bytes_:] + try: +- pubkey = CryptoRSA.construct( +- (number.bytes_to_long(rsa_n), +- number.bytes_to_long(rsa_e))) ++ public_key = rsa.RSAPublicNumbers( ++ _bytes_to_long(rsa_e), ++ _bytes_to_long(rsa_n)).public_key(default_backend()) + except ValueError: + raise ValidationFailure('invalid public key') + sig = rrsig.signature +@@ -346,42 +353,47 @@ def _validate_rrsig(rrset, rrsig, keys, origin=None, now=None): + dsa_g = keyptr[0:octets] + keyptr = keyptr[octets:] + dsa_y = keyptr[0:octets] +- pubkey = CryptoDSA.construct( +- (number.bytes_to_long(dsa_y), +- number.bytes_to_long(dsa_g), +- number.bytes_to_long(dsa_p), +- number.bytes_to_long(dsa_q))) +- sig = rrsig.signature[1:] ++ try: ++ public_key = dsa.DSAPublicNumbers( ++ _bytes_to_long(dsa_y), ++ dsa.DSAParameterNumbers( ++ _bytes_to_long(dsa_p), ++ _bytes_to_long(dsa_q), ++ _bytes_to_long(dsa_g))).public_key(default_backend()) ++ except ValueError: ++ raise ValidationFailure('invalid public key') ++ sig_r = rrsig.signature[1:21] ++ sig_s = rrsig.signature[21:] ++ sig = utils.encode_dss_signature(_bytes_to_long(sig_r), ++ _bytes_to_long(sig_s)) + elif _is_ecdsa(rrsig.algorithm): +- # use ecdsa for NIST-384p -- not currently supported by pycryptodome +- + keyptr = candidate_key.key +- + if rrsig.algorithm == ECDSAP256SHA256: +- curve = ecdsa.curves.NIST256p +- key_len = 32 ++ curve = ec.SECP256R1() ++ octets = 32 + elif rrsig.algorithm == ECDSAP384SHA384: +- curve = ecdsa.curves.NIST384p +- key_len = 48 +- +- x = number.bytes_to_long(keyptr[0:key_len]) +- y = number.bytes_to_long(keyptr[key_len:key_len * 2]) +- if not ecdsa.ecdsa.point_is_valid(curve.generator, x, y): +- raise ValidationFailure('invalid ECDSA key') +- point = ecdsa.ellipticcurve.Point(curve.curve, x, y, curve.order) +- verifying_key = ecdsa.keys.VerifyingKey.from_public_point(point, +- curve) +- pubkey = ECKeyWrapper(verifying_key, key_len) +- r = rrsig.signature[:key_len] +- s = rrsig.signature[key_len:] +- sig = ecdsa.ecdsa.Signature(number.bytes_to_long(r), +- number.bytes_to_long(s)) ++ curve = ec.SECP384R1() ++ octets = 48 ++ ecdsa_x = keyptr[0:octets] ++ ecdsa_y = keyptr[octets:octets * 2] ++ try: ++ public_key = ec.EllipticCurvePublicNumbers( ++ curve=curve, ++ x=_bytes_to_long(ecdsa_x), ++ y=_bytes_to_long(ecdsa_y)).public_key(default_backend()) ++ except ValueError: ++ raise ValidationFailure('invalid public key') ++ sig_r = rrsig.signature[0:octets] ++ sig_s = rrsig.signature[octets:] ++ sig = utils.encode_dss_signature(_bytes_to_long(sig_r), ++ _bytes_to_long(sig_s)) + + else: + raise ValidationFailure('unknown algorithm %u' % rrsig.algorithm) + +- hash.update(_to_rdata(rrsig, origin)[:18]) +- hash.update(rrsig.signer.to_digestable(origin)) ++ data = b'' ++ data += _to_rdata(rrsig, origin)[:18] ++ data += rrsig.signer.to_digestable(origin) + + if rrsig.labels < len(rrname) - 1: + suffix = rrname.split(rrsig.labels + 1)[1] +@@ -391,25 +403,21 @@ def _validate_rrsig(rrset, rrsig, keys, origin=None, now=None): + rrsig.original_ttl) + rrlist = sorted(rdataset) + for rr in rrlist: +- hash.update(rrnamebuf) +- hash.update(rrfixed) ++ data += rrnamebuf ++ data += rrfixed + rrdata = rr.to_digestable(origin) + rrlen = struct.pack('!H', len(rrdata)) +- hash.update(rrlen) +- hash.update(rrdata) ++ data += rrlen ++ data += rrdata + ++ chosen_hash = _make_hash(rrsig.algorithm) + try: + if _is_rsa(rrsig.algorithm): +- verifier = pkcs1_15.new(pubkey) +- # will raise ValueError if verify fails: +- verifier.verify(hash, sig) ++ public_key.verify(sig, data, padding.PKCS1v15(), chosen_hash) + elif _is_dsa(rrsig.algorithm): +- verifier = DSS.new(pubkey, 'fips-186-3') +- verifier.verify(hash, sig) ++ public_key.verify(sig, data, chosen_hash) + elif _is_ecdsa(rrsig.algorithm): +- digest = hash.digest() +- if not pubkey.verify(digest, sig): +- raise ValueError ++ public_key.verify(sig, data, ec.ECDSA(chosen_hash)) + else: + # Raise here for code clarity; this won't actually ever happen + # since if the algorithm is really unknown we'd already have +@@ -417,7 +425,7 @@ def _validate_rrsig(rrset, rrsig, keys, origin=None, now=None): + raise ValidationFailure('unknown algorithm %u' % rrsig.algorithm) + # If we got here, we successfully verified so we can return without error + return +- except ValueError: ++ except InvalidSignature: + # this happens on an individual validation failure + continue + # nothing verified -- raise failure: +@@ -472,48 +480,24 @@ def _validate(rrset, rrsigset, keys, origin=None, now=None): + raise ValidationFailure("no RRSIGs validated") + + +-def _need_pycrypto(*args, **kwargs): +- raise NotImplementedError("DNSSEC validation requires pycryptodome/pycryptodomex") ++def _need_pyca(*args, **kwargs): ++ raise NotImplementedError("DNSSEC validation requires python cryptography") + + + try: +- try: +- # test we're using pycryptodome, not pycrypto (which misses SHA1 for example) +- from Crypto.Hash import MD5, SHA1, SHA256, SHA384, SHA512 +- from Crypto.PublicKey import RSA as CryptoRSA, DSA as CryptoDSA +- from Crypto.Signature import pkcs1_15, DSS +- from Crypto.Util import number +- except ImportError: +- from Cryptodome.Hash import MD5, SHA1, SHA256, SHA384, SHA512 +- from Cryptodome.PublicKey import RSA as CryptoRSA, DSA as CryptoDSA +- from Cryptodome.Signature import pkcs1_15, DSS +- from Cryptodome.Util import number ++ from cryptography.exceptions import InvalidSignature ++ from cryptography.hazmat.backends import default_backend ++ from cryptography.hazmat.primitives import hashes ++ from cryptography.hazmat.primitives.asymmetric import padding ++ from cryptography.hazmat.primitives.asymmetric import utils ++ from cryptography.hazmat.primitives.asymmetric import dsa ++ from cryptography.hazmat.primitives.asymmetric import ec ++ from cryptography.hazmat.primitives.asymmetric import rsa + except ImportError: +- validate = _need_pycrypto +- validate_rrsig = _need_pycrypto +- _have_pycrypto = False +- _have_ecdsa = False ++ validate = _need_pyca ++ validate_rrsig = _need_pyca ++ _have_pyca = False + else: + validate = _validate + validate_rrsig = _validate_rrsig +- _have_pycrypto = True +- +- try: +- import ecdsa +- import ecdsa.ecdsa +- import ecdsa.ellipticcurve +- import ecdsa.keys +- except ImportError: +- _have_ecdsa = False +- else: +- _have_ecdsa = True +- +- class ECKeyWrapper(object): +- +- def __init__(self, key, key_len): +- self.key = key +- self.key_len = key_len +- +- def verify(self, digest, sig): +- diglong = number.bytes_to_long(digest) +- return self.key.pubkey.verifies(diglong, sig) ++ _have_pyca = True +diff --git a/setup.py b/setup.py +index 743d43c..2ee38a7 100755 +--- a/setup.py ++++ b/setup.py +@@ -75,7 +75,7 @@ direct manipulation of DNS zones, messages, names, and records.""", + 'provides': ['dns'], + 'extras_require': { + 'IDNA': ['idna>=2.1'], +- 'DNSSEC': ['pycryptodome', 'ecdsa>=0.13'], ++ 'DNSSEC': ['cryptography>=2.3'], + }, + 'ext_modules': ext_modules if compile_cython else None, + 'zip_safe': False if compile_cython else None, +diff --git a/tests/test_dnssec.py b/tests/test_dnssec.py +index c87862a..20b52b2 100644 +--- a/tests/test_dnssec.py ++++ b/tests/test_dnssec.py +@@ -151,8 +151,8 @@ abs_ecdsa384_soa_rrsig = dns.rrset.from_text('example.', 86400, 'IN', 'RRSIG', + + + +-@unittest.skipUnless(dns.dnssec._have_pycrypto, +- "Pycryptodome cannot be imported") ++@unittest.skipUnless(dns.dnssec._have_pyca, ++ "Python Cryptography cannot be imported") + class DNSSECValidatorTestCase(unittest.TestCase): + + def testAbsoluteRSAGood(self): # type: () -> None +@@ -199,28 +199,20 @@ class DNSSECValidatorTestCase(unittest.TestCase): + ds = dns.dnssec.make_ds(abs_example, example_sep_key, 'SHA256') + self.failUnless(ds == example_ds_sha256) + +- @unittest.skipUnless(dns.dnssec._have_ecdsa, +- "python ECDSA cannot be imported") + def testAbsoluteECDSA256Good(self): # type: () -> None + dns.dnssec.validate(abs_ecdsa256_soa, abs_ecdsa256_soa_rrsig, + abs_ecdsa256_keys, None, when3) + +- @unittest.skipUnless(dns.dnssec._have_ecdsa, +- "python ECDSA cannot be imported") + def testAbsoluteECDSA256Bad(self): # type: () -> None + def bad(): # type: () -> None + dns.dnssec.validate(abs_other_ecdsa256_soa, abs_ecdsa256_soa_rrsig, + abs_ecdsa256_keys, None, when3) + self.failUnlessRaises(dns.dnssec.ValidationFailure, bad) + +- @unittest.skipUnless(dns.dnssec._have_ecdsa, +- "python ECDSA cannot be imported") + def testAbsoluteECDSA384Good(self): # type: () -> None + dns.dnssec.validate(abs_ecdsa384_soa, abs_ecdsa384_soa_rrsig, + abs_ecdsa384_keys, None, when4) + +- @unittest.skipUnless(dns.dnssec._have_ecdsa, +- "python ECDSA cannot be imported") + def testAbsoluteECDSA384Bad(self): # type: () -> None + def bad(): # type: () -> None + dns.dnssec.validate(abs_other_ecdsa384_soa, abs_ecdsa384_soa_rrsig, +-- +2.26.2 + diff --git a/SPECS/python-eventlet.spec b/SPECS/python-eventlet.spec new file mode 100644 index 0000000..af3f7a1 --- /dev/null +++ b/SPECS/python-eventlet.spec @@ -0,0 +1,321 @@ +%global modname eventlet +%global bundle_dns 1 +%{?python_enable_dependency_generator} + +Name: python-%{modname} +Version: 0.30.2 +Release: 1%{?dist} +Summary: Highly concurrent networking library +%if %bundle_dns +License: MIT and ISC +%else +License: MIT +%endif + +URL: http://eventlet.net +Source0: https://github.com/eventlet/%{modname}/archive/v%{version}.zip +Source1: %{pypi_source dnspython 1.16.0 zip} +Patch0: switch_to_python_cryptography.patch + +# Backport of upstream PR to introduce compatibility with Python 3.10 +# https://github.com/eventlet/eventlet/pull/715 +Patch715: https://github.com/eventlet/eventlet/pull/715.patch + +BuildArch: noarch + +%description +Eventlet is a networking library written in Python. It achieves high +scalability by using non-blocking io while at the same time retaining +high programmer usability by using coroutines to make the non-blocking +io operations appear blocking at the source code level. + +%package -n python3-%{modname} +Summary: %{summary} +BuildArch: noarch +BuildRequires: python3-devel +BuildRequires: python3-setuptools +BuildRequires: python3dist(greenlet) >= 0.3 +BuildRequires: python3dist(monotonic) >= 1.4 +BuildRequires: python3dist(six) >= 1.10 +BuildRequires: python3-nose +BuildRequires: python3-pyOpenSSL + +%if %bundle_dns +Provides: bundled(python3dist(dnspython)) = 1.16.0 +BuildRequires: python3-cryptography +Recommends: python3-cryptography +%else +BuildRequires: python3dist(dnspython) >= 1.15 +BuildRequires: python3dist(dnspython) < 2 +%endif + +%{?python_provide:%python_provide python3-%{modname}} + + +%description -n python3-%{modname} +Eventlet is a networking library written in Python. It achieves high +scalability by using non-blocking io while at the same time retaining +high programmer usability by using coroutines to make the non-blocking +io operations appear blocking at the source code level. + +%package -n python3-%{modname}-doc +Summary: Documentation for python3-%{modname} +BuildRequires: python3-sphinx +BuildRequires: python3-zmq + +%description -n python3-%{modname}-doc +%{summary}. + +%prep +%if %bundle_dns +%setup -n %{modname}-%{version} -q -a1 +%else +%setup -n %{modname}-%{version} -q +%endif +%patch -P 715 -p1 +# Remove dependency on enum-compat from setup.py +# enum-compat is not needed for Python 3 +sed -i "/'enum-compat',/d" setup.py +%if %bundle_dns +# We bundle last version of dns1 as eventlet does not support yet dns2 +pushd dnspython-1.16.0 +%patch -P 0 -p1 +grep -lRZ "dns\." dns | xargs -0 -l sed -i -e 's/\([^[a-zA-Z]\)dns\./\1eventlet\.dns\./g' +grep -lRZ "^import dns$" dns | xargs -0 -l sed -i -e 's/^import\ dns$/import\ eventlet\.dns/' +popd +mv dnspython-1.16.0/dns eventlet +sed -i '/dnspython >= 1.15.0, < 2.0.0/d' setup.py +sed -i "s/import_patched('dns/import_patched('eventlet\.dns/g" eventlet/support/greendns.py +cp -a dnspython-1.16.0/LICENSE LICENSE.dns +rm -vrf dnspython-1.16.0 +%endif +rm -vrf *.egg-info + +%build +%py3_build + +# Disable setting up dns (we have no /etc/resolv.conf in mock +export EVENTLET_NO_GREENDNS=yes +export PYTHONPATH=$(pwd) +sphinx-build-%{python3_version} -b html -d doctrees doc html-3 + +%install +%py3_install +rm -vrf %{buildroot}%{python3_sitelib}/tests + +%check +# Disable setting up dns (we have no /etc/resolv.conf in mock +export EVENTLET_NO_GREENDNS=yes +# Disable 2 tests that require dns that we just disabled +rm -f tests/greendns_test.py +rm -f tests/socket_test.py +# Tests are written only for Python 3 +nosetests-%{python3_version} -v + +%files -n python3-%{modname} +%doc README.rst AUTHORS LICENSE NEWS +%license LICENSE +%if %bundle_dns +%license LICENSE.dns +%endif +%{python3_sitelib}/%{modname}/ +%{python3_sitelib}/%{modname}-*.egg-info/ + +%files -n python3-%{modname}-doc +%license LICENSE +%doc html-3 + +%changelog +* Sun Mar 07 2021 Kevin Fenzi - 0.30.2-1 +- Update to 0.30.2. Fixes rhbz#1934511 + +* Sun Feb 07 2021 Kevin Fenzi - 0.30.1-1 +- Update to 0.30.1. Fixes rhbz#1923933 + +* Wed Jan 27 2021 Fedora Release Engineering - 0.30.0-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild + +* Sat Dec 26 2020 Kevin Fenzi - 0.30.0-1 +- Update to 0.30.0. (rhbz#1907221) + +* Mon Nov 30 2020 Joel Capitao - 0.29.1-2.20201102git087ba743 +- Bundle dns1 (rhbz#1896191) + +* Fri Nov 06 2020 Joel Capitao - 0.29.1-1.20201102git087ba743 +- Update to 0.29.1.20201102git087ba743. (rhbz#1862178) + +* Sat Oct 10 2020 Kevin Fenzi - 0.26.0-1 +- Update to 0.26.0. + +* Wed Jul 29 2020 Fedora Release Engineering - 0.25.2-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild + +* Sun May 24 2020 Miro Hrončok - 0.25.2-2 +- Rebuilt for Python 3.9 + +* Sat Apr 18 2020 Kevin Fenzi - 0.25.2-1 +- Update to 0.25.2. Fixes bug #1822602 + +* Thu Jan 30 2020 Fedora Release Engineering - 0.25.1-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild + +* Thu Sep 26 2019 Miro Hrončok - 0.25.1-2 +- Subpackage python2-eventlet has been removed + See https://fedoraproject.org/wiki/Changes/Mass_Python_2_Package_Removal + +* Thu Aug 22 2019 Kevin Fenzi - 0.25.1-1 +- Update to 0.25.1. Fixes bug #1744357 + +* Mon Aug 19 2019 Miro Hrončok - 0.25.0-3 +- Rebuilt for Python 3.8 + +* Fri Jul 26 2019 Fedora Release Engineering - 0.25.0-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild + +* Tue May 28 2019 Kevin Fenzi - 0.25.0-1 +- Update to 0.25.0. Fixes bug #1713639 + +* Sat Mar 09 2019 Kevin Fenzi - 0.24.1-4 +- Drop python2-eventlet-doc subpackage as python2-sphinx is going away. + +* Sat Feb 02 2019 Fedora Release Engineering - 0.24.1-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild + +* Tue Nov 20 2018 Igor Gnatenko - 0.24.1-2 +- use python dependency generator + +* Sun Oct 14 2018 Kevin Fenzi - 0.24.1-1 +- Update to 0.24.1. Fixes bug #1611023 + +* Sat Jul 14 2018 Fedora Release Engineering - 0.23.0-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild + +* Fri Jun 22 2018 Miro Hrončok - 0.23.0-1 +- Update to 0.23.0 (#1575434) +- Add patch for Python 3.7 (#1594248) + +* Tue Jun 19 2018 Miro Hrončok - 0.22.1-2 +- Rebuilt for Python 3.7 + +* Sun Feb 18 2018 Kevin Fenzi - 0.22.1-1 +- Update to 0.22.1. Fixes bug #1546471 + +* Fri Feb 09 2018 Fedora Release Engineering - 0.22.0-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild + +* Sat Jan 13 2018 Igor Gnatenko - 0.22.0-1 +- Update to 0.22.0 + +* Tue Oct 3 2017 Haïkel Guémar - 0.21.0-3 +- Fix upstream #401 +- Fix compat with PyOpenSSL 17.3.0 +- Cleanup BR + +* Thu Jul 27 2017 Fedora Release Engineering - 0.21.0-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild + +* Tue May 23 2017 Lumír Balhar - 0.21.0-1 +- Upstream 0.21.0 +- Fix issue with enum-compat dependency for dependent packages +- Enable tests +- Fix tracebacks during docs generating by install python[23]-zmq + +* Tue Apr 25 2017 Haïkel Guémar - 0.20.1-1 +- Upstream 0.20.1 + +* Sat Feb 11 2017 Fedora Release Engineering - 0.18.4-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild + +* Mon Dec 19 2016 Miro Hrončok - 0.18.4-3 +- Rebuild for Python 3.6 + +* Tue Jul 19 2016 Fedora Release Engineering - 0.18.4-2 +- https://fedoraproject.org/wiki/Changes/Automatic_Provides_for_Python_RPM_Packages + +* Mon Apr 25 2016 Kevin Fenzi - 0.18.4-1 +- Update to 0.18.4. Fixes bug #1329993 + +* Thu Feb 04 2016 Fedora Release Engineering - 0.17.4-6 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_24_Mass_Rebuild + +* Tue Nov 10 2015 Fedora Release Engineering - 0.17.4-5 +- Rebuilt for https://fedoraproject.org/wiki/Changes/python3.5 + +* Mon Oct 19 2015 Jon Schlueter 0.17.4-4 +- greenio: send() was running empty loop on ENOTCONN rhbz#1268351 + +* Thu Sep 03 2015 Pádraig Brady - 0.17.4-3 +- Tighten up Provides: and Obsoletes: for previous change + +* Tue Sep 01 2015 Chandan Kumar - 0.17.4-2 +- Added python3 support + +* Wed Jul 22 2015 Pádraig Brady - 0.17.4-1 +- Latest upstream + +* Thu Jun 18 2015 Fedora Release Engineering - 0.17.3-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild + +* Tue Apr 14 2015 Pádraig Brady - 0.17.3-1 +- Latest upstream + +* Tue Mar 31 2015 Pádraig Brady - 0.17.1-1 +- Latest upstream + +* Tue Sep 02 2014 Pádraig Brady - 0.15.2-1 +- Latest upstream + +* Sat Jun 07 2014 Fedora Release Engineering - 0.14.0-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild + +* Mon Oct 28 2013 Alan Pevec - 0.14.0-1 +- Update to 0.14.0 + +* Sun Aug 04 2013 Fedora Release Engineering - 0.12.0-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_20_Mass_Rebuild + +* Wed Feb 20 2013 Pádraig Brady - 0.9.17-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild + +* Mon Nov 12 2012 Pádraig Brady - 0.9.16-7 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild + +* Tue Mar 27 2012 Pádraig Brady - 0.9.16-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild + +* Wed Nov 09 2011 Pádraig Brady = 6.1 + +* Sat Aug 27 2011 Kevin Fenzi - 0.9.16-1 +- Update to 0.9.16 + +* Tue Feb 08 2011 Fedora Release Engineering - 0.9.12-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild + +* Wed Sep 08 2010 Lev Shamardin - 0.9.12-1 +- Updated to version 0.9.12. + +* Wed Jul 28 2010 Lev Shamardin - 0.9.9-1 +- Updated to version 0.9.9. + +* Wed Apr 14 2010 Lev Shamardin - 0.9.7-1 +- Initial package version.