Skip to content

Commit 23fb12b

Browse files
authored
[core] add six and replace custom compat functions (#751)
* [core] vendor six and replace custom compat functions * make_async_decorator * Add docs about dependencies * remove vendored 'six'
1 parent a1bf836 commit 23fb12b

File tree

5 files changed

+77
-113
lines changed

5 files changed

+77
-113
lines changed

ddtrace/compat.py

Lines changed: 68 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,20 @@
11
import platform
22
import sys
3+
import textwrap
4+
5+
import six
6+
7+
__all__ = [
8+
'httplib',
9+
'iteritems',
10+
'PY2',
11+
'Queue',
12+
'stringify',
13+
'StringIO',
14+
'urlencode',
15+
'parse',
16+
'reraise',
17+
]
318

419
PYTHON_VERSION_INFO = sys.version_info
520
PY2 = sys.version_info[0] == 2
@@ -8,32 +23,58 @@
823
PYTHON_VERSION = platform.python_version()
924
PYTHON_INTERPRETER = platform.python_implementation()
1025

11-
stringify = str
12-
13-
if PY2:
14-
from urllib import urlencode
15-
import httplib
16-
stringify = unicode
17-
from Queue import Queue
18-
try:
19-
from cStringIO import StringIO
20-
except ImportError:
21-
from StringIO import StringIO
22-
else:
23-
from queue import Queue
24-
from urllib.parse import urlencode
25-
import http.client as httplib
26-
from io import StringIO
27-
2826
try:
29-
import urlparse as parse
27+
StringIO = six.moves.cStringIO
3028
except ImportError:
31-
from urllib import parse
29+
StringIO = six.StringIO
3230

33-
try:
31+
httplib = six.moves.http_client
32+
urlencode = six.moves.urllib.parse.urlencode
33+
parse = six.moves.urllib.parse
34+
Queue = six.moves.queue.Queue
35+
iteritems = six.iteritems
36+
reraise = six.reraise
37+
38+
stringify = six.text_type
39+
string_type = six.string_types[0]
40+
msgpack_type = six.binary_type
41+
# DEV: `six` doesn't have `float` in `integer_types`
42+
numeric_types = six.integer_types + (float, )
43+
44+
45+
if PYTHON_VERSION_INFO[0:2] >= (3, 4):
3446
from asyncio import iscoroutinefunction
35-
from .compat_async import _make_async_decorator as make_async_decorator
36-
except ImportError:
47+
48+
# Execute from a string to get around syntax errors from `yield from`
49+
# DEV: The idea to do this was stolen from `six`
50+
# https://github.com/benjaminp/six/blob/15e31431af97e5e64b80af0a3f598d382bcdd49a/six.py#L719-L737
51+
six.exec_(textwrap.dedent("""
52+
import functools
53+
import asyncio
54+
55+
56+
def make_async_decorator(tracer, coro, *params, **kw_params):
57+
\"\"\"
58+
Decorator factory that creates an asynchronous wrapper that yields
59+
a coroutine result. This factory is required to handle Python 2
60+
compatibilities.
61+
62+
:param object tracer: the tracer instance that is used
63+
:param function f: the coroutine that must be executed
64+
:param tuple params: arguments given to the Tracer.trace()
65+
:param dict kw_params: keyword arguments given to the Tracer.trace()
66+
\"\"\"
67+
@functools.wraps(coro)
68+
@asyncio.coroutine
69+
def func_wrapper(*args, **kwargs):
70+
with tracer.trace(*params, **kw_params):
71+
result = yield from coro(*args, **kwargs) # noqa: E999
72+
return result
73+
74+
return func_wrapper
75+
"""))
76+
77+
else:
3778
# asyncio is missing so we can't have coroutines; these
3879
# functions are used only to ensure code executions in case
3980
# of an unexpected behavior
@@ -44,30 +85,24 @@ def make_async_decorator(tracer, fn, *params, **kw_params):
4485
return fn
4586

4687

47-
def iteritems(obj, **kwargs):
48-
func = getattr(obj, "iteritems", None)
49-
if not func:
50-
func = obj.items
51-
return func(**kwargs)
52-
53-
88+
# DEV: There is `six.u()` which does something similar, but doesn't have the guard around `hasattr(s, 'decode')`
5489
def to_unicode(s):
5590
""" Return a unicode string for the given bytes or string instance. """
5691
# No reason to decode if we already have the unicode compatible object we expect
57-
# DEV: `stringify` will be a `str` for python 3 and `unicode` for python 2
92+
# DEV: `six.text_type` will be a `str` for python 3 and `unicode` for python 2
5893
# DEV: Double decoding a `unicode` can cause a `UnicodeEncodeError`
5994
# e.g. `'\xc3\xbf'.decode('utf-8').decode('utf-8')`
60-
if isinstance(s, stringify):
95+
if isinstance(s, six.text_type):
6196
return s
6297

6398
# If the object has a `decode` method, then decode into `utf-8`
6499
# e.g. Python 2 `str`, Python 2/3 `bytearray`, etc
65100
if hasattr(s, 'decode'):
66101
return s.decode('utf-8')
67102

68-
# Always try to coerce the object into the `stringify` object we expect
103+
# Always try to coerce the object into the `six.text_type` object we expect
69104
# e.g. `to_unicode(1)`, `to_unicode(dict(key='value'))`
70-
return stringify(s)
105+
return six.text_type(s)
71106

72107

73108
def get_connection_response(conn):
@@ -86,45 +121,3 @@ def get_connection_response(conn):
86121
return conn.getresponse(buffering=True)
87122
else:
88123
return conn.getresponse()
89-
90-
91-
if PY2:
92-
string_type = basestring
93-
msgpack_type = basestring
94-
numeric_types = (int, long, float)
95-
else:
96-
string_type = str
97-
msgpack_type = bytes
98-
numeric_types = (int, float)
99-
100-
if PY2:
101-
# avoids Python 3 `SyntaxError`
102-
# this block will be replaced with the `six` library
103-
from .utils.reraise import _reraise as reraise
104-
else:
105-
def reraise(tp, value, tb=None):
106-
"""Python 3 re-raise function. This function is internal and
107-
will be replaced entirely with the `six` library.
108-
"""
109-
try:
110-
if value is None:
111-
value = tp()
112-
if value.__traceback__ is not tb:
113-
raise value.with_traceback(tb)
114-
raise value
115-
finally:
116-
value = None
117-
tb = None
118-
119-
120-
__all__ = [
121-
'httplib',
122-
'iteritems',
123-
'PY2',
124-
'Queue',
125-
'stringify',
126-
'StringIO',
127-
'urlencode',
128-
'parse',
129-
'reraise',
130-
]

ddtrace/compat_async.py

Lines changed: 0 additions & 28 deletions
This file was deleted.

ddtrace/utils/reraise.py

Lines changed: 0 additions & 5 deletions
This file was deleted.

setup.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -82,13 +82,14 @@ def run_tests(self):
8282
license='BSD',
8383
packages=find_packages(exclude=['tests*']),
8484
install_requires=[
85-
"wrapt",
86-
"msgpack-python",
85+
'msgpack-python',
86+
'six',
87+
'wrapt',
8788
],
8889
extras_require={
8990
# users can include opentracing by having:
90-
# install_requires=["ddtrace[opentracing]", ...]
91-
"opentracing": ["opentracing>=2.0.0"],
91+
# install_requires=['ddtrace[opentracing]', ...]
92+
'opentracing': ['opentracing>=2.0.0'],
9293
},
9394
# plugin tox
9495
tests_require=['tox', 'flake8'],

tox.ini

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -620,4 +620,7 @@ python_files = test*\.py
620620

621621
[flake8]
622622
max-line-length=120
623-
exclude=.git,__pycache__,.tox,.ddtox,.eggs,*.egg
623+
exclude=
624+
.ddtox,.tox,
625+
.git,__pycache__,
626+
.eggs,*.egg

0 commit comments

Comments
 (0)