Esempio n. 1
0
File: util.py Progetto: nltk/epydoc
def runbuilder(s, attribs='', build=None, exclude=''):
    """
    This test function takes a string containing the contents of a
    module.  It writes the string contents to a file, imports the file
    as a module, and uses build_doc to build documentation, and pretty
    prints the resulting ModuleDoc object.  The C{attribs} argument
    specifies which attributes of the C{APIDoc}s should be displayed.
    The C{build} argument gives the name of a variable in the module
    whose documentation should be built, instead of bilding docs for
    the whole module.
    """
    # Write it to a temp file.
    file_path = write_pystring_to_tmp_dir(s)
    # Build it.
    val_doc = build_doc(file_path)
    if build: val_doc = val_doc.variables[build].value
    # Display it.
    if isinstance(val_doc, ClassDoc):
        for val in val_doc.variables.values():
            if isinstance(val.value, RoutineDoc):
                fun_to_plain(val.value)
    s = val_doc.pp(include=attribs.split(),exclude=exclude.split())
    s = re.sub(r"(filename = ).*", r"\1...", s)
    s = re.sub(r"(<module 'epydoc_test' from ).*", r'\1...', s)
    s = re.sub(r"(<function \w+ at )0x\w+>", r"\1...>", s)
    s = re.sub(r"(<\w+ object at )0x\w+>", r"\1...>", s)
    print(s)
    # Clean up.
    cleanup_tmp_dir(file_path)
Esempio n. 2
0
def runbuilder(s, attribs='', build=None, exclude=''):
    """
    This test function takes a string containing the contents of a
    module.  It writes the string contents to a file, imports the file
    as a module, and uses build_doc to build documentation, and pretty
    prints the resulting ModuleDoc object.  The C{attribs} argument
    specifies which attributes of the C{APIDoc}s should be displayed.
    The C{build} argument gives the name of a variable in the module
    whose documentation should be built, instead of bilding docs for
    the whole module.
    """
    # Write it to a temp file.
    tmp_dir = write_pystring_to_tmp_dir(s)
    # Build it.
    val_doc = build_doc(os.path.join(tmp_dir, 'epydoc_test.py'))
    if build: val_doc = val_doc.variables[build].value
    # Display it.
    if isinstance(val_doc, ClassDoc):
        for val in val_doc.variables.values():
            if isinstance(val.value, RoutineDoc):
                fun_to_plain(val.value)
    s = val_doc.pp(include=attribs.split(), exclude=exclude.split())
    s = re.sub(r"(filename = ).*", r"\1...", s)
    s = re.sub(r"(<module 'epydoc_test' from ).*", r'\1...', s)
    s = re.sub(r"(<function \w+ at )0x\w+>", r"\1...>", s)
    s = re.sub(r"(<\w+ object at )0x\w+>", r"\1...>", s)
    print(s)
    # Clean up.
    cleanup_tmp_dir(tmp_dir)
Esempio n. 3
0
def buildvaluedoc(s):
    """
    This test function takes a string containing the contents of a
    module.  It writes the string contents to a file, imports the file
    as a module, and uses build_doc to build documentation, and
    returns it as a C{ValueDoc} object.
    """
    tmp_dir = write_pystring_to_tmp_dir(s)
    val_doc = build_doc(os.path.join(tmp_dir, 'epydoc_test.py'))
    cleanup_tmp_dir(tmp_dir)
    return val_doc
Esempio n. 4
0
File: util.py Progetto: nltk/epydoc
def buildvaluedoc(s):
    """
    This test function takes a string containing the contents of a
    module.  It writes the string contents to a file, imports the file
    as a module, and uses build_doc to build documentation, and
    returns it as a C{ValueDoc} object.
    """
    file_path = write_pystring_to_tmp_dir(s)
    val_doc = build_doc(file_path)
    cleanup_tmp_dir(file_path)
    return val_doc
Esempio n. 5
0
def getMethodTypedArgument(specFile):
    val_doc = parse_docs(specFile)
    doc = build_doc(specFile)
    moduledoc = introspect_docs(filename=specFile)
    methodDetails = dict()
    for ckey in moduledoc.variables.iterkeys():
        classdoc = moduledoc.variables[ckey].value
        for rkey in classdoc.variables.iterkeys():
            routinedoc = classdoc.variables[rkey].value
            if isinstance(routinedoc, RoutineDoc):
                argType=dict()
                for arg in routinedoc.arg_types.iterkeys():
                    argument = str(routinedoc.arg_types[arg])
                    paramType = re.findall('<epytext><para inline=True>(?P<paramtype>.*)</para></epytext>', argument)[0]
                    argType[arg] = paramType
                methodDetails[rkey] = argType
    return methodDetails
Esempio n. 6
0
def contract_epydoc(f):
    """
    The decorator for any functions which have a epydoc-formatted docstring.
    It validates the function inputs and output against the contract defined
    by the epydoc description.

    Currently, it supports the usual functions as well as simple object methods
    (though neither classmethods nor staticmethods).

    Inside the epydoc contracts, it supports the following fields:

    - C{@type arg:} - the type of the C{arg} argument is validated before
        the function is called.

    - C{@rtype:} - the return type of the function is validated after
        the function is called.

    - C{@precondition:} - the precondition (that may involve the arguments
        of the function)
        that should be satisfied before the function is executed.

    - C{@postcondition:} - the postcondition (that may involve the result
        of the function given as C{result} variable)
        that should be satisfied after the function is executed.

    @param f: The function which epydoc documentation should be verified.
    @precondition: callable(f)
    """
    if ENABLED:
        try:
            from epydoc import apidoc, docbuilder, markup
        except ImportError:
            raise ImportError(
                "To use contract_epydoc() function, "
                "you must have the epydoc module "
                "(often called python-epydoc) installed.\n"
                "For more details about epydoc installation, see "
                "http://epydoc.sourceforge.net/")

        # Given a method/function, get the module
        # where the function is defined.
        module = inspect.getmodule(f)
        _stack = inspect.stack()[1:]

        # The function/method marked with @contract_epydoc may be
        # either top-level in the module,
        # or defined inside some namespace, like a class or another function.
        base_function_path = _get_function_base_path_from_stack(_stack)

        # Now, analyze the epydoc comments,
        # and maybe cacke the documentation linker.
        if hasattr(module, "_dbc_ds_linker"):
            _dbc_ds_linker = module._dbc_ds_linker
        else:
            _dbc_ds_linker = markup.DocstringLinker()
            if USE_EPYDOC_CACHE:
                module._dbc_ds_linker = _dbc_ds_linker

        contract = docbuilder.build_doc(f)

        preconditions = [
            description.to_plaintext(_dbc_ds_linker)
            for field, argument, description in contract.metadata
            if field.singular == "Precondition"
        ]
        postconditions = [
            description.to_plaintext(_dbc_ds_linker)
            for field, argument, description in contract.metadata
            if field.singular == "Postcondition"
        ]

        if isinstance(f, (staticmethod, classmethod)):
            raise NotImplementedError(
                "The @contract_epydoc decorator is not supported "
                "for either staticmethod or classmethod functions; "
                "please use it before (below) turning a function into "
                "a static method or a class method.")
        elif isinstance(contract, apidoc.RoutineDoc):
            f_path = "%(mod_name)s module (%(mod_file_path)s), %(func_name)s()" % {
                "mod_name":
                module.__name__,
                "mod_file_path":
                contract.defining_module.filename,
                "func_name":
                ".".join(filter(None, (base_function_path, f.__name__))),
            }
        else:
            raise Exception("@contract_epydoc decorator is not yet supported "
                            "for %s types!" % type(contract))

        _stack = inspect.stack()
        def_frame = _stack[1][0]

        # Don't copy the dictionaries, but refer to the original stack frame
        def_globals = def_frame.f_globals
        def_locals = def_frame.f_locals

        #
        # At this stage we have "f_path" variable containing
        # the fully qualified name of the called function.
        # Also, def_globals and def_locals contain the globals/locals of
        # the code where the decorated function was defined.
        #

        @wraps(f)
        def wrapped_f(*args, **kwargs):
            _stack = inspect.stack()

            # Do we actually want to use the globals with NoneType
            # already imported?
            #def_globals_with_nonetype = dict(def_globals);
            #def_globals_with_nonetype["NoneType"] = NoneType

            # Stack now:
            # [0] is the level inside wrapped_f.
            # [1] is the caller.

            # For "globals" dictionary, we should use the globals of the code
            # that called the wrapper function.
            call_frame = _stack[1][0]

            call_globals = call_frame.f_globals
            call_locals = call_frame.f_locals

            arguments_to_validate = list(contract.arg_types)

            try:
                expected_types = \
                    dict((argument,
                          _parse_str_to_type(
                              f_path,
                              _preprocess_field_argument(
                                  contract.arg_types[argument].to_plaintext(
                                      _dbc_ds_linker)),
                              "'%s' argument" % argument,
                              _globals=def_globals,
                              _locals=def_locals))
                             for argument in arguments_to_validate)
            except Exception, e:
                raise e

            # All values:
            # First try to use the default values;
            # then add the positional arguments,
            # then add the named arguments.
            values = dict(
                chain(
                    izip(contract.posargs,
                         ((df.pyval if df is not None else None)
                          for df in contract.posarg_defaults)),
                    izip(contract.posargs, args), kwargs.iteritems()))

            # Validate arguments
            for argument in arguments_to_validate:
                assert argument in values, "%r not in %r" % (argument, values)
                value = values[argument]
                expected_type = expected_types[argument]

                if not isinstance(value, expected_type):
                    raise TypeError(
                        "%s:\n"
                        "The '%s' argument is of %r while must be of %r; "
                        "its value is %r" %
                        (f_path, argument, type(value), expected_type, value))

            # Validate preconditions.
            # Preconditions may use the globals from the function definition,
            # as well as the function arguments.
            locals_for_preconditions = values
            for description_str in preconditions:
                description_str = _preprocess_field_argument(description_str)
                value = _parse_str_to_value(f_path,
                                            description_str,
                                            'precondition definition',
                                            _globals=def_globals,
                                            _locals=locals_for_preconditions)
                if not value:
                    raise ValueError(
                        "%s:\n"
                        "The following precondition results in logical False; "
                        "its definition is:\n"
                        "\t%s\n"
                        "and its real value is %r" %
                        (f_path, description_str.strip(), value))

            #
            # Call the desired function
            #
            result = f(*args, **kwargs)  # IGNORE THIS LINE

            # Validate return value
            if contract.return_type is not None:

                expected_type = _parse_str_to_type(
                    f_path,
                    _preprocess_field_argument(
                        contract.return_type.to_plaintext(_dbc_ds_linker)),
                    'return value',
                    _globals=def_globals,
                    _locals=values)
                if not isinstance(result, expected_type):
                    raise TypeError(
                        "%s:\n"
                        "The following return value is of %r while must be of %r: "
                        "%r" % (f_path, type(result), expected_type, result))

            # Validate postconditions.
            # Postconditions may use the globals from the function definition,
            # as well as the function arguments and the special "result" parameter.
            locals_for_postconditions = dict(locals_for_preconditions)
            locals_for_postconditions['result'] = result
            for description_str in postconditions:
                description_str = _preprocess_field_argument(description_str)
                value = _parse_str_to_value(f_path,
                                            description_str,
                                            'postcondition definition',
                                            _globals=def_globals,
                                            _locals=locals_for_postconditions)

                if not value:
                    raise ValueError(
                        "%s:\n"
                        "The following postcondition results in logical False; "
                        "its definition is:\n"
                        "\t%s\n"
                        "and its real value is %r" %
                        (f_path, description_str.strip(), value))

            # Validations are successful
            return result

        return wrapped_f
Esempio n. 7
0
def contract_epydoc(f):
    """
    The decorator for any functions which have a epydoc-formatted docstring.
    It validates the function inputs and output against the contract defined
    by the epydoc description.

    Currently, it supports the usual functions as well as simple object methods
    (though neither classmethods nor staticmethods).

    Inside the epydoc contracts, it supports the following fields:

    - C{@type arg:} - the type of the C{arg} argument is validated before
        the function is called.

    - C{@rtype:} - the return type of the function is validated after
        the function is called.

    - C{@precondition:} - the precondition (that may involve the arguments
        of the function)
        that should be satisfied before the function is executed.

    - C{@postcondition:} - the postcondition (that may involve the result
        of the function given as C{result} variable)
        that should be satisfied after the function is executed.

    @param f: The function which epydoc documentation should be verified.
    @precondition: callable(f)
    """
    if ENABLED:
        try:
            from epydoc import apidoc, docbuilder, markup
        except ImportError:
            raise ImportError(
                      "To use contract_epydoc() function, "
                          "you must have the epydoc module "
                          "(often called python-epydoc) installed.\n"
                      "For more details about epydoc installation, see "
                          "http://epydoc.sourceforge.net/")

        # Given a method/function, get the module
        # where the function is defined.
        module = inspect.getmodule(f)
        _stack = inspect.stack()[1:]

        # The function/method marked with @contract_epydoc may be
        # either top-level in the module,
        # or defined inside some namespace, like a class or another function.
        base_function_path = _get_function_base_path_from_stack(_stack)

        # Now, analyze the epydoc comments,
        # and maybe cacke the documentation linker.
        if hasattr(module, "_dbc_ds_linker"):
            _dbc_ds_linker = module._dbc_ds_linker
        else:
            _dbc_ds_linker = markup.DocstringLinker()
            if USE_EPYDOC_CACHE:
                module._dbc_ds_linker = _dbc_ds_linker


        contract = docbuilder.build_doc(f)

        preconditions = [description.to_plaintext(_dbc_ds_linker)
                             for field, argument, description in contract.metadata
                             if field.singular == "Precondition"]
        postconditions = [description.to_plaintext(_dbc_ds_linker)
                              for field, argument, description in contract.metadata
                              if field.singular == "Postcondition"]

        if isinstance(f, (staticmethod, classmethod)):
            raise NotImplementedError(
                      "The @contract_epydoc decorator is not supported "
                      "for either staticmethod or classmethod functions; "
                      "please use it before (below) turning a function into "
                      "a static method or a class method.")
        elif isinstance(contract, apidoc.RoutineDoc):
            f_path = "%(mod_name)s module (%(mod_file_path)s), %(func_name)s()" % {
                "mod_name"      : module.__name__,
                "mod_file_path" : contract.defining_module.filename,
                "func_name"     : ".".join(filter(None,
                                                  (base_function_path, f.__name__))),
                }
        else:
            raise Exception("@contract_epydoc decorator is not yet supported "
                            "for %s types!" % type(contract))

        _stack = inspect.stack()
        def_frame = _stack[1][0]

        # Don't copy the dictionaries, but refer to the original stack frame
        def_globals = def_frame.f_globals
        def_locals = def_frame.f_locals

        #
        # At this stage we have "f_path" variable containing
        # the fully qualified name of the called function.
        # Also, def_globals and def_locals contain the globals/locals of
        # the code where the decorated function was defined.
        #


        @wraps(f)
        def wrapped_f(*args, **kwargs):
            _stack = inspect.stack()

            # Do we actually want to use the globals with NoneType
            # already imported?
            #def_globals_with_nonetype = dict(def_globals);
            #def_globals_with_nonetype["NoneType"] = NoneType

            # Stack now:
            # [0] is the level inside wrapped_f.
            # [1] is the caller.

            # For "globals" dictionary, we should use the globals of the code
            # that called the wrapper function.
            call_frame = _stack[1][0]

            call_globals = call_frame.f_globals
            call_locals = call_frame.f_locals

            arguments_to_validate = list(contract.arg_types)

            try:
                expected_types = \
                    dict((argument,
                          _parse_str_to_type(
                              f_path,
                              _preprocess_field_argument(
                                  contract.arg_types[argument].to_plaintext(
                                      _dbc_ds_linker)),
                              "'%s' argument" % argument,
                              _globals=def_globals,
                              _locals=def_locals))
                             for argument in arguments_to_validate)
            except Exception, e:
                raise e

            # All values:
            # First try to use the default values;
            # then add the positional arguments,
            # then add the named arguments.
            values = dict(chain(izip(contract.posargs,
                                     ((df.pyval if df is not None else None)
                                          for df in contract.posarg_defaults)),
                                izip(contract.posargs, args),
                                kwargs.iteritems()))

            # Validate arguments
            for argument in arguments_to_validate:
                assert argument in values, "%r not in %r" % (argument, values)
                value = values[argument]
                expected_type = expected_types[argument]

                if not isinstance(value, expected_type):
                    raise TypeError("%s:\n"
                                    "The '%s' argument is of %r while must be of %r; "
                                    "its value is %r" % (f_path,
                                                         argument,
                                                         type(value),
                                                         expected_type,
                                                         value))

            # Validate preconditions.
            # Preconditions may use the globals from the function definition,
            # as well as the function arguments.
            locals_for_preconditions = values
            for description_str in preconditions:
                description_str = _preprocess_field_argument(description_str)
                value = _parse_str_to_value(f_path,
                                            description_str,
                                            'precondition definition',
                                            _globals=def_globals,
                                            _locals=locals_for_preconditions)
                if not value:
                    raise ValueError("%s:\n"
                                     "The following precondition results in logical False; "
                                     "its definition is:\n"
                                     "\t%s\n"
                                     "and its real value is %r" % (f_path,
                                                                   description_str.strip(),
                                                                   value))

            #
            # Call the desired function
            #
            result = f(*args, **kwargs)  # IGNORE THIS LINE

            # Validate return value
            if contract.return_type is not None:

                expected_type = _parse_str_to_type(
                                    f_path,
                                    _preprocess_field_argument(
                                        contract.return_type.to_plaintext(
                                            _dbc_ds_linker)),
                                    'return value',
                                    _globals=def_globals,
                                    _locals=values)
                if not isinstance(result, expected_type):
                    raise TypeError("%s:\n"
                                    "The following return value is of %r while must be of %r: "
                                    "%r" % (f_path,
                                            type(result),
                                            expected_type,
                                            result))

            # Validate postconditions.
            # Postconditions may use the globals from the function definition,
            # as well as the function arguments and the special "result" parameter.
            locals_for_postconditions = dict(locals_for_preconditions)
            locals_for_postconditions['result'] = result
            for description_str in postconditions:
                description_str = _preprocess_field_argument(description_str)
                value = _parse_str_to_value(f_path,
                                            description_str,
                                            'postcondition definition',
                                            _globals=def_globals,
                                            _locals=locals_for_postconditions)

                if not value:
                    raise ValueError("%s:\n"
                                     "The following postcondition results in logical False; "
                                     "its definition is:\n"
                                     "\t%s\n"
                                     "and its real value is %r" % (f_path,
                                                                   description_str.strip(),
                                                                   value))

            # Validations are successful
            return result

        return wrapped_f
Esempio n. 8
0
def contract_epydoc(f):
    """
    The decorator for any functions which have a epydoc-formatted docstring.
    It validates the function inputs and output against the contract defined by the epydoc description.

    Currently, it supports the usual functions as well as simple object methods
    (though neither classmethods nor staticmethods).

    Inside the epydoc contracts, it supports the following fields:

    - C{@type arg:} - the type of the C{arg} argument is validated before the function is called.

    - C{@rtype:} - the return type of the function is validated after the function is called.

    - C{@precondition:} - the precondition (that may involve the arguments of the function)
        that should be satisfied before the function is executed.

    - C{@postcondition:} - the postcondition (that may involve the result of the function given as C{result} variable)
        that should be satisfied after the function is executed.

    @param f: The function which epydoc documentation should be verified.
    @precondition: callable(f)
    """
    if ENABLED:
        try:
            from epydoc import apidoc, docbuilder, markup
        except ImportError:
            raise ImportError(
                'To use contract_epydoc() function, '
                'you must have the epydoc module (often called python-epydoc) installed.\n'
                'For more details about epydoc installation, see http://epydoc.sourceforge.net/'
            )

        # Given a method/function, get the module where the function is defined.
        module = inspect.getmodule(f)
        _stack = inspect.stack()[1:]

        # The function/method marked with @contract_epydoc may be either top-level in the module,
        # or defined inside some namespace, like a class or another function.
        base_function_path = _get_function_base_path_from_stack(_stack)

        # Now, analyze the epydoc comments,
        # and maybe cacke the documentation linker.
        if hasattr(module, '_dbc_ds_linker'):
            _dbc_ds_linker = module._dbc_ds_linker
        else:
            _dbc_ds_linker = markup.DocstringLinker()
            if USE_EPYDOC_CACHE:
                module._dbc_ds_linker = _dbc_ds_linker

        # Parse function contract
        contract = docbuilder.build_doc(f)

        preconditions = (description.to_plaintext(_dbc_ds_linker)
                         for field, argument, description in contract.metadata
                         if field.singular == 'Precondition')
        postconditions = (description.to_plaintext(_dbc_ds_linker)
                          for field, argument, description in contract.metadata
                          if field.singular == 'Postcondition')
        requirements = (description.to_plaintext(_dbc_ds_linker)
                        for field, argument, description in contract.metadata
                        if field.singular == 'Requires')

        if False:  # TODO
            # Parse module contract (if available).
            extra_mod_imports = {}
            _module = contract.defining_module.pyval
            # Now find whole-module requirements

            # Is the set of extra imports cached in the module?
            if hasattr(_module, '_dbc_extra_locals'):  # cached
                extra_mod_imports = _module._dbc_extra_locals
            else:  # not cached
                # Let's parse it by epydoc, and cache
                try:
                    mod_contract = docbuilder.build_doc(_module)
                except AttributeError as e:
                    if e.message == b"_Sentinel instance has no attribute '__getitem__'":
                        # No fields in docstring, or even no docstring at all.
                        pass
                    else:
                        raise
                else:
                    mod_requirements = (
                        description.to_plaintext(_dbc_ds_linker) for field,
                        argument, description in mod_contract.metadata
                        if field.singular == 'Requires')

                    for r in mod_requirements:
                        exec r in {}, extra_mod_imports

                _module._dbc_extra_locals = extra_mod_imports  # cache it in the whole module
            del _module
            # "extra_mod_imports" now contain the additional modules to use.

        if isinstance(f, (staticmethod, classmethod)):
            raise NotImplementedError(
                'The @contract_epydoc decorator is not supported '
                'for either staticmethod or classmethod functions; '
                'please use it before (below) turning a function into '
                'a static method or a class method.')
        elif isinstance(contract, apidoc.RoutineDoc):
            f_path = '%(mod_name)s module (%(mod_file_path)s), %(func_name)s()' % {
                'mod_name':
                module.__name__,
                'mod_file_path':
                contract.defining_module.filename,
                'func_name':
                '.'.join(filter(None, (base_function_path, f.__name__)))
            }
        else:
            raise Exception(
                '@contract_epydoc decorator is not yet supported for %s types!'
                % type(contract))

        _stack = inspect.stack()
        def_frame = _stack[1][0]
        del _stack

        # Don't copy the dictionaries, but refer to the original stack frame
        def_globals = def_frame.f_globals
        def_locals = def_frame.f_locals
        del def_frame

        # Take some data from contract
        arguments_to_validate = list(contract.arg_types)

        #
        # At this stage we have "f_path" variable containing the fully qualified name
        # of the called function.
        #
        # Also, "def_globals" and "def_locals" contain the globals/locals of the code
        # where the decorated function was defined.
        #
        # Other available variables are:
        # * arguments_to_validate
        # * contract (TODO: is it possible to avoid keeping it in memory?)
        # * _dbc_ds_linker (TODO: is it possible to avoid keeping it in memory?)

        @wraps(f)
        def wrapped_f(*args, **kwargs):
            _stack = inspect.stack()

            # Do we actually want to use the globals with NoneType already imported?
            #def_globals_with_nonetype = dict(def_globals); def_globals_with_nonetype["NoneType"] = NoneType

            # Stack now:
            # [0] is the level inside wrapped_f.
            # [1] is the caller.

            # For "globals" dictionary, we should use the globals of the code
            # that called the wrapper function.
            call_frame = _stack[1][0]

            call_globals = call_frame.f_globals
            call_locals = call_frame.f_locals

            try:
                expected_types = dict(
                    (argument,
                     _parse_str_to_type(f_path,
                                        contract.arg_types[argument].
                                        to_plaintext(_dbc_ds_linker),
                                        "'%s' argument" % argument,
                                        _globals=def_globals,
                                        _locals=def_locals))
                    for argument in arguments_to_validate)
            except Exception, e:
                raise e

            # All values:
            # First try to use the default values;
            # then add the positional arguments,
            # then add the named arguments.
            values = dict(
                chain(
                    izip(contract.posargs,
                         ((df.pyval if df is not None else None)
                          for df in contract.posarg_defaults)),
                    izip(contract.posargs, args), kwargs.iteritems()))

            # Validate arguments
            for argument in arguments_to_validate:
                assert argument in values, '%r not in %r' % (argument, values)
                value = values[argument]
                expected_type = expected_types[argument]

                if not isinstance(value, expected_type):
                    raise TypeError(
                        '%s:\n'
                        "The '%s' argument is of %r while must be of %r; "
                        'its value is %r' %
                        (f_path, argument, type(value), expected_type, value))

            # Validate preconditions.
            # Preconditions may use the globals from the function definition,
            # as well as the function arguments.
            locals_for_preconditions = values
            for description_str in preconditions:
                value = _parse_str_to_value(f_path,
                                            description_str,
                                            'precondition definition',
                                            _globals=def_globals,
                                            _locals=locals_for_preconditions)
                if not value:
                    raise ValueError(
                        '%s:\n'
                        'The following precondition results in logical False; '
                        'its definition is:\n'
                        '\t%s\n'
                        'and its real value is %r' %
                        (f_path, description_str.strip(), value))

            #
            # Call the desired function
            #
            result = f(*args, **kwargs)  # IGNORE THIS LINE

            # Validate return value
            if contract.return_type is not None:

                expected_type = _parse_str_to_type(
                    f_path,
                    contract.return_type.to_plaintext(_dbc_ds_linker),
                    'return value',
                    _globals=def_globals,
                    _locals=values)
                if not isinstance(result, expected_type):
                    raise TypeError(
                        '%s:\n'
                        'The following return value is of %r while must be of %r: '
                        '%r' % (f_path, type(result), expected_type, result))

            # Validate postconditions.
            # Postconditions may use the globals from the function definition,
            # as well as the function arguments and the special "result" parameter.
            locals_for_postconditions = dict(locals_for_preconditions)
            locals_for_postconditions['result'] = result
            for description_str in postconditions:
                value = _parse_str_to_value(f_path,
                                            description_str,
                                            'postcondition definition',
                                            _globals=def_globals,
                                            _locals=locals_for_postconditions)

                if not value:
                    raise ValueError(
                        '%s:\n'
                        'The following postcondition results in logical False; '
                        'its definition is:\n'
                        '\t%s\n'
                        'and its real value is %r' %
                        (f_path, description_str.strip(), value))

            # Validations are successful
            return result

        return wrapped_f