Skip to content

Commit 1a26892

Browse files
Kyle-Verhoogbrettlangdonjd
authored
add support for Python 3.9 (#1750)
* add support for Python 3.9 * fix asyncio tests; don't test py39 and gevent * fix asyncio * add release note Co-authored-by: Brett Langdon <[email protected]> Co-authored-by: Julien Danjou <[email protected]>
1 parent 7a9e689 commit 1a26892

File tree

7 files changed

+78
-64
lines changed

7 files changed

+78
-64
lines changed

ddtrace/contrib/asyncio/compat.py

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
1-
import sys
1+
import asyncio
2+
3+
4+
if hasattr(asyncio, "current_task"):
5+
6+
def asyncio_current_task():
7+
try:
8+
return asyncio.current_task()
9+
except RuntimeError:
10+
return None
11+
212

3-
# asyncio.Task.current_task method is deprecated and will be removed in Python
4-
# 3.9. Instead use asyncio.current_task
5-
if sys.version_info >= (3, 7, 0):
6-
from asyncio import current_task as asyncio_current_task
713
else:
8-
import asyncio
914

10-
asyncio_current_task = asyncio.Task.current_task
15+
def asyncio_current_task():
16+
return asyncio.Task.current_task()
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
---
2+
prelude: >
3+
Add support for Python 3.9

riotfile.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
3.6,
5050
3.7,
5151
3.8,
52+
3.9,
5253
],
5354
pkgs=[("msgpack", [""])],
5455
),

setup.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@ def get_exts_for(name):
174174
"Programming Language :: Python :: 3.6",
175175
"Programming Language :: Python :: 3.7",
176176
"Programming Language :: Python :: 3.8",
177+
"Programming Language :: Python :: 3.9",
177178
],
178179
use_scm_version=True,
179180
setup_requires=["setuptools_scm[toml]>=4", "cython"],

tests/contrib/asyncio/test_tracer.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import pytest
44
from ddtrace.compat import CONTEXTVARS_IS_AVAILABLE
5+
from ddtrace.contrib.asyncio.compat import asyncio_current_task
56

67
from .utils import AsyncioTestCase, mark_asyncio
78

@@ -16,7 +17,7 @@ class TestAsyncioTracer(AsyncioTestCase):
1617
def test_get_call_context(self):
1718
# it should return the context attached to the current Task
1819
# or create a new one
19-
task = asyncio.Task.current_task()
20+
task = asyncio_current_task()
2021
ctx = getattr(task, "__datadog_context", None)
2122
assert ctx is None
2223
# get the context from the loop creates a new one that
@@ -77,7 +78,7 @@ def test_context_task_none(self):
7778
# it should handle the case where a Task is not available
7879
# Note: the @mark_asyncio is missing to simulate an execution
7980
# without a Task
80-
task = asyncio.Task.current_task()
81+
task = asyncio_current_task()
8182
# the task is not available
8283
assert task is None
8384
# but a new Context is still created making the operation safe

tests/contrib/asyncio/test_tracer_safety.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import asyncio
22

33
from ddtrace.provider import DefaultContextProvider
4+
from ddtrace.contrib.asyncio.compat import asyncio_current_task
45
from .utils import AsyncioTestCase, mark_asyncio
56

67

@@ -22,7 +23,8 @@ def test_get_call_context(self):
2223
ctx = self.tracer.get_call_context()
2324
assert ctx is not None
2425
# test that it behaves the wrong way
25-
task = asyncio.Task.current_task()
26+
task = asyncio_current_task()
27+
assert task
2628
task_ctx = getattr(task, "__datadog_context", None)
2729
assert task_ctx is None
2830

tox.ini

Lines changed: 54 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -20,31 +20,31 @@ envlist =
2020
wait
2121
{py27,py35,py36,py37,py38,py39}-profile{,-gevent}
2222
{py27,py35,py36,py37,py38,py39}-profile-minreqs{,-gevent}
23-
{py27,py35,py36,py37,py38}-integration
24-
py{27,35,36,37,38}-vendor
25-
{py27,py35,py36,py37,py38}-ddtracerun
26-
{py27,py35,py36,py37,py38}-test_logging
23+
py{27,35,36,37,38,39}-integration
24+
py{27,35,36,37,38,39}-vendor
25+
py{27,35,36,37,38,39}-ddtracerun
26+
py{27,35,36,37,38,39}-test_logging
2727
# Integrations environments
2828
# aiobotocore dropped Python 3.5 support in 0.12
2929
aiobotocore_contrib-{py35}-aiobotocore{02,03,04,05,07,08,09,010,011}
3030
aiobotocore_contrib-{py36}-aiobotocore{02,03,04,05,07,08,09,010,011,012}
3131
# aiobotocore 0.2 and 0.4 do not work because they use async as a reserved keyword
32-
aiobotocore_contrib-py{37,38}-aiobotocore{03,05,07,08,09,010,011,012}
32+
aiobotocore_contrib-py{37,38,39}-aiobotocore{03,05,07,08,09,010,011,012}
3333
# Python 3.7 needs at least aiohttp 2.3
3434
aiohttp_contrib-{py35,py36}-aiohttp{12,13,20,21,22}-aiohttp_jinja{012,013}-yarl
3535
aiohttp_contrib-{py35,py36,py37,py38}-aiohttp23-aiohttp_jinja015-yarl10
3636
aiohttp_contrib-{py35,py36,py37}-aiohttp{30,31,32,33,35,36}-aiohttp_jinja{015}-yarl10
3737
aiohttp_contrib-py38-aiohttp{30,31,32,33,36}-aiohttp_jinja015-yarl10
3838
aiopg_contrib-{py35,py36}-aiopg{012,015}
39-
aiopg_contrib-py{37,38}-aiopg015
40-
algoliasearch_contrib-py{27,35,36,37,38}-algoliasearch{1,2,}
41-
asgi_contrib-{py36,py37,py38}-asgiref{min,}
42-
asyncio_contrib-{py35,py36,py37,py38}
39+
aiopg_contrib-py{37,38,39}-aiopg015
40+
algoliasearch_contrib-py{27,35,36,37,38,39}-algoliasearch{1,2,}
41+
asgi_contrib-py{36,37,38,39}-asgiref{min,}
42+
asyncio_contrib-py{35,36,37,38,39}
4343
# boto needs moto<1 and moto<1 does not support Python >= 3.7
4444
boto_contrib-{py27,py35,py36}-boto
45-
botocore_contrib-{py27,py35,py36,py37,py38}-botocore
46-
bottle_contrib{,_autopatch}-py{27,35,36,37,38}-bottle{11,12,}-webtest
47-
cassandra_contrib-{py27,py35,py36,py37,py38}-cassandra{35,36,37,38,315}
45+
botocore_contrib-py{27,35,36,37,38,39}-botocore
46+
bottle_contrib{,_autopatch}-py{27,35,36,37,38,39}-bottle{11,12,}-webtest
47+
cassandra_contrib-py{27,35,36,37,38,39}-cassandra{35,36,37,38,315}
4848
# Non-4.x celery should be able to use the older redis lib, since it locks to an older kombu
4949
celery_contrib-py{27,35,36}-celery31-redis210
5050
# 4.x celery bumps kombu to 4.4+, which requires redis 3.2 or later, this tests against
@@ -56,9 +56,9 @@ envlist =
5656
celery_contrib-py{27,35,36}-celery42-redis210-kombu43
5757
# Celery 4.3 wants Kombu >= 4.4 and Redis >= 3.2
5858
# Python 3.7 needs Celery 4.3
59-
celery_contrib-py{27,35,36,37,38}-celery43-redis32-kombu44
60-
consul_contrib-py{27,35,36,37,38}-consul{07,10,11,}
61-
dbapi_contrib-py{27,35,36,37,38}
59+
celery_contrib-py{27,35,36,37,38,39}-celery43-redis32-kombu44
60+
consul_contrib-py{27,35,36,37,38,39}-consul{07,10,11,}
61+
dbapi_contrib-py{27,35,36,37,38,39}
6262
# Django Python version support
6363
# 1.11 2.7, 3.4, 3.5, 3.6, 3.7 (added in 1.11.17)
6464
# 2.0 3.4, 3.5, 3.6, 3.7
@@ -69,14 +69,14 @@ envlist =
6969
# Source: https://docs.djangoproject.com/en/dev/faq/install/#what-python-version-can-i-use-with-django
7070
django_contrib{,_migration}-py{27,35,36}-django{18,111}-djangopylibmc06-djangoredis45-pylibmc-redis{210}-memcached-test_django
7171
django_contrib{,_migration}-py35-django{20,21,22}-djangopylibmc06-djangoredis45-pylibmc-redis{210}-memcached-test_django
72-
django_contrib{,_migration}-py{36,37,38}-django{20,21,22,30,}-djangopylibmc06-djangoredis45-pylibmc-redis{210}-memcached-test_django
72+
django_contrib{,_migration}-py{36,37,38,39}-django{20,21,22,30,}-djangopylibmc06-djangoredis45-pylibmc-redis{210}-memcached-test_django
7373
django_drf_contrib-py{27,35,36}-django{111}-djangorestframework{34,37}-test_django
7474
django_drf_contrib-py35-django{22}-djangorestframework{38,310,}-test_django
7575
django_drf_contrib-py{36,37}-django{22}-djangorestframework{38,310,}-test_django
76-
django_drf_contrib-py{36,37,38}-django30-djangorestframework310-test_django
77-
django_drf_contrib-py{36,37,38}-django-djangorestframework311-test_django
76+
django_drf_contrib-py{36,37,38,39}-django30-djangorestframework310-test_django
77+
django_drf_contrib-py{36,37,38,39}-django-djangorestframework311-test_django
7878
dogpile_contrib-py{27,35}-dogpilecache{06,07,08,09}
79-
dogpile_contrib-py{36,37,38}-dogpilecache{06,07,08,09,10,}
79+
dogpile_contrib-py{36,37,38,39}-dogpilecache{06,07,08,09,10,}
8080
elasticsearch_contrib-{py27,py35,py36}-elasticsearch{16,17,18,23,24,51,52,53,54,63,64}
8181
elasticsearch_contrib-{py27,py35,py36}-elasticsearch1{100}
8282
elasticsearch_contrib-{py27,py35,py36}-elasticsearch2{50}
@@ -87,10 +87,10 @@ envlist =
8787
flask_contrib{,_autopatch}-{py27,py35,py36}-flask{010,011,012,10}-blinker
8888
# Flask <=0.9 does not support Python 3
8989
flask_contrib{,_autopatch}-{py27}-flask{09}-blinker
90-
flask_cache_contrib-{py27,py35,py36,py37,py38}-flask{010,011,012}-flaskcache{013}-memcached-redis{210}-blinker
91-
flask_cache_contrib-{py27}-flask{010,011}-flaskcache{012}-memcached-redis{210}-blinker
90+
flask_cache_contrib-py{27,35,36,37,38,39}-flask{010,011,012}-flaskcache{013}-memcached-redis{210}-blinker
91+
flask_cache_contrib-py27-flask{010,011}-flaskcache{012}-memcached-redis{210}-blinker
9292
futures_contrib-py27-futures{30,31,32,}
93-
futures_contrib-py{35,36,37,38}
93+
futures_contrib-py{35,36,37,38,39}
9494
gevent_contrib-py27-gevent{11,12,13}-sslmodules
9595
gevent_contrib-py{35,36}-gevent{11,12,13}-sslmodules3-sslmodules
9696
gevent_contrib-py{37,38}-gevent{13,14}-sslmodules3-sslmodules
@@ -103,56 +103,56 @@ envlist =
103103
grpc_contrib-py{27,35,36}-grpc{112,114,118,120,121,122}-googleapis-common-protos
104104
grpc_contrib-py{37}-grpc{114,118,120,121,122,124,126,128,}-googleapis-common-protos
105105
grpc_contrib-py{38}-grpc{124,126,128,}-googleapis-common-protos
106-
httplib_contrib-py{27,35,36,37,38}
107-
jinja2_contrib-py{27,35,36,37,38}-jinja{27,28,29,210,211,}
106+
httplib_contrib-py{27,35,36,37,38,39}
107+
jinja2_contrib-py{27,35,36,37,38,39}-jinja{27,28,29,210,211,}
108108
kombu_contrib-py{27,35,36}-kombu{40,41,42,43,44,45,46,}
109109
# Kombu >= 4.2 only supports Python 3.7+
110-
kombu_contrib-py{37,38}-kombu{42,43,44,45,46,}
111-
mako_contrib-py{27,35,36,37,38}-mako{010,100,110,}
112-
molten_contrib-py{36,37,38}-molten{06,07,10,}
113-
mongoengine_contrib-py{27,35,36,37,38}-mongoengine{015,016,017,018,}-pymongo
114-
mysql_contrib-py{27,35,36,37,38}-mysqlconnector{80,}
110+
kombu_contrib-py{37,38,39}-kombu{42,43,44,45,46,}
111+
mako_contrib-py{27,35,36,37,38,39}-mako{010,100,110,}
112+
molten_contrib-py{36,37,38,39}-molten{06,07,10,}
113+
mongoengine_contrib-py{27,35,36,37,38,39}-mongoengine{015,016,017,018,}-pymongo
114+
mysql_contrib-py{27,35,36,37,38,39}-mysqlconnector{80,}
115115
mysqldb_contrib-py27-mysqldb{12,}
116-
mysqldb_contrib-py{27,35,36,37,38}-mysqlclient{13,14,}
116+
mysqldb_contrib-py{27,35,36,37,38,39}-mysqlclient{13,14,}
117117
psycopg_contrib-py{27,35,36}-psycopg2{24,25,26,27,28}
118118
psycopg_contrib-py37-psycopg2{27,28}
119119
# psycopg <2.7 doesn't support Python 3.8: https://github.com/psycopg/psycopg2/issues/854
120-
psycopg_contrib-py{38}-psycopg2{28}
121-
pylibmc_contrib-py{27,35,36,37,38}-pylibmc{140,150,}
120+
psycopg_contrib-py{38,39}-psycopg2{28}
121+
pylibmc_contrib-py{27,35,36,37,38,39}-pylibmc{140,150,}
122122
pylons_contrib-py27-pylons{096,097,010,10,}
123-
pymemcache_contrib{,_autopatch}-{py27,py35,py36,py37,py38}-pymemcache{130,140}
123+
pymemcache_contrib{,_autopatch}-py{27,35,36,37,38,39}-pymemcache{130,140}
124124
pymongo_contrib-py{27,35,36,37}-pymongo{30,31,32,33,34,35,36,37,38,39,310,}-mongoengine
125125
# pymongo does not yet support Python 3.8: https://github.com/pymssql/pymssql/issues/586
126126
# but these tests still work.
127-
pymongo_contrib-py38-pymongo{30,31,32,33,35,36,37,38,39,310,}-mongoengine
128-
pymysql_contrib-py{27,35,36,37,38}-pymysql{07,08,09,}
129-
pynamodb_contrib-{py27,py35,py36,py37,py38}-pynamodb{40,41,42,43,}-moto1
130-
pyodbc_contrib-py{27,35,36,37,38}-pyodbc{3,4}
131-
pyramid_contrib{,_autopatch}-py{27,35,36,37,38}-pyramid{17,18,19,110,}-webtest
132-
redis_contrib-py{27,35,36,37,38}-redis{210,30,32,33,34,35,}
133-
rediscluster_contrib-py{27,35,36,37,38}-rediscluster{135,136,200,}-redis210
134-
requests_contrib{,_autopatch}-{py27,py35,py36,py37,py38}-requests{208,209,210,211,212,213,219}
127+
pymongo_contrib-py{38,39}-pymongo{30,31,32,33,35,36,37,38,39,310,}-mongoengine
128+
pymysql_contrib-py{27,35,36,37,38,39}-pymysql{07,08,09,}
129+
pynamodb_contrib-py{27,35,36,37,38,39}-pynamodb{40,41,42,43,}-moto1
130+
pyodbc_contrib-py{27,35,36,37,38,39}-pyodbc{3,4}
131+
pyramid_contrib{,_autopatch}-py{27,35,36,37,38,39}-pyramid{17,18,19,110,}-webtest
132+
redis_contrib-py{27,35,36,37,38,39}-redis{210,30,32,33,34,35,}
133+
rediscluster_contrib-py{27,35,36,37,38,39}-rediscluster{135,136,200,}-redis210
134+
requests_contrib{,_autopatch}-py{27,35,36,37,38,39}-requests{208,209,210,211,212,213,219}
135135
# python 3.6 requests + gevent regression test
136136
# DEV: This is a known issue for gevent 1.1, suggestion is to upgrade to gevent > 1.2
137137
# https://github.com/gevent/gevent/issues/903
138138
requests_gevent_contrib-{py36}-requests{208,209,210,211,212,213,219}-gevent{12,13}
139139
requests_gevent_contrib-py{37,38}-requests{208,209,210,211,212,213,219}-gevent13
140-
sanic_contrib-py{36,37,38}-sanic{1906,1909,1912,2003,2006}
141-
sqlalchemy_contrib-py{27,35,36,37,38}-sqlalchemy{10,11,12,13,}-psycopg228-mysqlconnector
142-
sqlite3_contrib-{py27,py35,py36,py37,py38}-sqlite3
143-
starlette_contrib-{py36,py37,py38}-starlette{13,}
144-
tornado_contrib-py{27,35,36,37,38}-tornado{44,45}
145-
tornado_contrib-py{37,38}-tornado{50,51,60,}
140+
sanic_contrib-py{36,37,38,39}-sanic{1906,1909,1912,2003,2006}
141+
sqlalchemy_contrib-py{27,35,36,37,38,39}-sqlalchemy{10,11,12,13,}-psycopg228-mysqlconnector
142+
sqlite3_contrib-py{27,35,36,37,38,39}-sqlite3
143+
starlette_contrib-py{36,37,38,39}-starlette{13,}
144+
tornado_contrib-py{27,35,36,37,38,39}-tornado{44,45}
145+
tornado_contrib-py{37,38,39}-tornado{50,51,60,}
146146
tornado_contrib-py27-tornado{44,45}-futures{30,31,32,}
147-
vertica_contrib-{py27,py35,py36,py37,py38}-vertica{060,070}
147+
vertica_contrib-py{27,35,36,37,38,39}-vertica{060,070}
148148
# Opentracer
149-
{py27,py35,py36,py37,py38}-opentracer
150-
{py35,py36,py37,py38}-opentracer_asyncio
151-
py{35,36,37,38}-opentracer_tornado-tornado{44,45,50,60,}
152-
{py27}-opentracer_gevent-gevent{10}
153-
{py27,py35,py36}-opentracer_gevent-gevent{11,12}
149+
py{27,35,36,37,38,39}-opentracer
150+
py{35,36,37,38}-opentracer_asyncio
151+
py{35,36,37,38,39}-opentracer_tornado-tornado{44,45,50,60,}
152+
py27-opentracer_gevent-gevent{10}
153+
py{27,35,36}-opentracer_gevent-gevent{11,12}
154154
py{37,38}-opentracer_gevent-gevent{13,14}
155-
benchmarks-{py27,py35,py36,py37,py38}
155+
benchmarks-py{27,35,36,37,38,39}
156156

157157
isolated_build = true
158158

0 commit comments

Comments
 (0)