AttributeInfo.py :  » XML » 4Suite » 4Suite-XML-1.0.2 » Ft » Xml » Xslt » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » XML » 4Suite 
4Suite » 4Suite XML 1.0.2 » Ft » Xml » Xslt » AttributeInfo.py
########################################################################
# $Header: /var/local/cvsroot/4Suite/Ft/Xml/Xslt/AttributeInfo.py,v 1.30 2006/08/11 15:13:36 jkloth Exp $
"""
Classes that support validation and evaluation of attribute values in
XSLT instruction elements

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

from Ft import TranslateMessage

import cStringIO, traceback

from Ft.Xml.XPath import Conversions
from Ft.Xml.XPath import RuntimeException
from Ft.Xml.XPath import parser
_xpath_parser = parser.new()

from Ft.Xml.Xslt import XsltException,XsltRuntimeException,Error
from Ft.Xml.Xslt import parser
_xpattern_parser = parser.new()
del parser

from Ft.Xml import XML_NAMESPACE,XMLNS_NAMESPACE,EMPTY_NAMESPACE
from Ft.Xml.Lib.XmlString import IsQName,SplitQName

from AttributeValueTemplate import AttributeValueTemplate


class AttributeInfo:

    display = 'unknown'

    def __init__(self, required=0, default=None, description=''):
        self.required = required
        self.default = default
        self.description = description
        return

    def __str__(self):
        return self.display

    def prepare(self, element, value):
        if value is None:
            return self.default
        return value
    reprocess = prepare

    def validate(self, validation):
        return 1


class _ConstantValue:
    def __init__(self, value):
        self.value = value

    def isConstant(self):
        return 1

    def evaluate(self, context):
        return self.value

    def __repr__(self):
        return repr(self.value)

    def __nonzero__(self):
        return self.value is not None


class Choice(AttributeInfo):

    def __init__(self, values, required=0, default=None, description=''):
        AttributeInfo.__init__(self, required, default, description)
        self.values = values
        return

    def prepare(self, element, value):
        if value is None:
            return self.default
        if value not in self.values:
            # check for a AttributeInfo instance
            allowed = filter(lambda v, t=type(self): type(v) is t, self.values)
            for info in allowed:
                try:
                    allowed.prepare(element, value)
                    return value
                except:
                    pass
            # if we get here it is an error
            raise XsltException(Error.INVALID_ATTR_CHOICE, value, str(self))
        return value
    reprocess = prepare

    def __str__(self):
        return ' | '.join(map(lambda v: '"' + v + '"', self.values))


class Avt:

    def __str__(self):
        return '{ %s }' % self.display

    def prepare(self, element, value):
        if value is None:
            return _ConstantValue(self.reprocess(element, self.default))
        elif '{' not in value and '}' not in value:
            return _ConstantValue(self.reprocess(element, value))
        try:
            return AttributeValueTemplate(value, self, element)
        except SyntaxError, error:
            # an error from the XPath parser
            raise XsltException(Error.INVALID_AVT, value,
                                element.baseUri, element.lineNumber,
                                element.columnNumber, str(error))
        except XsltException, error:
            raise XsltException(Error.INVALID_AVT, value,
                                element.baseUri, element.lineNumber,
                                element.columnNumber, error.args[0])


class ChoiceAvt(Avt, Choice):

    def __str__(self):
        return '{ %s }' % Choice.__str__(self)


class AnyAvt(Avt, AttributeInfo):
    display = _('any avt')


class String(AttributeInfo):
    display = _('string')


class StringAvt(Avt, String):
    pass


class Char(AttributeInfo):
    """
    A string value with a length of one
    """
    display = _('char')

    def prepare(self, element, value):
        if value is None:
            return self.default
        if len(value) > 1:
            raise XsltException(Error.INVALID_CHAR_ATTR, value)
        return value
    reprocess = prepare


class CharAvt(Avt, Char):
    pass


class Number(AttributeInfo):
    display = _('number')

    def prepare(self, element, value):
        if value is None:
            return self.default
        try:
            return float(value or self.default)
        except:
            raise XsltException(Error.INVALID_NUMBER_ATTR, value)
    reprocess = prepare


class NumberAvt(Avt, Number):
    reprocess = Number.prepare


class UriReference(AttributeInfo):
    display = _('uri-reference')

    def __init__(self, required=0, default=None, description='', isNsName=0):
        AttributeInfo.__init__(self, required, default, description)
        self._isNsName = isNsName

    def prepare(self, element, value):
        if value is None:
            return self.default
        if self._isNsName and \
            value == XML_NAMESPACE or value == XMLNS_NAMESPACE:
            raise XsltException(Error.INVALID_NS_URIREF_ATTR, value)
        return value
    reprocess = prepare


class UriReferenceAvt(Avt, UriReference):
    pass


class Id(AttributeInfo):
    display = _('id')

    def prepare(self, element, value):
        if value is None:
            return self.default
        if not value:
            raise XsltException(Error.INVALID_ID_ATTR, value)
        return value
    reprocess = prepare


class IdAvt(Avt, Id):
    pass


class QName(AttributeInfo):
    display = _('qname')

    def prepare(self, element, value):
        if value is None:
            if self.default is None:
                return None
            value = self.default
        elif not IsQName(value):
            raise XsltException(Error.INVALID_QNAME_ATTR, value)

        prefix, local = SplitQName(value)
        if prefix:
            try:
                namespace = element.namespaces[prefix]
            except KeyError:
                raise XsltRuntimeException(Error.UNDEFINED_PREFIX,
                                           element, prefix)
        else:
            namespace = EMPTY_NAMESPACE
        return (namespace, local)
    reprocess = prepare


class QNameAvt(Avt, QName):
    pass


class RawQName(QName):

    def prepare(self, element, value):
        if value is None:
            if self.default is None:
                return None
            value = self.default
        elif not IsQName(value):
            raise XsltException(Error.INVALID_QNAME_ATTR, value)
        return SplitQName(value)
    reprocess = prepare


class RawQNameAvt(Avt, RawQName):
    pass


class NCName(AttributeInfo):
    display = _('ncname')

    def prepare(self, element, value):
        if value is None:
            return self.default
        if not value:
            raise XsltException(Error.INVALID_NCNAME_ATTR, value)
        if ':' in value:
            raise XsltException(Error.INVALID_NCNAME_ATTR, value)
        return value
    reprocess = prepare


class NCNameAvt(Avt, NCName):
    pass


class Prefix(AttributeInfo):
    display = _('prefix')

    def prepare(self, element, value):
        if value is None:
            return self.default
        if not value:
            raise XsltException(Error.INVALID_PREFIX_ATTR, value)
        if ':' in value:
            raise XsltException(Error.INVALID_PREFIX_ATTR, value)
        if value == '#default':
            value = None
        return value
    reprocess = prepare


class PrefixAvt(Avt, Prefix):
    pass


class NMToken(AttributeInfo):
    display = _('nmtoken')

    def prepare(self, element, value):
        if value is None:
            return self.default
        if not value:
            raise XsltException(Error.INVALID_NMTOKEN_ATTR, value)
        return value
    reprocess = prepare


class NMTokenAvt(Avt, NMToken):
    pass


class QNameButNotNCName(AttributeInfo):
    display = _('qname-but-not-ncname')

    def prepare(self, element, value):
        if value is None:
            if self.default is None:
                return None
            value = self.default
        elif not value:
            raise XsltException(Error.QNAME_BUT_NOT_NCNAME, value)

        try:
            index = value.index(':')
        except ValueError:
            raise XsltException(Error.QNAME_BUT_NOT_NCNAME, value)
        prefix, local = value[:index], value[index+1:]
        try:
            namespace = element.namespaces[prefix]
        except KeyError:
            raise XsltRuntimeException(Error.UNDEFINED_PREFIX,
                                       element, prefix)
        return (namespace, local)
    reprocess = prepare


class Token(AttributeInfo):
    """
    An attribute whose value is used as an XPath NameTest
    """
    display = _('token')

    def prepare(self, element, value):
        # a 'token' is really an XPath NameTest; '*' | NCName ':' '*' | QName
        # From XPath 1.0 section 2.3:
        #  if the QName does not have a prefix, then the namespace URI is null
        index = value.rfind(':')
        if index == -1:
            namespace = None
            local = value
        else:
            prefix = value[:index]
            local = value[index+1:]
            try:
                namespace = element.namespaces[prefix]
            except KeyError:
                raise XsltRuntimeException(Error.UNDEFINED_PREFIX,
                                           element, prefix)
        return (namespace, local)
    reprocess = prepare


class TokenAvt(Avt, Token):
    pass


class ExpressionWrapper:

    def __init__(self, expression, element, original):
        self.expression = expression
        self.element = element
        self.original = original
        return

    def __nonzero__(self):
        # True if self.expression is not None, which is always the case
        # otherwise this instance would not exist!
        return True

    def __getattr__(self, attr):
        """Make this behave as if it was the expression object itself."""
        return getattr(self.expression, attr)

    # Provide the copy/pickle helpers so as to not get them from the
    # wrapped expression.
    def __getstate__(self):
        return (self.expression, self.element, self.original)

    def __setstate__(self, state):
        self.expression, self.element, self.original = state
        return

    def evaluate(self,context):
        try:
            return self.expression.evaluate(context)
        except XPathRuntimeException, e:
            import MessageSource
            e.message = MessageSource.EXPRESSION_POSITION_INFO % (
                self.element.baseUri, self.element.lineNumber,
                self.element.columnNumber, self.original, str(e))
            # By modifying the exception value directly, we do not need
            # to raise with that value, thus leaving the frame stack
            # intact (original traceback is displayed).
            raise
        except XsltRuntimeException, e:
            import MessageSource
            e.message = MessageSource.XSLT_EXPRESSION_POSITION_INFO % (
                str(e), self.original)
            # By modifying the exception value directly, we do not need
            # to raise with that value, thus leaving the frame stack
            # intact (original traceback is displayed).
            raise
        except (KeyboardInterrupt, SystemExit):
            raise
        except Exception, e:
            import MessageSource
            tb = cStringIO.StringIO()
            tb.write("Lower-level traceback:\n")
            traceback.print_exc(1000, tb)
            raise RuntimeError(MessageSource.EXPRESSION_POSITION_INFO % (
                self.element.baseUri, self.element.lineNumber,
                self.element.columnNumber, self.original, tb.getvalue()))

class Expression(AttributeInfo):
    """
    An attribute whose value is used as an XPath expression
    """
    display = _('expression')

    def prepare(self, element, value):
        if value is None:
            if self.default is None:
                return None
            value = self.default
        try:
            expression = _xpath_parser.parse(value)
        except SyntaxError, error:
            raise XsltException(Error.INVALID_EXPRESSION, value,
                                element.baseUri, element.lineNumber,
                                element.columnNumber, str(error))
        return ExpressionWrapper(expression, element, value)

class NodeSetExpression(Expression):
    display = _('node-set-expression')

class StringExpression(Expression):
    display = _('string-expression')

class NumberExpression(Expression):
    display = _('number-expression')

class BooleanExpression(Expression):
    display = _('boolean-expression')


class Pattern(AttributeInfo):
    """
    An attribute whose value is used as an XPattern expression
    """
    display = _('pattern')

    def prepare(self, element, value):
        if value is None:
            if self.default:
                value = self.default
            else:
                return None
        try:
            return _xpattern_parser.parse(value)
        except SyntaxError, error:
            raise XsltException(Error.INVALID_PATTERN, value,
                                element.baseUri, element.lineNumber,
                                element.columnNumber, str(error))

class Tokens(Token):
    """
    A whitespace separated list of tokens (see Token for description of a token)
    """
    display = _('tokens')

    def prepare(self, element, value):
        if value is None:
            return []
        tokens = []
        for token in value.split():
            prepared = Token.prepare(self, element, token)
            tokens.append(prepared)
        return tokens
    reprocess = prepare

class TokensAvt(Avt, Tokens):
    pass


class QNames(QName):
    """
    A whitespace separated list of qnames (see QName for description of a qname)
    """
    display = _('qnames')

    def prepare(self, element, value):
        if value is None:
            return []
        qnames = []
        for qname in value.split():
            prepared = QName.prepare(self, element, qname)
            qnames.append(prepared)
        return qnames
    reprocess = prepare

class QNamesAvt(Avt, QNames):
    pass


class Prefixes(Prefix):
    """
    A whitespace separated list of prefixes (see Prefix for more information)
    """
    display = _('prefixes')

    def prepare(self, element, value):
        if value is None:
            return []
        prefixes = []
        for prefix in value.split():
            prepared = Prefix.prepare(self, element, prefix)
            prefixes.append(prepared)
        return prefixes
    reprocess = prepare

class PrefixesAvt(Avt, Prefixes):
    pass


class YesNo(AttributeInfo):

    display = '"yes" | "no"'

    def prepare(self, element, value):
        if value is None:
            return self.default and self.default == 'yes'
        elif value not in ['yes', 'no']:
            raise XsltException(Error.INVALID_ATTR_CHOICE, value, str(self))
        return value == 'yes'
    reprocess = prepare

class YesNoAvt(Avt, YesNo):
    pass

www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.