mirror of
https://github.com/open-telemetry/opentelemetry-python-contrib.git
synced 2025-08-01 09:13:23 +08:00
Move DD code into its own directory (#6)
This commit is contained in:
151
reference/ddtrace/compat.py
Normal file
151
reference/ddtrace/compat.py
Normal file
@ -0,0 +1,151 @@
|
||||
import platform
|
||||
import re
|
||||
import sys
|
||||
import textwrap
|
||||
|
||||
from ddtrace.vendor import six
|
||||
|
||||
__all__ = [
|
||||
'httplib',
|
||||
'iteritems',
|
||||
'PY2',
|
||||
'Queue',
|
||||
'stringify',
|
||||
'StringIO',
|
||||
'urlencode',
|
||||
'parse',
|
||||
'reraise',
|
||||
]
|
||||
|
||||
PYTHON_VERSION_INFO = sys.version_info
|
||||
PY2 = sys.version_info[0] == 2
|
||||
PY3 = sys.version_info[0] == 3
|
||||
|
||||
# Infos about python passed to the trace agent through the header
|
||||
PYTHON_VERSION = platform.python_version()
|
||||
PYTHON_INTERPRETER = platform.python_implementation()
|
||||
|
||||
try:
|
||||
StringIO = six.moves.cStringIO
|
||||
except ImportError:
|
||||
StringIO = six.StringIO
|
||||
|
||||
httplib = six.moves.http_client
|
||||
urlencode = six.moves.urllib.parse.urlencode
|
||||
parse = six.moves.urllib.parse
|
||||
Queue = six.moves.queue.Queue
|
||||
iteritems = six.iteritems
|
||||
reraise = six.reraise
|
||||
reload_module = six.moves.reload_module
|
||||
|
||||
stringify = six.text_type
|
||||
string_type = six.string_types[0]
|
||||
msgpack_type = six.binary_type
|
||||
# DEV: `six` doesn't have `float` in `integer_types`
|
||||
numeric_types = six.integer_types + (float, )
|
||||
|
||||
# Pattern class generated by `re.compile`
|
||||
if PYTHON_VERSION_INFO >= (3, 7):
|
||||
pattern_type = re.Pattern
|
||||
else:
|
||||
pattern_type = re._pattern_type
|
||||
|
||||
|
||||
def is_integer(obj):
|
||||
"""Helper to determine if the provided ``obj`` is an integer type or not"""
|
||||
# DEV: We have to make sure it is an integer and not a boolean
|
||||
# >>> type(True)
|
||||
# <class 'bool'>
|
||||
# >>> isinstance(True, int)
|
||||
# True
|
||||
return isinstance(obj, six.integer_types) and not isinstance(obj, bool)
|
||||
|
||||
|
||||
try:
|
||||
from time import time_ns
|
||||
except ImportError:
|
||||
from time import time as _time
|
||||
|
||||
def time_ns():
|
||||
return int(_time() * 10e5) * 1000
|
||||
|
||||
|
||||
if PYTHON_VERSION_INFO[0:2] >= (3, 4):
|
||||
from asyncio import iscoroutinefunction
|
||||
|
||||
# Execute from a string to get around syntax errors from `yield from`
|
||||
# DEV: The idea to do this was stolen from `six`
|
||||
# https://github.com/benjaminp/six/blob/15e31431af97e5e64b80af0a3f598d382bcdd49a/six.py#L719-L737
|
||||
six.exec_(textwrap.dedent("""
|
||||
import functools
|
||||
import asyncio
|
||||
|
||||
|
||||
def make_async_decorator(tracer, coro, *params, **kw_params):
|
||||
\"\"\"
|
||||
Decorator factory that creates an asynchronous wrapper that yields
|
||||
a coroutine result. This factory is required to handle Python 2
|
||||
compatibilities.
|
||||
|
||||
:param object tracer: the tracer instance that is used
|
||||
:param function f: the coroutine that must be executed
|
||||
:param tuple params: arguments given to the Tracer.trace()
|
||||
:param dict kw_params: keyword arguments given to the Tracer.trace()
|
||||
\"\"\"
|
||||
@functools.wraps(coro)
|
||||
@asyncio.coroutine
|
||||
def func_wrapper(*args, **kwargs):
|
||||
with tracer.trace(*params, **kw_params):
|
||||
result = yield from coro(*args, **kwargs) # noqa: E999
|
||||
return result
|
||||
|
||||
return func_wrapper
|
||||
"""))
|
||||
|
||||
else:
|
||||
# asyncio is missing so we can't have coroutines; these
|
||||
# functions are used only to ensure code executions in case
|
||||
# of an unexpected behavior
|
||||
def iscoroutinefunction(fn):
|
||||
return False
|
||||
|
||||
def make_async_decorator(tracer, fn, *params, **kw_params):
|
||||
return fn
|
||||
|
||||
|
||||
# DEV: There is `six.u()` which does something similar, but doesn't have the guard around `hasattr(s, 'decode')`
|
||||
def to_unicode(s):
|
||||
""" Return a unicode string for the given bytes or string instance. """
|
||||
# No reason to decode if we already have the unicode compatible object we expect
|
||||
# DEV: `six.text_type` will be a `str` for python 3 and `unicode` for python 2
|
||||
# DEV: Double decoding a `unicode` can cause a `UnicodeEncodeError`
|
||||
# e.g. `'\xc3\xbf'.decode('utf-8').decode('utf-8')`
|
||||
if isinstance(s, six.text_type):
|
||||
return s
|
||||
|
||||
# If the object has a `decode` method, then decode into `utf-8`
|
||||
# e.g. Python 2 `str`, Python 2/3 `bytearray`, etc
|
||||
if hasattr(s, 'decode'):
|
||||
return s.decode('utf-8')
|
||||
|
||||
# Always try to coerce the object into the `six.text_type` object we expect
|
||||
# e.g. `to_unicode(1)`, `to_unicode(dict(key='value'))`
|
||||
return six.text_type(s)
|
||||
|
||||
|
||||
def get_connection_response(conn):
|
||||
"""Returns the response for a connection.
|
||||
|
||||
If using Python 2 enable buffering.
|
||||
|
||||
Python 2 does not enable buffering by default resulting in many recv
|
||||
syscalls.
|
||||
|
||||
See:
|
||||
https://bugs.python.org/issue4879
|
||||
https://github.com/python/cpython/commit/3c43fcba8b67ea0cec4a443c755ce5f25990a6cf
|
||||
"""
|
||||
if PY2:
|
||||
return conn.getresponse(buffering=True)
|
||||
else:
|
||||
return conn.getresponse()
|
Reference in New Issue
Block a user