Exemplo n.º 1
0
def test_no_source_file():
    code = compile("lambda x: 12", __file__, "eval")
    with pytest.raises(AttributeError):
        qualname(code)

    fn = eval(code)
    with pytest.raises(AttributeError):
        qualname(code)
Exemplo n.º 2
0
def _get_callable(obj, of_class = None):
    """ Get callable for an object and its full name.

    Supports:

    * functions
    * classes (jumps to __init__())
    * methods
    * @classmethod
    * @property

    :param obj: function|class
    :type obj: Callable
    :param of_class: Class that this method is a member of
    :type of_class: class|None
    :return: (qualname, Callable|None, Class|None). Callable is None for classes without __init__()
    :rtype: (str, Callable|None, Class|None)
    """
    # Cases
    o = obj

    if inspect.isclass(obj):
        try:
            o = obj.__init__
            of_class = obj
        except AttributeError:
            pass

    # Finish
    return qualname(obj), o, of_class
 def allowed_client_methods(self):
     method_names = []
     if self.client_methods_gatekeeper:
         methods = self.client_methods_gatekeeper.allowed
         for method in methods:
             method_names.append(qualname(method))
     return method_names
Exemplo n.º 4
0
def get_qualname(fn):
    # Python >= 3.3 only
    try:
        return fn.__qualname__.split('.')
    except AttributeError:
        pass

    # Python < 3.3
    try:
        import qualname
        return qualname.qualname(fn).split('.')
    except ImportError:
        pass

    # Hack: Issue error if we're wrapping a class method and failed to
    # get the qualname
    import inspect
    context = [
        x[0].f_code.co_name for x in inspect.stack()
        if '__module__' in x[0].f_code.co_names
        and inspect.getmodule(x[0].f_code).__name__ != __name__
    ]
    if len(context) > 0:
        raise Exception(
            'To use a task defined in a class, please upgrade to Python >= 3.3 or install qualname (e.g. pip install qualname)'
        )

    return [fn.__name__]
Exemplo n.º 5
0
 def wrapped(*args, **kwargs):
     before = time.time()
     try:
         return f(*args, **kwargs)
     finally:
         stop = time.time()
         print("{} +{:f} ".format(qualname(f),
                                  (stop - before) * 1000))
Exemplo n.º 6
0
def safe_qualname(obj):
    result = safe_qualname._cache.get(obj)
    if not result:
        try:
            result = qualname(obj)
        except AttributeError:
            result = obj.__name__
        if '<locals>' not in result:
            safe_qualname._cache[obj] = result
    return result
Exemplo n.º 7
0
Arquivo: core.py Projeto: miladh/pylgn
def closure_params(closure):
    """
    Stores closure parameters in a dict

    Parameters
    ----------
    closure : function
            A closure function

    Returns
    -------
    out : dict
        Dictionary

    """
    if sys.version_info >= (3, 4):
        pass
    else:        
        from qualname import qualname

    attrs = {}

    for cell_name, cell in zip(closure.__code__.co_freevars,
                               closure.__closure__):
        cell_contents = cell.cell_contents
        if not callable(cell_contents):
            if "params" not in attrs:
                attrs["params"] = {}
            attrs["params"][cell_name] = cell_contents
            if sys.version_info >= (3, 4):
                attrs["type"] = closure.__qualname__.split(".")[0]
            else:
                attrs["type"] = qualname(closure).split(".")[0]
        else:
            attrs[cell_name] = closure_params(cell_contents)
            if sys.version_info >= (3, 4):
                attrs[cell_name]["type"] = cell_contents.__qualname__.split("."
                                                                            )[0]
            else:
                attrs[cell_name]["type"] = qualname(cell_contents).split(".")[0]
                
    return attrs
Exemplo n.º 8
0
    def filter_queryset(self, request, queryset, view):
        filter_class = getattr(view,'filter_class', None)

        if filter_class is None:
            return queryset

        if not issubclass(filter_class, BaseFilterset):
            raise TypeError("%s expects filter_class to be %s: %s" % (qualname(self.__class__), qualname(BaseFilterset), repr(filter_class)))

        if not hasattr(view,'get_queryset'):
            raise TypeError("%s expects view to have get_queryset method" % (qualname(self.__class__),))

        if issubclass(filter_class, ModelFilterset):
            fs_model = filter_class.Meta.model
            qs_model = view.get_queryset()._document
            if not issubclass(qs_model, fs_model):
                raise TypeError("filter and view document class mismatch: %s vs %s " % (qualname(fs_model), qualname(qs_model)))

        filterset = filter_class(request.query_params)
        return filterset.filter_queryset(queryset)
Exemplo n.º 9
0
def safe_qualname(cls):
    # type: (type) -> str
    result = _safe_qualname_cache.get(cls)
    if not result:
        try:
            result = qualname(cls)
        except (AttributeError, IOError, SyntaxError):
            result = cls.__name__
        if '<locals>' not in result:
            _safe_qualname_cache[cls] = result
    return result
Exemplo n.º 10
0
def autodoc_skip_member(app, what, name, obj, skip, options):
    # skip everything that isn't decorated with @autobahn.public or ..
    if hasattr(obj, '_is_public') and obj._is_public:
        if qualname:
            try:
                qn = qualname(obj)
            except AttributeError as e:
                print(e)
                qn = name
            print('public API: {}.{}'.format(obj.__module__, qn))
        return False
    else:
        return True
Exemplo n.º 11
0
def autodoc_skip_member(app, what, name, obj, skip, options):
    # skip everything that isn't decorated with @autobahn.public or ..
    if hasattr(obj, '_is_public') and obj._is_public:
        if qualname:
            try:
                qn = qualname(obj)
            except AttributeError as e:
                print(e)
                qn = name
            print('public API: {}.{}'.format(obj.__module__, qn))
        return False
    else:
        return True
def model_equation(eqparam, funccomp):
    """
    The module which builds and evaluates the EBM by adding functions parsed through the **funccomp**.

    Input has to be given as `Dictionaries` supplied by ``lowEBMs.Packages.Configuration.importer`` from a specific **configuration.ini**.

    **Function-call arguments** \n

    :param dict eqparam:        Configuration dictionary containing additional information for the model equation:
                                
                                    * C_ao: The systems heat capacity (times the height of the system)

                                        * type: float
                                        * unit: Joule*Meter/Kelvin
                                        * value: > 0

    :param dict funccomp:       Configuration 2D dictionary containing function names and function parameters used:

                                    * funcnames: a dictionary of names of functions defined in ``lowEBMs.Packages.Functions`` which are added up. See :doc:`here <functions>` for a list of functions

                                    * funcparams: a dictionary of functions parameters corresponding to the functions chosen within **funcnames**. For details on the parameters see the specific function :doc:`here <functions>`

    :returns:                   The temperature gradient :math:`\\frac{dT}{dt}` (Kelvin/seconds) 
                                   

    :rtype:                     float or array(float), depending on 0D EBM or 1D EBM. In 1D, output is an array containing the temperature gradient for each latitudinal belt.

    """
    y = 0  #variable which can be used to sum up functions
    funclist = funccomp[
        'funclist']  #Extracting needed arrays from the funccomp array
    funcparam = funccomp['funcparam']
    C_ao = eqparam['c_ao']  #Extracting Equationparameters
    if builtins.parallelization == True:
        C_ao = np.transpose(np.array(
            [C_ao] * len(Vars.Lat))) if np.shape(C_ao) == (
                builtins.number_of_parallels, ) else C_ao
    for funcnum in funclist:
        if builtins.control == True:
            if qualname(funclist[funcnum])[:7] == 'forcing':
                pass
            else:
                y += funclist[funcnum](
                    funcparam[funcnum]
                )  #Calling the selected function and sum them up
        else:
            y += funclist[funcnum](
                funcparam[funcnum]
            )  #Calling the selected function and sum them up
    return y / C_ao  #output of y, weighted with the heat capacity
Exemplo n.º 13
0
def get_path(obj):
    # type: (Any) -> str
    """
    Get full import path to an object.

    .. code:: python

        >>> from abc import abstractmethod
        >>> from objetto.utils.lazy_import import get_path

        >>> get_path(abstractmethod)
        'abc|abstractmethod'

    :param obj: Object.

    :return: Import path.
    :rtype: str

    :raises ValueError: Can't determine consistent import path.
    """

    module = obj.__module__
    if not module:
        error = "can't get module for {}".format(obj)
        raise ValueError(error)

    try:
        qual_name = qualname(obj)
        if not qual_name:
            raise AttributeError()
    except AttributeError:
        qual_name = obj.__name__

    if not qual_name:
        error = "can't get name for {}".format(obj)
        raise ValueError(error)

    path = "|".join((module, qual_name))

    try:
        imported_obj = import_path(path)
    except (ValueError, ImportError):
        imported_obj = None

    if imported_obj is not obj:
        error = "can't get consistent import path to {}".format(obj)
        raise ValueError(error)

    return path
Exemplo n.º 14
0
    def filter_queryset(self, request, queryset, view):
        filter_class = getattr(view, 'filter_class', None)

        if filter_class is None:
            return queryset

        if not issubclass(filter_class, BaseFilterset):
            raise TypeError("%s expects filter_class to be %s: %s" % (qualname(
                self.__class__), qualname(BaseFilterset), repr(filter_class)))

        if not hasattr(view, 'get_queryset'):
            raise TypeError("%s expects view to have get_queryset method" %
                            (qualname(self.__class__), ))

        if issubclass(filter_class, ModelFilterset):
            fs_model = filter_class.Meta.model
            qs_model = view.get_queryset()._document
            if not issubclass(qs_model, fs_model):
                raise TypeError(
                    "filter and view document class mismatch: %s vs %s " %
                    (qualname(fs_model), qualname(qs_model)))

        filterset = filter_class(request.query_params)
        return filterset.filter_queryset(queryset)
Exemplo n.º 15
0
    def __fullname__(cls):
        # type: () -> str
        """
        Get qualified class name if possible, fall back to class name otherwise.

        :return: Full class name.
        :rtype: str
        """
        try:
            name = qualname(cls)
            if not name:
                raise AttributeError()
        except AttributeError:
            name = cls.__name__
        return name
        def inner(self, *args, **kwargs):
            call_info = call_info_nt(orig_method, args, kwargs, None, None)
            client_methods_gatekeeper(qualname(func), call_info)

            ret = None
            error = None
            try:
                ret = func(self, *args, **kwargs)
            except Exception as error:
                pass
            finally:
                call_info = call_info_nt(func, args, kwargs, ret, error)
                call_store.append(call_info)
            if error:     # Probably rework this flow, probably messes up chaining
                raise error
            return ret
def get_class_name_from_method(func):
    # type: (Any) -> str
    if hasattr(func, "__self__"):
        class_name = func.__self__.__class__.__name__
    elif hasattr(func, "__class__"):
        class_name = func.__class__.__name__
    else:
        raise Protocol0Error("Cannot get class_name from func")

    if class_name and all(word not in class_name
                          for word in ["function", "None"]):
        return class_name

    try:
        return ".".join(qualname(func).split(".")[:-1])
    except (AttributeError, IOError):
        return "unknown %s" % func
Exemplo n.º 18
0
def find_qualified_name(obj):
    name = None

    try:
        name = qualname(obj)
    except (AttributeError, IOError):
        pass

    if name is None:
        try:
            name = obj.__name__
        except AttributeError:
            pass

    if name is None:
        name = repr(obj)

    module = inspect.getmodule(obj)

    return '.'.join(filter(None, (getattr(module, '__name__', ''), name)))
Exemplo n.º 19
0
 def add_dir(self, *args):
     if not args:
         raise TypeError(
             'AddonDirectory.add_dir() Missing endpoint argument')
     name = None
     params = ()
     if len(args) < 2:
         if isinstance(args[0], str):
             name = endpoint = args[0]
         else:
             endpoint = args[0]
     elif len(args) < 3:
         name, endpoint = args
     else:
         raise TypeError('AddonDirectory.add_dir() Too many arguments')
     if isinstance(endpoint, Call):
         endpoint, params = endpoint.method, endpoint.args
     if ismethod(endpoint):
         obj = endpoint.__self__
         ser = obj
         if not params:
             params = (), {}
         params = (ser, ) + params[0], params[1]
     if name is None:
         handle = self.addon._find_call(endpoint)
         if handle:
             name = getattr(handle, 'title', endpoint)
         else:
             name = endpoint
     url = self.addon.mkurl(qualname(endpoint), params=params or None)
     item = xbmcgui.ListItem(name)
     xbmcplugin.addDirectoryItem(handle=self.addon.id,
                                 url=url,
                                 listitem=item,
                                 isFolder=True)
     print('DD : %r : %r' % (name, url))
     print('ITEM·%s·%s·' % (name, url))
     return item
Exemplo n.º 20
0
def test_local_classes_with_same_name():
    assert qualname(class_maker1()) == 'class_maker1.<locals>.C'
    X, Y, Z = class_maker2()
    assert qualname(X) == 'class_maker2.<locals>.X'
    assert qualname(Y) == 'class_maker2.<locals>.Y'
    assert qualname(Z) == 'class_maker2.<locals>.Z'
    assert qualname(X.D) == 'class_maker2.<locals>.X.D'
    assert qualname(Y.D) == 'class_maker2.<locals>.Y.D'
    assert qualname(Z.D) == 'class_maker2.<locals>.Z.D'
    assert qualname(X.D.f1) == 'class_maker2.<locals>.X.D.f1'
    assert qualname(X.D.f2) == 'class_maker2.<locals>.X.D.f2'
    assert qualname(Y.D.g) == 'class_maker2.<locals>.Y.D.g'
    assert qualname(Z.D.h) == 'class_maker2.<locals>.Z.D.h'
    assert qualname(Z.D.i) == 'class_maker2.<locals>.Z.D.i'
    A1, A2 = class_maker3()
    options = ['class_maker3.<locals>.A1.B',
               'class_maker3.<locals>.A2.B']
    assert qualname(A1.B) in options
    assert qualname(A2.B) in options
Exemplo n.º 21
0
def test_classes_with_same_name():
    assert qualname(C.D) == 'C.D'
    assert qualname(D) == 'D'
Exemplo n.º 22
0
def test_problematic_docstring():
    assert qualname(ClassWithProblematicDocstring.InnerClass) == 'ClassWithProblematicDocstring.InnerClass'
Exemplo n.º 23
0
def test_builtins():
    assert qualname(int) == 'int'
    assert qualname(len) == 'len'
Exemplo n.º 24
0
def test_directly_constructed_type():
    new_type = type('NewCls', (object,), {})
    assert qualname(new_type) == 'NewCls'
Exemplo n.º 25
0
def key_name(func):
    return '{module}.{name}'.format(
        module=func.__module__,
        name=qualname(func),
    )
Exemplo n.º 26
0
def test_nested_functions():
    assert qualname(f) == 'f'
    assert qualname(f()) == 'f.<locals>.g'
    assert qualname(C.D.h()) == 'C.D.h.<locals>.i.<locals>.j'
Exemplo n.º 27
0
def fullname(obj):
    """Return a fully qualified name for a module, function, class, etc."""
    if hasattr(obj, '__module__'):
        return obj.__module__ + '.' + qualname(obj)
    else:
        return obj.__name__
Exemplo n.º 28
0
def test_builtin():
    assert qualname(int) == 'int'
    assert qualname(DeprecationWarning) == 'DeprecationWarning'
Exemplo n.º 29
0
 def add_path(config, view, path, **kwargs):
     route_name = '%s_%s' % (qualname(view), path.replace('/', '_').split('{')[0])
     config.add_route(route_name, path)
     config.add_view(view, route_name=route_name, **kwargs)
Exemplo n.º 30
0
def test_nested_classes():
    assert qualname(C) == 'C'
    assert qualname(C.D) == 'C.D'
Exemplo n.º 31
0
def fullname(obj):
    """Return a fully qualified name for a module, function, class, etc."""
    if hasattr(obj, '__module__'):
        return obj.__module__ + '.' + qualname(obj)
    else:
        return obj.__name__
Exemplo n.º 32
0
def test_methods_in_nested_classes():
    assert qualname(C.f) == 'C.f'
    assert qualname(C.D.g) == 'C.D.g'
Exemplo n.º 33
0
def qual_name_safe(f):
    try:
        return f.__qualname__
    except AttributeError:  # Occurs when Python <= 3.3
        from qualname import qualname
        return qualname(f)
Exemplo n.º 34
0
def output_importer(functiondict):
    functionlist = list(functiondict.values())
    """
    Creates empty lists for the storage-variables which will be filled during the simulation.

    The lists are directly written to their entry in ``Variable.Vars`` and can be returned after the simulation is finished. 

    """
    if (builtins.number_of_integration) % builtins.data_readout == 0:
        #Assigning dynamical variables in Variables Package with initial values from var
        for func in functionlist:
            if qualname(func) == 'transfer.sellers':
                Vars.cL = np.array([0] * int(
                    builtins.number_of_integration / builtins.data_readout),
                                   dtype=object)
                Vars.C = np.array([0] * int(
                    builtins.number_of_integration / builtins.data_readout),
                                  dtype=object)
                Vars.F = np.array([0] * int(
                    builtins.number_of_integration / builtins.data_readout),
                                  dtype=object)
                Vars.P = np.array([0] * int(
                    builtins.number_of_integration / builtins.data_readout),
                                  dtype=object)
                Vars.Transfer = np.array([0] * int(
                    builtins.number_of_integration / builtins.data_readout),
                                         dtype=object)
            if qualname(func) == 'transfer.budyko':
                Vars.BudTransfer = np.array([0] * int(
                    builtins.number_of_integration / builtins.data_readout),
                                            dtype=object)
            if qualname(func) == 'forcing.co2_myhre':
                Vars.CO2Output = np.array([0] * int(
                    builtins.number_of_integration / builtins.data_readout),
                                          dtype=object)
            if qualname(func) == 'forcing.solar':
                Vars.SolarOutput = np.array([0] * int(
                    builtins.number_of_integration / builtins.data_readout),
                                            dtype=object)
            if qualname(func) == 'forcing.aod':
                Vars.AODOutput == np.array([0] * int(
                    builtins.number_of_integration / builtins.data_readout),
                                           dtype=object)

        Vars.ExternalOutput = np.array(
            [0] * int(builtins.number_of_integration / builtins.data_readout),
            dtype=object)
        Vars.alpha = np.array(
            [0] * int(builtins.number_of_integration / builtins.data_readout),
            dtype=object)
        Vars.solar = np.array(
            [0] * int(builtins.number_of_integration / builtins.data_readout),
            dtype=object)
        Vars.noise = np.array(
            [0] * int(builtins.number_of_integration / builtins.data_readout),
            dtype=object)
        Vars.Rdown = np.array(
            [0] * int(builtins.number_of_integration / builtins.data_readout),
            dtype=object)
        #Vars.Rup=np.reshape(np.zeros(int(builtins.number_of_integration/builtins.data_readout)*len(Vars.Lat)),(int(builtins.number_of_integration/builtins.data_readout),len(Vars.Lat)))
        Vars.Rup = np.array(
            [0] * int(builtins.number_of_integration / builtins.data_readout),
            dtype=object)
    else:
        for func in functionlist:
            if qualname(func) == 'transfer.sellers':
                Vars.cL = np.array([0] * int(builtins.number_of_integration /
                                             builtins.data_readout + 1),
                                   dtype=object)
                Vars.C = np.array([0] * int(builtins.number_of_integration /
                                            builtins.data_readout + 1),
                                  dtype=object)
                Vars.F = np.array([0] * int(builtins.number_of_integration /
                                            builtins.data_readout + 1),
                                  dtype=object)
                Vars.P = np.array([0] * int(builtins.number_of_integration /
                                            builtins.data_readout + 1),
                                  dtype=object)
                Vars.Transfer = np.array([0] *
                                         int(builtins.number_of_integration /
                                             builtins.data_readout + 1),
                                         dtype=object)
            if qualname(func) == 'transfer.budyko':
                Vars.BudTransfer = np.array(
                    [0] * int(builtins.number_of_integration /
                              builtins.data_readout + 1),
                    dtype=object)
            if qualname(func) == 'forcing.co2_myhre':
                Vars.CO2Output = np.array([0] *
                                          int(builtins.number_of_integration /
                                              builtins.data_readout + 1),
                                          dtype=object)
            if qualname(func) == 'forcing.solar':
                Vars.SolarOutput = np.array(
                    [0] * int(builtins.number_of_integration /
                              builtins.data_readout + 1),
                    dtype=object)
            if qualname(func) == 'forcing.aod':
                Vars.AODOutput == np.array([0] *
                                           int(builtins.number_of_integration /
                                               builtins.data_readout + 1),
                                           dtype=object)

        Vars.ExternalOutput = np.array(
            [0] *
            int(builtins.number_of_integration / builtins.data_readout + 1),
            dtype=object)
        Vars.alpha = np.array(
            [0] *
            int(builtins.number_of_integration / builtins.data_readout + 1),
            dtype=object)
        Vars.solar = np.array(
            [0] *
            int(builtins.number_of_integration / builtins.data_readout + 1),
            dtype=object)
        Vars.noise = np.array(
            [0] *
            int(builtins.number_of_integration / builtins.data_readout + 1),
            dtype=object)
        Vars.Rdown = np.array(
            [0] *
            int(builtins.number_of_integration / builtins.data_readout + 1),
            dtype=object)
        #Vars.Rup=np.reshape(np.zeros(int(builtins.number_of_integration/builtins.data_readout)*len(Vars.Lat)),(int(builtins.number_of_integration/builtins.data_readout),len(Vars.Lat)))
        Vars.Rup = np.array(
            [0] *
            int(builtins.number_of_integration / builtins.data_readout + 1),
            dtype=object)

    Vars.ExternalOutput = np.array([
        Vars.ExternalOutput for i in range(int(builtins.number_of_externals))
    ],
                                   dtype=object)
    Vars.External_time_start = np.array(
        [0 for i in range(int(builtins.number_of_externals))], dtype=object)
    Vars.ForcingTracker = np.array(
        [[0, 0] for i in range(int(builtins.number_of_externals))],
        dtype=object)
    Vars.ExternalInput = np.array(
        [0 for i in range(int(builtins.number_of_externals))], dtype=object)
    Vars.Read = {
        'cL': Vars.cL,
        'C': Vars.C,
        'F': Vars.F,
        'P': Vars.P,
        'Transfer': Vars.Transfer,
        'alpha': Vars.alpha,
        'BudTransfer': Vars.BudTransfer,
        'solar': Vars.solar,
        'noise': Vars.noise,
        'Rdown': Vars.Rdown,
        'Rup': Vars.Rup,
        'ExternalOutput': Vars.ExternalOutput,
        'CO2Output': Vars.CO2Output,
        'SolarOutput': Vars.SolarOutput,
        'AODOutput': Vars.AODOutput
    }
Exemplo n.º 35
0
def test_nested_classes():
    assert qualname(C) == 'C'
    assert qualname(C.D) == 'C.D'
Exemplo n.º 36
0
def test_methods_in_nested_classes():
    assert qualname(C.f) == 'C.f'
    assert qualname(C.D.g) == 'C.D.g'
Exemplo n.º 37
0
def test_nested_functions():
    assert qualname(f) == 'f'
    assert qualname(f()) == 'f.<locals>.g'
    assert qualname(C.D.h()) == 'C.D.h.<locals>.i.<locals>.j'
Exemplo n.º 38
0
 def __repr__(self):
     return "%s(name='%s',lookup='%s')" % (qualname(
         self.__class__), self.name, self.lookup_type)
Exemplo n.º 39
0
 def __repr__(self):
     return "%s(name='%s',lookup='%s')" % (qualname(self.__class__), self.name, self.lookup_type)
Exemplo n.º 40
0
    def __call__(self, f):
        # If there are decorator arguments, __call__() is only called once, as
        # part of the decoration process! You can only give it a single
        # argument, which is the function object.

        # TODO: Check if there are no arguments in the wrapped method

        func_name = f.__name__
        if not self.field_name:
            # TODO: Check if field already exists on model
            field_name = '_{}_cached'.format(func_name)
        else:
            field_name = self.field_name

        # In Python 3: f.__qualname__.split('.')[0]
        class_name = qualname(f).split('.')[0]
        class_path = '{}.{}'.format(f.__module__, class_name)

        register.add(
            class_path, f, self.field, field_name, self.dirty_func, self.invalidated_by
        )

        # Also run on initialization of code
        def wrapped_f(*args, **kwargs):
            if 'use_dbcache' in kwargs:
                use_dbcache = kwargs.pop('use_dbcache')
            else:
                use_dbcache = True

            instance = args[0]

            # If `None` is an actual valid value, this causes the decorated
            # method to always call the original method.
            cached_value = getattr(instance, field_name, None)
            if not use_dbcache or cached_value is None:
                # Call original method.
                value = f(*args, **kwargs)

                logger.debug('{}.{} call returned: {}'.format(
                    class_path, func_name, value
                ))

                if value != cached_value:
                    # Update database field for next call and to store when saved.
                    setattr(instance, field_name, value)
                    logger.debug('{}.{} updated and returned dbcache field ("{}") value: {}'.format(
                        class_path, func_name, field_name, value
                    ))

                    # TODO: Not sure if this is the right approach. Saving
                    # when calling a method is not really nice design.

                    # Update the database only if the instance already has a PK.
                    if instance.pk:
                        logger.debug('{}.{} updated dbcache field ("{}") in the database: {}'.format(
                            class_path, func_name, field_name, value
                        ))
                        # WARNING: This causes a database update query when
                        # calling a method that most likely does not imply
                        # such behaviour (like: Model.get_FOO).
                        #
                        # Bypass triggers by using update
                        instance.__class__.objects.filter(pk=instance.pk).update(**{field_name: value})
            else:
                value = cached_value
                logger.debug('{}.{} returned dbcache field ("{}") value: {}'.format(
                    class_path, func_name, field_name, value
                ))

            return value
        return wrapped_f
Exemplo n.º 41
0
def recursive_repr(
        func,  # type: Callable
        max_depth=1,  # type: Optional[int]
        max_global_depth=2,  # type: Optional[int]
        *args,  # type: Any
        **kwargs  # type: Any
):
    # type: (...) -> str
    """
    Decorate a representation method/function and prevents infinite recursion.

    .. code:: python

        >>> from objetto.utils.recursive_repr import recursive_repr

        >>> class MyClass(object):
        ...
        ...     @recursive_repr
        ...     def __repr__(self):
        ...         return "MyClass<" + repr(self) + ">"
        ...
        >>> my_obj = MyClass()
        >>> repr(my_obj)
        'MyClass<...>'

    :param func: The '__repr__' and/or '__str__' method/function.
    :type func: function

    :param max_depth: Maximum recursion depth before returning fill value.
    :type max_depth: int

    :param max_global_depth: Maximum global depth before returning fill value.
    :type max_global_depth: int

    :return: Decorated method function.
    :rtype: function
    """
    self = args[0]
    self_id = id(self)
    try:
        reprs = _local.reprs
    except AttributeError:
        reprs = _local.reprs = ValueCounter()
    try:
        global_reprs = _local.global_reprs
    except AttributeError:
        global_reprs = _local.global_reprs = [0]

    reprs[self_id] += 1
    global_reprs[0] += 1
    try:
        if max_depth is not None and reprs[self_id] > max_depth:
            return "..."
        elif max_global_depth is not None and global_reprs[
                0] > max_global_depth:
            try:
                qual_name = qualname(type(self))
            except AttributeError:
                qual_name = type(self).__name__
            return "<{} at {}>".format(qual_name, hex(id(self)))
        else:
            return func(*args, **kwargs)
    finally:
        reprs[self_id] -= 1
        if not reprs[self_id]:
            del reprs[self_id]
        if not reprs:
            del _local.reprs
        global_reprs[0] -= 1
        if not global_reprs[0]:
            del _local.global_reprs