elasticapm/utils/compat.py (46 lines of code) (raw):

# -*- coding: utf-8 -*- # BSD 3-Clause License # # Copyright (c) 2019, Elasticsearch BV # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright notice, this # list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # # * Neither the name of the copyright holder nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import atexit import functools import platform from typing import TypeVar _AnnotatedFunctionT = TypeVar("_AnnotatedFunctionT") def noop_decorator(func: _AnnotatedFunctionT) -> _AnnotatedFunctionT: @functools.wraps(func) def wrapped(*args, **kwargs): return func(*args, **kwargs) return wrapped def atexit_register(func) -> None: """ Uses either uwsgi's atexit mechanism, or atexit from the stdlib. When running under uwsgi, using their atexit handler is more reliable, especially when using gevent :param func: the function to call at exit """ try: import uwsgi orig = getattr(uwsgi, "atexit", None) def uwsgi_atexit() -> None: if callable(orig): orig() func() uwsgi.atexit = uwsgi_atexit except ImportError: atexit.register(func) def get_default_library_patters(): """ Returns library paths depending on the used platform. :return: a list of glob paths """ python_version = platform.python_version_tuple() python_implementation = platform.python_implementation() system = platform.system() if python_implementation == "PyPy": if python_version[0] == "2": return ["*/lib-python/%s.%s/*" % python_version[:2], "*/site-packages/*"] else: return ["*/lib-python/%s/*" % python_version[0], "*/site-packages/*"] else: if system == "Windows": return [r"*\lib\*"] return ["*/lib/python%s.%s/*" % python_version[:2], "*/lib64/python%s.%s/*" % python_version[:2]] def multidict_to_dict(d): """ Turns a werkzeug.MultiDict or django.MultiValueDict into a dict with list values :param d: a MultiDict or MultiValueDict instance :return: a dict instance """ return dict((k, v[0] if len(v) == 1 else v) for k, v in d.lists()) try: import uwsgi # check if a master is running before importing postfork if uwsgi.masterpid() != 0: from uwsgidecorators import postfork else: def postfork(f): return f except (ImportError, AttributeError): def postfork(f): return f