cds.cern.ch Open in urlscan Pro
188.185.12.33  Public Scan

URL: http://cds.cern.ch/help/hacking/miscutil-errorlib?ln=en
Submission: On September 11 via api from US — Scanned from CH

Form analysis 0 forms found in the DOM

Text Content

CERN ACCELERATING SCIENCE

 * Sign in
 * Directory


CERN DOCUMENT SERVER


ACCESS ARTICLES, REPORTS AND MULTIMEDIA CONTENT IN HEP


MAIN MENU

 * Search
 * Submit
 * Help
 * Personalize
   * Your alerts
   * Your baskets
   * Your comments
   * Your searches

Home > Hacking Invenio > MiscUtil Internals > Error Library


ERROR LIBRARY

These are the functions and methodologies for error handling in Invenio.


CONTENTS

 1. Overview
 2. Creating errors
 3. Using error library
 4. Troubleshooting


1. OVERVIEW

This API handles two concepts: Errors and Warnings.

An error is an unexpected behavior that leads to the stopping of current
process. Discussing of web pages, errors should be displayed by instead of the
requested page. Errors are logged into invenio/var/log/invenio.err. Errors can
be logged with client information and a tracestack.

A warning is an unexpected behavior that can be ignored. Warnings are logged
into invenio/var/log/invenio.log with just the warning message.

Errors and warnings should be internationalized (see below).


2. CREATING ERRORS


2.1 CONFIGURATION FILE

Every module should create a file containing error definitions, warning
definitions, variables avoiding "magic" number or strings, etc.

This file has to be named against a convention:

    <module-name>_config.py


e.g. webmessage_config.py for the WebMessage module.


2.2 DICTIONARIES OF ERRORS

Errors and warnings are eventually stored into dictionaries. The dictionaries
are to be named against the following convention:

    CFG_<MODULENAME>_ERROR_MESSAGES and
    CFG_<MODULENAME>_WARNING_MESSAGES


These two dictionaries (one can choose to implement only one if he doesn't need
warnings, for example) contain an error-name -> displayable message association.

Errors are to be named against the following convention:

    ERR_<MODULE-NAME>_ERROR_NAME


Please note the use of uppercase.

Warnings can also be named as errors if convenient, and so have to follow one of
these rules:

    WRN_<MODULE-NAME>_WARNING_NAME or
    ERR_<MODULE-NAME>_WARNING_NAME


The associated message can obviously contain substituted variables like %s,
%d...


INTERNATIONALIZATION

Errors should also be internationalized. As the config file cannot receive
parameters, this is done by the error handling library. The convenient way that
has been chosen is to nest the classical _() function inside the string.

An internationalized error message should look like this:

    '_("Internationalized error (%s) message")'


A complete example of correct dictionary is given below:

    CFG_WEBCOMMENT_ERROR_MESSAGES =
    {   'ERR_WEBCOMMENT_RECID_INVALID'       :  '_("%i is an invalid record ID")',
        'ERR_WEBCOMMENT_RECID_NAN'           :  '_("Record ID %i is not a number")',
        'ERR_WEBCOMMENT_UID_INVALID'         :  '_("%i is an invalid user ID")'
    }



3. USING ERROR LIBRARY


3.1 FROM A WEB INTERFACE

When displaying a page, the modules/webstyle/lib/webpage.py python module should
be used. This module provides a page() function, convenient for webpage output,
which can handle errors (display and log).
A call to this function should use the following arguments, assuming that
language information is stored in a variable called ln, and request information
are stored in req (will be used for IP logging, for example):

    page(...,
         req=req,
         language=ln,
         errors=error_list,
         warnings=warnings_list,
         ...)


list of errors and warnings are behaving the same way. They are lists of tuples:

    [(error_name, param1, ..., paramN), ...]


The params are used to represent substitued values in messages. For example if
you want to throw one of the errors above, error_list should look like this:

    error_list = [('ERR_WEBCOMMENT_RECID_INVALID', 123456)]


EXAMPLE

Business logic should be separated from web interface. We consider three files
in the following (real) example:

 1. webmessage_webinterface.py, which is the page as viewed by a browser,
 2. webmessage.py, which contains the business logic,
 3. webmessage_config, which contains error definitions

In this example, a user tries to read a message. We must ensure he doesn't read
another message, and that this message really exist in the system. For a more
convenient reading, some (non error-related) parts of code have been suppressed.

WEBMESSAGE_CONFIG.PY

# error messages. (should not happen, except in case of reload, or url altering)
CFG_WEBMESSAGE_ERROR_MESSAGES = \
{   'ERR_WEBMESSAGE_NOTOWNER':  '_("This message is not in your mailbox")',
    'ERR_WEBMESSAGE_NONICKNAME':'_("No nickname or user for uid #%s")',
    'ERR_WEBMESSAGE_NOMESSAGE': '_("This message doesn\'t exist")'
}


WEBMESSAGE.PY: BUSINESS LOGIC

from invenio.webmessage_config import CFG_WEBMESSAGE_ERROR_MESSAGES

def perform_request_display_msg(uid, msgid, ln=CFG_SITE_LANG):
    uid   = wash_url_argument(uid, 'int')
    msgid = wash_url_argument(msgid, 'int')
    ln    = wash_language(ln)
    errors = []
    warnings = []
    body = ""
    if (check_user_owns_message(uid, msgid) == 0):
        # The user doesn't own this message
        errors.append(('ERR_WEBMESSAGE_NOTOWNER',))
    else:
        (msg_id, ...) = get_message(uid, msgid)
        if (msg_id == ""):
	    # The message exists in table user_msgMESSAGE
	    # but not in table msgMESSAGE => table inconsistency
            errors.append(('ERR_WEBMESSAGE_NOMESSAGE',))
        else:
            body = webmessage_templates.tmpl_display_msg( ... )
    return (body, errors, warnings)


WEBMESSAGE_WEBINTERFACE.PY: WEB INTERFACE

from invenio.webpage import page
from invenio.webmessage import perform_request_display_msg

def display_msg(req, msgid=-1, ln=CFG_SITE_LANG):
    _ = gettext_set_language(ln)
    (body, errors, warnings) = perform_request_display_msg(uid, msgid, ln)
    title = _("Read a message")
    return page(title       = title,
                body        = body,
                navtrail    = get_navtrail(ln, title),
                uid         = uid,
                lastupdated = __lastupdated__,
                req         = req,
                language    = ln,
                errors      = errors,
                warnings    = warnings)




3.2 FROM A COMMAND LINE INTERFACE

The following functions can be useful (see source code for other functions):

   get_msgs_for_code_list(code_list, stream='error', ln=CFG_SITE_LANG)
        Returns formatted strings for the given errors
        @param code_list: list of tuples  [(err_name, arg1, ..., argN), ...]
        @param stream: 'error' or 'warning'
        @return list of tuples of length 2 [('ERR_...', err_msg), ...]
                if code_list empty, will return None.
                if errors retrieving error messages, will append an error to
                the list

    register_errors(errors_or_warnings_list, stream, req=None)
        log errors to invenio.err and warnings to invenio.log
        errors will be logged with client information (if req is given)
        and a tracestack
        warnings will be logged with just the warning message
        @param errors_or_warnings_list: list of tuples (err_name, err_msg)
        @param stream: 'error' or 'warning'
        @param req = mod_python request
        @return integer 1 if successfully wrote to stream, integer 0 if not
                will append another error to errors_list if unsuccessful

    send_error_report_to_admin(header, url, time, browser, client,
                               error, sys_error, traceback)
        Sends an email to the admin with client info and tracestack


EXAMPLE

In the following example, two files are used:

 1. webmessage_config, containing error messages
 2. webmessage_example_bin.py, containing business logic

Scenario: a function receives an error and wants to register it only if it is
not a messaging error

WEBMESSAGE_CONFIG.PY

# error messages. (should not happen, except in case of reload, or url altering)
CFG_WEBMESSAGE_ERROR_MESSAGES = \
{   'ERR_WEBMESSAGE_NOTOWNER':  '_("This message is not in your mailbox")',
    'ERR_WEBMESSAGE_NONICKNAME':'_("No nickname or user for uid #%s")',
    'ERR_WEBMESSAGE_NOMESSAGE': '_("This message doesn\'t exist")'
}


WEBMESSAGE_EXAMPLE_BIN.PY

from invenio.webmessage_config import CFG_WEBMESSAGE_ERROR_MESSAGES
from invenio.errorlib import get_msgs_for_code_list, register_errors

def handle_error(error):
    errorlist = get_msgs_for_code_list([error])

    # error is a tuple of error name, arguments => we only need the name
    if CFG_WEBMESSAGE_ERROR_MESSAGES[error[0]]:
        print("Error in webmessage: %s" % errorlist[0][1])
    else:
        for error in errorlist:
            print("Error: %s" % error[1])
        register_errors(errorlist, 'error')



4. TROUBLESHOOTING

MiscUtil can generate errors. See miscutil_config.py for a complete list. One
can see below some usual errors and their solutions:

ERR_MISCUTIL_IMPORT_ERROR The <module-name>_config.py file has not been found.
Check it has the correct name and is deployed.
Check that the error is named following this pattern:

    WRN_<MODULE-NAME>_WARNING_NAME or
    ERR_<MODULE-NAME>_WARNING_NAME


ERR_MISCUTIL_NO_DICT No dictionary could be found in <module-name>_config.py.
Check that your dictionary is correctly named:

    CFG_<MODULENAME>_ERROR_MESSAGES


You could also have inverted errors and warnings if only one dictionary was
provided.
This can also happen when using direct API if the stream argument is misspelled.
ERR_MISCUTIL_NO_MESSAGE_IN_DICT A dictionary was found but not the error in it.
You probably misspelled error_name, or inverted errors and warnings
dictionaries. ERR_MISCUTIL_UNDEFINED_ERROR The library couldn't guess the name
of module. Check that the error name is beginning with ERR_MODULE-NAME_ or
WRN_MODULE-NAME_. This library uses underscores as separators to guess module
name. ERR_MISCUTIL_TOO_MANY_ARGUMENT As the library was rendering the display of
error, a surnumerous text substitute was found (surnumerous are ignored for
final rendering, and this error is appened to list of errors):

    'ERR_KNIGHTS': '_("We are the knights who say %s!")'
    errors = ('ERR_KNIGHTS', 'ni', 'ni')


ERR_MISCUTIL_TOO_FEW_ARGUMENT Not enough arguments (text substitutes) were given
for an error. Missing ones are replaced by '???':

    'ERR_KNIGHTS': '_("We are the knights who say %s! We demand a %s")'
    errors = ('ERR_KNIGHTS', 'ni') # so, where is the shrubbery??


ERR_MISCUTIL_BAD_ARGUMENT_TYPE Your arguments (text substitutes) did not match
with the error declaration
e.g. inversion between integer (%i) and string (%s)

CERN Document Server :: Search :: Submit :: Personalize :: Help :: Privacy
Notice
Powered by Invenio
Maintained by CDS Service - Need help? Contact CDS Support.

This site is also available in the following languages:
Български  Català  Deutsch  Ελληνικά  English  Español  Français  Hrvatski
 Italiano  日本語  ქართული  Norsk/Bokmål  Polski  Português  Русский  Slovensky
 Svenska  中文(简)  中文(繁)