########################################################################
# $Header: /var/local/cvsroot/4Suite/Ft/__init__.py,v 1.40 2005/04/05 23:00:49 jkloth Exp $
"""
4Suite: an open-source platform for XML and RDF processing.

Copyright 2004 Fourthought, Inc. (USA).
Detailed license and copyright information: http://4suite.org/COPYRIGHT
Project home, documentation, distributions: http://4suite.org/
"""

# True/False did not appear until Python 2.2.1
import sys
if sys.hexversion < 0x02020100:
    raise ImportError('Python 2.2.1 or newer required for 4Suite.')

# Determine natural platform charset
DEFAULT_ENCODING = 'US-ASCII'
try:
    import locale
except ImportError:
    pass
else:
    charset = locale.getlocale()[1]
    if charset is None:
        #Get around a Python bug on some platforms
        #see http://mail.python.org/pipermail/python-bugs-list/2002-July/012505.html
        try:
            # getdefaultlocale()[1] might be None
            charset = locale.getdefaultlocale()[1] or DEFAULT_ENCODING
        except:
            # Unable to determine platform encoding, only allow US-ASCII
            charset = DEFAULT_ENCODING

    DEFAULT_ENCODING = charset
    del locale
    del charset

#10,000 is the value from Python 1.5.2
MAX_PYTHON_RECURSION_DEPTH = 10000


class FtException(Exception):
    """
    Base class for all 4Suite-specific exceptions
    """
    #FIXME: make all exception classes use *args instead of argtuple
    def __init__(self, errorCode, messages, argtuple=(), **kwargs):
        """
        errorCode = Numeric ID for the type of error.
        messages = Mapping of errorCodes to localized error message strings.
        argtuple or keyword args = Values for message string formatting.
        """
        assert not (argtuple and kwargs) # we can use args or kwargs, not both
        self.message = messages[errorCode] % (kwargs or argtuple)
        self.errorCode = errorCode
        # Exception.__init__() will set self.args to the args passed to it
        Exception.__init__(self, *(self.message,) + (kwargs and (kwargs,) or (argtuple,)))

    def __getattr__(self, name):
        if name == 'params':
            return self.args[1]
        raise AttributeError(name)

    def __str__(self):
        return self.message

    def __repr__(self):
        return '%s: %s' % (self.__class__.__name__, self.message)


class FtWarning(Warning):
    pass


import warnings
__stdlib__showwarning = warnings.showwarning
def __ft__showwarning(message, category, filename, lineno, file=None):
    """
    warnings.showwarning() replacement that word-wraps the message if
    file is a terminal, and doesn't add filename, line, stack info to
    RuntimeWarnings.
    """
    if issubclass(category, FtWarning):
        from Ft.Lib import Wrap, Terminal
        if file is None:
            file = sys.stderr
        terminal = Terminal.Terminal(file)
        message = "%s: %s\n" % (category.__name__, message)
        if hasattr(file, 'isatty') and file.isatty():
            message = Wrap(message, terminal.columns())
        terminal.writetty(message)
        terminal.flush()
    else:
        __stdlib__showwarning(message, category, filename, lineno, file)
    return
warnings.showwarning = __ft__showwarning
del warnings


# Load the installation information module, only available from installed
# 4Suite or during setup via dummy module.
try:
    import __config__
except ImportError:
    import os
    from distutils.fancy_getopt import wrap_text

    msg = """
4Suite is having trouble importing the modules it needs.
This is usually because the current working directory, which happens
to be %r at the moment, contains modules with names that are the
same as modules that 4Suite is trying to import. For example, 4Suite
cannot be invoked from the source code directory that contains the
setup.py that was used to install 4Suite.

Try changing the current working directory to a suitable location
outside of the 4Suite source. If you continue to have trouble,
please send a message to the 4Suite mailing list at
4suite@lists.fourthought.com, along with any information that might
explain why you got this message.
""" % os.getcwd()

    # Wrap the message to 78 characters preserving paragraphs
    lines = []
    for chunk in msg.split('\n\n'):
        lines.extend(wrap_text(chunk, 78))
        lines.append('')
    raise SystemExit('\n'.join(lines))


def GetConfigVars(*names):
    """
    With no arguments, return a dictionary of all configuration variables
    relevant for the current installation.  With arguments, return a list
    of values that result from looking up each argument in the configuration
    variable dictionary.

    The following are the currently defined variables and their meaning:

    NAME, FULLNAME, VERSION, URL - fields as given for call to setup()
    BINDIR - directory for user executables
    DATADIR - directory for read-only platform-independent data
    DOCDIR - directory for documentation files
    LIBDIR - directory for extra libraries
    LOCALEDIR - directory for message catalogs
    LOCALSTATEDIR - directory for modifiable host-specific data
    SYSCONFIDIR - directory for read-only host-specific data
    """
    if names:
        vals = []
        for name in names:
            vals.append(getattr(__config__, name, None))
        return vals
    else:
        return vars(__config__)


def GetConfigVar(name):
    """
    Return the value of a single variable using the dictionary returned
    by 'get_config_vars()'.  Equivalent to GetConfigVars().get(name)
    """
    return getattr(__config__, name, None)

__version__ = __config__.VERSION

# gettext has been part of the standard library since Python 2.0
# 2005-02-25 Jeremy Kloth:
#  As of Python 2.3, function calls and lambdas are equivalent in
#  performance.  Translation retrieval is now simplier as a result.
import gettext
translation = gettext.translation(__config__.NAME, __config__.LOCALEDIR,
                                  fallback=True)
TranslateMessage = translation.gettext
del translation, gettext
