Author: reinhard Date: 2009-10-05 14:47:25 -0500 (Mon, 05 Oct 2009) New Revision: 9927
Modified: trunk/gnue-common/src/base/errors.py trunk/gnue-common/src/base/i18n.py trunk/gnue-common/src/base/utils.py trunk/gnue-common/src/lib/checktype.py Log: Some work on documentation. Modified: trunk/gnue-common/src/base/errors.py =================================================================== --- trunk/gnue-common/src/base/errors.py 2009-10-02 16:59:33 UTC (rev 9926) +++ trunk/gnue-common/src/base/errors.py 2009-10-05 19:47:25 UTC (rev 9927) @@ -23,6 +23,126 @@ """ Unicode enabled exception base classes. + +Exceptions in GNU Enterprise +============================ + +The C{errors} module defines four new exception base classes introducing three +concepts not available in standard exceptions. + +Exception groups +---------------- + +GNU Enterprise defines four exception groups: C{system}, C{admin}, +C{application}, and C{user}. The groups are distinguished by the question: +"Whose fault is it, that the exception occured?" + +Exception handling code can behave differently depending on the group. + +Group "system" +~~~~~~~~~~~~~~ + +Unhandled exceptions of group C{system} generally indicate a program bug in the +GNU Enterprise framework. If such an exception occures unhandled, the user +interface would typically ask the user to file a bug report, and/or send a +traceback to the system administrator in order to allow him/her to file a bug +report. The exception detail (usually the traceback) is important for such +exceptions. + +To define a new exception of group C{system}, simply derive your exception +class from L{SystemError}. Additionally, all exceptions not derived from any of +the base classes in this module are considered to be of group C{system}, this +includes all Python builtin exceptions and all exceptions defined in modules +external to GNU Enterprise. + +Group "admin" +~~~~~~~~~~~~~ + +Exceptions of group C{admin} indicate a mistake in installation or +configuration. If such an exception occures unhandled, the user interface would +typically ask the user to inform the system administrator and/or send a message +to the system administrator automatically. The exception detail can or can not +be important for such exceptions. + +To define a new exception of group C{admin}, simply derive your exception class +from L{AdminError}. + +Group "application" +~~~~~~~~~~~~~~~~~~~ + +Exceptions of group C{application} indicate a bug in an application built upon +the GNU Enterprise framework, like for example a malformed form definition +file. If such an exception occures unhandled, the user interface would +typically ask the user to inform the programmer of the application, and/or send +a message to the application programmer automatically. The exception detail is +usually very important for such an exception and might, for example, contain +the relevant line of the form definition file. + +To define a new exception of group C{application}, simply derive your exception +class from L{ApplicationError}. + +Group "user" +~~~~~~~~~~~~ + +Exceptions of group C{user} indicate unexpected user input. If such an +exception occures unhandled, the user interface would display a friendly, +non-panicking message. All exceptions of this group are designed so that the +exception message contains all necessary information, the user interface should +not display the detail for this exception (usually a traceback), since this +would only confuse the user. + +To define a new exception of group C{user}, simply derive your exception class +from L{UserError}. + +Exception info +-------------- + +The functions L{get_exception} and L{format_exception} return a tuple of four +strings giving full information about the exception: + + 1. C{group}: the exception group (C{system}, C{admin}, C{application}, or + C{user}). Always an 8 bit string. + 2. C{name}: the name of the exception, usually the class name without any + modules prepended. Always a unicode string. + 3. C{message}: the exception message, the text priarly displayed to the + user. Always a unicode string. + 4. C{detail}: the exception detail, in many cases a string representation + of the traceback. Always a unicode string. + +Using exception info for different purposes +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +All exceptions derived from the base classes defined in this module allow to +explicitly define C{name} and C{detail} by simply assigning a unicode string to +the instance variables C{name} and C{detail} respectively of the exception. + +A typical use of this is to use something more meaningful than a traceback as +exception detail. For example, if an error occures when parsing a file, the +relevant line in the file might be much more useful. + +The possibility to explicitly define the name can be used to let exceptions +raised through a single class to look like they were different classes, like +when transporting remote exceptions defined in the next section. + +Remote exceptions +~~~~~~~~~~~~~~~~~ + +Remote exceptions are a way to transport exceptions across contexts, like from +a server process to a client process. The idea is to catch the exception at the +source end, extract the exception info from it in the form of four strings by +using the L{get_exception} function, transporting these strings to the +target end, raise an all-purpose general wrapper exception on the target end, +and feed it with these four strings. + +To define a new all-purpose general wrapper exception, simply derive it from +L{RemoteError}. + +Unicode enabled exceptions +-------------------------- + +All base exception classes defined in this module, and all classes derived from +them, allow for unicode stings in the exception message. This is essential to +allow for translated exception messages. """ import sys @@ -57,7 +177,7 @@ @ivar detail: The detail information to the exception. If set, this will be returned by L{get_exception} and L{format_exception} instead of the traceback. - @type name: unicode or None + @type detail: unicode or None """ def __init__(self, message, group='system'): @@ -82,8 +202,7 @@ class SystemError(Error): """ - This exception class should be used for exceptions indicating a bug in - GNUe. Whenever such an exception is raised, one have found such a bug :) + Base class for exceptions indicating a bug in the GNU Enterprise frameork. """ def __init__(self, message): @@ -96,9 +215,8 @@ class AdminError(Error): """ - This exception class should be used for exceptions indicating a - misconfiguration in a widest sense. This could be a missing module for a - dbdriver as well as an 'out of disk space' error. + Base class for exceptions indicating a mistake in installation or + configuration. """ def __init__(self, message): @@ -111,8 +229,8 @@ class ApplicationError(Error): """ - This class should be used for errors caused by applications like a corrupt - trigger code, or a misformed xml-file and so on. + Base class for exceptions indicating a bug in the application running on + top of the GNU Enterprise framework. """ def __init__(self, message): @@ -125,10 +243,7 @@ class UserError(Error): """ - This class should be used for exceptions where a user did something wrong, - or a situation has occured which isn't dramatic, but the user has to be - informed of. Example: wrong password or the user has entered non-numeric - data into a numeric field, and so on. + Base class for exceptions indicating unexpected user input. """ def __init__(self, message): @@ -141,9 +256,10 @@ class RemoteError(Error): """ - This class is used for transporting an exception raised at a remote point. - Once it has been created it never changes it's contents. A remote error - usually contains System-, Admin- or User-Errors. + Base class for wrappers around exceptions raised in a different context. + + Exceptions of this class (or a descendant class) can mimick any given + exception, by wrapping arbitary group, name, message and detail properties. """ def __init__(self, group, name, message, detail): @@ -163,10 +279,11 @@ def get_exception(tb_skip=None): """ - Return a tuple (group, name, message, detail) for the last occured + Return a tuple (group, name, message, detail) for the currently handled exception. @param tb_skip: Number of traceback lines to suppress at the beginning. + @type tb_skip: int """ (etype, evalue, etraceback) = sys.exc_info() @@ -186,6 +303,7 @@ @param etype, evalue, etraceback: Exception info as returned by sys.exc_info(). @param tb_skip: Number of traceback lines to suppress at the beginning. + @type tb_skip: int """ # group Modified: trunk/gnue-common/src/base/i18n.py =================================================================== --- trunk/gnue-common/src/base/i18n.py 2009-10-02 16:59:33 UTC (rev 9926) +++ trunk/gnue-common/src/base/i18n.py 2009-10-05 19:47:25 UTC (rev 9927) @@ -23,6 +23,54 @@ """ Internationalization support. + +Languages and Encodings in GNU Enterprise +========================================= + +The C{i18n} module provides some convenience functions to support handling of +different user languages and different character set encodings. + +Character set encoding +---------------------- + +In GNUe, all user visible text (including data from the database) is generally +handled in the form of unicode strings, and only converted from/to 8-bit +strings at the points where it enters/leaves the GNU Enterprise infrastructure. +That is, if a file is read, user input is queried, or data from a database +backend is retrieved, all texts are immediately converted to unicode. Likewise, +if a file is written, data is sent to a database backend, or output is written +to a screen, a conversion from unicode to an 8 bit string happens only +immediately before writing. + +This way, GNUe does not have to handle different encodings in the code, and +avoids mixing up texts with different character sets. + +At the same time, it is essential to use the correct encoding when doing the +conversions of incoming and outgoing data, and it is important to understand +which encoding is the correct one for the purpose. For example, any output +written to the text screen certainly has to be encoded to the current system +encoding defined e.g. through the C{$LANG} environment variable, while data +sent to a database backend must be encoded depending on the database server's +and client's configuration. + +For the admittedly frequent case of the current system encoding, this module +defines the convenience functions L{inconv} and {outconv}, available in the +builtin namespace as C{i()} and C{o()} respectively. + +Translations of user visible text +--------------------------------- + +To make text translatable, enclose it with C{_()} or C{u_()}. The difference is +that C{u_()} yields a unicode string, while C{_()} yields an 8 bit string +encoded with the current system encoding. It is recommended to always use +C{u_()}, the use of C{_()} will likely be deprecated soon. + +To indicate the message catalog to be used for translations in a module, set +the global variable C{__gettext_domain__} in the module. This setting is +effective for the module itself and all its submodules, except for submodules +which redefine C{__gettext_domain__} themselves. So usually you just have to +define C{__gettext_domain__} only once in the __init__.py of the root directory +of the whole module tree for which a message catalog is applicable. """ import gettext @@ -40,10 +88,12 @@ # Locale initialization # ============================================================================= -def init_locale(): +def __init_locale(): """ - Initialize locale support. This is called automatically in module - initialization, no need to call it manually. + Initialize locale support. + + This is called automatically in module initialization, no need to call it + manually. """ # On Mac, locale.setlocale() does not set the default locale. Instead we @@ -63,40 +113,50 @@ # ============================================================================= # ----------------------------------------------------------------------------- -# Convert Unicode to String, using the current encoding +# Convert String to Unicode, using the current encoding # ----------------------------------------------------------------------------- -def outconv(text): +def inconv(text): """ - Encode a text to the current encoding. This function is available as - the builtin function "o()". + Decode a text from the current encoding. This function is available as + the builtin function "i()". + + @param text: Text as 8 bit string. + @type text: str + @return: Text in unicode. + @rtype: unicode """ - # TODO: in 0.8, warn if text is not unicode, in 0.9, throw error - #checktype(text, unicode) + checktype(text, str) encoding = locale.getlocale()[1] if encoding is None: encoding = 'ascii' - return text.encode(encoding, 'replace') + return unicode(text, encoding, 'replace') # ----------------------------------------------------------------------------- -# Convert String to Unicode, using the current encoding +# Convert Unicode to String, using the current encoding # ----------------------------------------------------------------------------- -def inconv(text): +def outconv(text): """ Encode a text to the current encoding. This function is available as the builtin function "o()". + + @param text: Text as unicode. + @type text: unicode + @return: Text as 8 bit string. + @rtype: str """ - checktype(text, str) + # TODO: in 0.8, warn if text is not unicode, in 0.9, throw error + #checktype(text, unicode) encoding = locale.getlocale()[1] if encoding is None: encoding = 'ascii' - return unicode(text, encoding, 'replace') + return text.encode(encoding, 'replace') # ============================================================================= @@ -200,4 +260,4 @@ __builtin__.__dict__['u_'] = utranslate __builtin__.__dict__['_'] = translate -init_locale() +__init_locale() Modified: trunk/gnue-common/src/base/utils.py =================================================================== --- trunk/gnue-common/src/base/utils.py 2009-10-02 16:59:33 UTC (rev 9926) +++ trunk/gnue-common/src/base/utils.py 2009-10-05 19:47:25 UTC (rev 9927) @@ -22,7 +22,7 @@ # $Id$ """ -The utils module provides some very basic although GNU Enterprise specific +The C{utils} module provides some very basic although GNU Enterprise specific utility functions. """ Modified: trunk/gnue-common/src/lib/checktype.py =================================================================== --- trunk/gnue-common/src/lib/checktype.py 2009-10-02 16:59:33 UTC (rev 9926) +++ trunk/gnue-common/src/lib/checktype.py 2009-10-05 19:47:25 UTC (rev 9927) @@ -41,9 +41,21 @@ def checktype(variable, valid_type): """ - Check a varaible (for example a parameter to a function) for a correct type. - This function is available as builtin function. + Check a varaible for a correct type. + This function checks whether the type of a given variable is in a given + list of valid types. If this is not the case, an exception is raised. + + A typical use case is testing function parameters for the correct type at + the beginning of the function definition:: + def format_number(number, format, precision): + checktype(number, [int, float, decimal.Decimal]) + checktype(flormat, [str, unicode, None]) + checktype(precision, int) + + After module initialization, this function is available in the builtin + namespace. + @param variable: Variable to check. @param valid_type: Type, class, or a list of types and classes that are valid. _______________________________________________ commit-gnue mailing list commit-gnue@gnu.org http://lists.gnu.org/mailman/listinfo/commit-gnue