Пример #1
0
 def evaluate(self, context):
     '''Returns a number'''
     lrt = self._left.evaluate(context)
     lrt = Conversions.NumberValue(lrt)
     rrt = self._right.evaluate(context)
     rrt = Conversions.NumberValue(rrt)
     res = 0
     # multiply
     if self._op == 0:
         res = lrt * rrt
     # divide
     elif self._op == 1:
         try:
             res = lrt / rrt
         except ZeroDivisionError:
             if lrt < 0:
                 res = -number.inf
             elif lrt == 0:
                 res = number.nan
             else:
                 res = number.inf
     # modulo
     elif self._op == 2:
         try:
             res = lrt % rrt
         except ZeroDivisionError:
             res = number.nan
     return res
Пример #2
0
    def evaluate(self, context):
        """Returns a boolean"""
        left = self._left.evaluate(context)
        right = self._right.evaluate(context)

        if isinstance(left, Types.NodesetType) or \
           isinstance(right, Types.NodesetType):
            return _nodeset_compare(self._cmp, left, right)

        # From XPath 1.0 Section 3.4:
        # order for equality expressions when neither is a node-set
        # 1. either is boolean, both are converted as if by boolean()
        # 2. either is number, both are converted as if by number()
        # otherwise, both are converted as if by string()
        if isinstance(left, Types.BooleanType):
            right = Conversions.BooleanValue(right)
        elif isinstance(right, Types.BooleanType):
            left = Conversions.BooleanValue(left)
        elif isinstance(left, Types.NumberType):
            right = Conversions.NumberValue(right)
        elif isinstance(right, Types.NumberType):
            left = Conversions.NumberValue(left)
        else:
            left = Conversions.StringValue(left)
            right = Conversions.StringValue(right)
        return self._cmp(left, right) and boolean.true or boolean.false
Пример #3
0
def pipp_thumbnail(context, src, width, height):
    ctx = context.processor.extensionParams[(NAMESPACE, 'context')]
    image_name = ctx.abs_in_path(Conversions.StringValue(src))
    ctx.add_depends(image_name[len(ctx.in_root):])
    thumb_name = re.sub('(\.\w+)$', '_thumb\g<1>',
                        Conversions.StringValue(src))

    if width:
        width = int(Conversions.NumberValue(width))
    if height:
        height = int(Conversions.NumberValue(height))

    img = Image.open(image_name)
    w, h = img.size

    if height and not width:
        width = int(w * height / h)
    if width and not height:
        height = int(h * width / w)

    img = img.resize((width, height))
    img.save(ctx.abs_out_path(ctx.abs_in_path(thumb_name)))

    #--
    # Add image to cache using fake inroot name, so width/height functions work
    #--
    images[ctx.abs_in_path(thumb_name)] = img

    return thumb_name
Пример #4
0
def ATan2(context, y, x):
    """
    The math:atan2 function returns the angle ( in radians ) from the X axis
    to a point (y,x).
    """
    x = Conversions.NumberValue(x)
    y = Conversions.NumberValue(y)
    try:
        return math.atan2(y, x)
    except ValueError:
        return number.nan
Пример #5
0
    def evaluate(self, context):
        """Returns a boolean"""
        left = self._left.evaluate(context)
        right = self._right.evaluate(context)

        if isinstance(left, Types.NodesetType) or \
           isinstance(right, Types.NodesetType):
            return _nodeset_compare(self._cmp, left, right, relational=True)

        left = Conversions.NumberValue(left)
        right = Conversions.NumberValue(right)
        return self._cmp(left, right) and boolean.true or boolean.false
Пример #6
0
 def evaluate(self, context):
     '''Returns a number'''
     if self._leftLit:
         lrt = self._left
     else:
         lrt = self._left.evaluate(context)
         lrt = Conversions.NumberValue(lrt)
     if self._rightLit:
         rrt = self._right
     else:
         rrt = self._right.evaluate(context)
         rrt = Conversions.NumberValue(rrt)
     return lrt + (rrt * self._sign)
Пример #7
0
 def __init__(self, sign, left, right):
     self._sign = sign
     self._leftLit = 0
     self._rightLit = 0
     if isinstance(left, ParsedLiteralExpr):
         self._leftLit = 1
         self._left = Conversions.NumberValue(left.evaluate(None))
     else:
         self._left = left
     if isinstance(right, ParsedLiteralExpr):
         self._rightLit = 1
         self._right = Conversions.NumberValue(right.evaluate(None))
     else:
         self._right = right
     return
Пример #8
0
def FormatNumber(context, number, formatString, decimalFormatName=None):
    """
    Implementation of format-number().

    Converts its first argument to a string using the format pattern
    string specified by the second argument and the decimal-format
    named by the third argument (see the xsl:decimal-format element),
    or the default decimal-format, if there is no third argument.

    The format pattern string is in the syntax specified by the JDK 1.1
    DecimalFormat class. The decimal-format name must be a QName. It is
    an error if the stylesheet does not contain a declaration of the
    decimal-format with the specified expanded-name.
    """
    num = Conversions.NumberValue(number)

    format_string = Conversions.StringValue(formatString)

    if decimalFormatName is not None:
        format_name = context.expandQName(decimalFormatName)
    else:
        format_name = None
    try:
        decimal_format = context.stylesheet.decimalFormats[format_name]
    except KeyError:
        raise XsltRuntimeException(Error.UNDEFINED_DECIMAL_FORMAT,
                                   decimalFormatName)

    return routines.FormatNumber(num, format_string, decimal_format)
Пример #9
0
def Substring(context, st, start, length=None):
    """Function: <string> substring(<string>, <number>, <number>?)"""
    if not isinstance(st, XPathStringType):
        st = Conversions.StringValue(st)
    if not isinstance(start, NumberType):
        start = Conversions.NumberValue(start)

    # start == NaN: spec doesn't say; assume no substring to return
    # start == +Inf or -Inf: no substring to return
    if number.isnan(start) or number.isinf(start):
        return u''

    # start is finite, safe for int() and round().
    start = int(round(start))
    # convert to 0-based index for python string slice
    if start < 1:
        startidx = 0
    else:
        startidx = start - 1

    # length undefined: return chars startidx to end
    if length is None:
        return st[startidx:]
    elif not isinstance(length, NumberType):
        length = Conversions.NumberValue(length)

    # length == NaN: spec doesn't say; assume no substring to return
    if number.isnan(length):
        return u''
    # length == +Inf: return chars startidx to end
    # length == -Inf: no substring to return
    elif number.isinf(length):
        if length > 0:
            return st[startidx:]
        else:
            return u''

    # length is finite, safe for int() and round().
    length = int(round(length))

    # return value must end before position (start+length)
    # which is (start+length-1) in 0-based index
    endidx = start + length - 1
    if endidx > startidx:
        return st[startidx:endidx]
    else:
        return u''
Пример #10
0
    def instantiate(self, context, processor):
        # get value(s) to format
        if self._value:
            value = Conversions.NumberValue(self._value.evaluate(context))
            if not number.finite(value) or value < 0.5:
                # This is an error.  However, recovery is to just write
                # the number as if the string() function was used.
                processor.writers[-1].text(Conversions.StringValue(value))
                return
            else:
                values = [int(round(value))]
        else:
            node = context.node
            if self._level == SINGLE:
                value = self._single_value(context, node, self._count,
                                           self._from)
                if value == 0:
                    values = []
                else:
                    values = [value]
            elif self._level == MULTIPLE:
                values = self._multiple_values(context, node)
            elif self._level == ANY:
                value = self._any_value(context, node)
                if value == 0:
                    values = []
                else:
                    values = [value]
            else:
                # 'single' without count or from attributes
                value = 1
                prev = node.previousSibling
                type = node.nodeType
                expanded = (node.namespaceURI, node.localName)
                while prev:
                    if prev.nodeType == type and \
                       (prev.namespaceURI, prev.localName) == expanded:
                        value += 1
                    prev = prev.previousSibling
                values = [value]

        # format the value(s)
        grouping_size = int(self._grouping_size.evaluate(context))
        if grouping_size:
            grouping_separator = self._grouping_separator.evaluate(context)
        else:
            grouping_separator = None

        formatter = self._formatter
        if not formatter:
            format = self._format and self._format.evaluate(
                context) or DEFAULT_FORMAT
            lang = self._lang and self._lang.evaluate(context) or DEFAULT_LANG
            letter_value = self._letter_value.evaluate(context) or ''
            formatter = self.createFormatter(format, lang, letter_value)

        numstr = formatter.format(values, grouping_size, grouping_separator)
        processor.writers[-1].text(numstr)
        return
Пример #11
0
def ATan(context, num):
    """
    The math:atan function returns the arctangent value of a number.
    """
    try:
        return math.atan(Conversions.NumberValue(num))
    except ValueError:
        return number.nan
Пример #12
0
def ASin(context, num):
    """
    The math:asin function returns the arcsine value of a number.
    """
    try:
        return math.asin(Conversions.NumberValue(num))
    except ValueError:
        return number.nan
Пример #13
0
def Round(context, object_):
    """Function: <number> round(<number>)"""
    num = Conversions.NumberValue(object_)
    if number.isnan(num) or number.isinf(num):
        return num
    elif num < 0 and num % 1.0 == 0.5:
        return round(num, 0) + 1
    else:
        return round(num, 0)
Пример #14
0
def Constant(context, name, precision):
    """
    The math:constant function returns the specified constant to a set precision.
    """
    name = Conversions.StringValue(name)
    if not CONSTANTS.has_key(name):
        return number.nan

    precision = Conversions.NumberValue(precision)
    return float('%0.*f' % (int(precision), CONSTANTS[name]))
Пример #15
0
def Floor(context, object_):
    """Function: <number> floor(<number>)"""
    num = Conversions.NumberValue(object_)
    if number.isnan(num) or number.isinf(num):
        return num
    elif int(num) == num:
        return num
    elif num < 0:
        return float(int(num) - 1)
    else:
        return float(int(num))
Пример #16
0
def Ceiling(context, object_):
    """Function: <number> ceiling(<number>)"""
    num = Conversions.NumberValue(object_)
    if number.isnan(num) or number.isinf(num):
        return num
    elif int(num) == num:
        return num
    elif num > 0:
        return float(int(num) + 1)
    else:
        return float(int(num))
Пример #17
0
def Java_Color_GetHSBColor(context, hue, saturation, brightness):
    hue = Conversions.NumberValue(hue)
    saturation = Conversions.NumberValue(saturation)
    brightness = Conversions.NumberValue(brightness)

    if saturation == 0:
        r = g = b = int(brightness * 255)
    else:
        r = g = b = 0
        h = (hue - int(hue)) * 6.0
        f = h - int(h)
        p = brightness * (1.0 - saturation)
        q = brightness * (1.0 - saturation * f)
        t = brightness * (1.0 - (saturation * (1.0 - f)))

        h = int(h)
        if h == 0:
            r = int(brightness * 255)
            g = int(t * 255)
            b = int(p * 255)
        elif h == 1:
            r = int(q * 255)
            g = int(brightness * 255)
            b = int(p * 255)
        elif h == 2:
            r = int(p * 255)
            g = int(brightness * 255)
            b = int(t * 255)
        elif h == 3:
            r = int(p * 255)
            g = int(q * 255)
            b = int(brightness * 255)
        elif h == 4:
            r = int(t * 255)
            g = int(p * 255)
            b = int(brightness * 255)
        elif h == 5:
            r = int(brightness * 255)
            g = int(p * 255)
            b = int(q * 255)
    return 0xff000000L | (r << 16) | (g << 8) | (b << 0)
Пример #18
0
def Wrap(context, text, width):
    """
    f:wrap() returns a string with the text reflowed so that each line
    fits within the given width. Existing linefeeds are preserved, but
    spaces are considered inter-word separators that can be collapsed.
    To reflow without preserving existing linefeeds, strip them first,
    e.g. with translate(text, '&#10;', '').
    http://lists.fourthought.com/pipermail/4suite-dev/2002-December/000878.html
    """
    s = Conversions.StringValue(text)
    width = Conversions.NumberValue(width)
    return LineWrap(s, width)
Пример #19
0
    def _xu_append(self, context, element, preserveSpace):
        select = element.getAttributeNS(EMPTY_NAMESPACE, u'select')
        if not select:
            raise XUpdateException(XUpdateException.NO_SELECT)

        child = element.getAttributeNS(EMPTY_NAMESPACE, u'child') or u'last()'

        oldNss = context.processorNss
        context.processorNss = Domlette.GetAllNs(element)

        nodeset = self.evaluateExpression(context, select)
        if not isinstance(nodeset, Types.NodesetType) or not nodeset:
            # Error if not a node-set or empty node-set
            raise XUpdateException(XUpdateException.INVALID_SELECT,
                                   expr=select)

        for refnode in nodeset:
            self.pushDomResult(refnode.ownerDocument)
            # A wrapper element is used in case attributes are being added
            wrapper_localName = 'wrapper'
            wrapper_namespace = EMPTY_NAMESPACE
            try:
                self.writers[-1].startElement(wrapper_localName,
                                              wrapper_namespace)
                for node in element.childNodes:
                    self.visit(context, node, preserveSpace)
            finally:
                self.writers[-1].endElement(wrapper_localName,
                                            wrapper_namespace)
                result = self.popResult()

            size = len(refnode.childNodes)
            con = Context.Context(refnode, 1, size,
                                  processorNss={'xupdate': XUPDATE_NS})
            # Python lists is 0-indexed counting, node-sets 1-indexed
            position = self.evaluateExpression(con, child)
            position = int(Conversions.NumberValue(position))

            wrapper = result.childNodes[0]
            if wrapper.attributes and hasattr(refnode, 'setAttributeNodeNS'):
                for attr in wrapper.attributes.values():
                    refnode.setAttributeNodeNS(attr)

            # we operate on a shallow copy of the child nodes here to avoid
            # modifying the membership of the sequence we're interating over.
            for node in tuple(wrapper.childNodes):
                if position >= size:
                    refnode.appendChild(node)
                else:
                    refnode.insertBefore(node, refnode.childNodes[position])

        context.processorNss = oldNss
        return
Пример #20
0
def pipp_gtitle(context, font, height, texture, bgcolor, text):
    ctx = context.processor.extensionParams[(NAMESPACE, 'context')]

    ctx.add_depends(Conversions.StringValue(font))
    ctx.add_depends(Conversions.StringValue(texture))

    #--
    # Convert the XSLT parameters into regular python types
    #--
    font = ctx.abs_in_path(Conversions.StringValue(font))
    height = int(Conversions.NumberValue(height))
    texture = ctx.abs_in_path(Conversions.StringValue(texture))
    bgcolor = int(Conversions.StringValue(bgcolor)[1:], 16)
    text = Conversions.StringValue(text)
    file_name = re.sub('[^a-zA-Z0-9]', '_', text) + '.png'
    pseudo_in_name = ctx.abs_in_path(file_name)

    # Avoid unwanted cropping
    text = '  ' + text + '  '

    #--
    # Create the text mask
    #--
    im_font = ImageFont.truetype(font, height)
    text_mask = Image.new('RGBA', im_font.getsize(text), 0)
    text_mask_draw = ImageDraw.Draw(text_mask)
    text_mask_draw.text((0, 0), text, font=im_font, fill=(0, 0, 0, 0xFF))
    text_mask = text_mask.crop(text_mask.getbbox())

    #--
    # Create the background pattern
    #--
    texture = Image.open(texture)
    background = Image.new('RGBA', text_mask.size)
    for x in range(0, 1 + text_mask.size[0] / texture.size[0]):
        for y in range(0, 1 + text_mask.size[1] / texture.size[1]):
            background.paste(texture,
                             (x * texture.size[0], y * texture.size[1]))

    #--
    # Create the final image
    #--
    out = Image.new('RGBA', text_mask.size, bgcolor)
    out.paste(background, (0, 0), text_mask)
    out = out.convert('P')
    out.save(ctx.abs_out_path(pseudo_in_name), transparency=0)

    #--
    # Add image to cache using fake inroot name, so width/height functions work
    #--
    images[pseudo_in_name] = out

    return file_name
Пример #21
0
def Sqrt(context, num):
    """
    The math:sqrt function returns the square root of a number.
    """
    # The platform C library determines what math.sqrt() returns.
    # On some platforms, especially prior to Python 2.4,
    # nan may be returned for a negative or nan argument.
    # On other platforms, and especially since Python 2.4,
    # a ValueError is raised.
    #
    # EXSLT requires that we return zero for negative arg.
    # The result for a nan arg is undefined, but we'll return nan.
    n = Conversions.NumberValue(num)
    if number.isnan(n):
        return number.nan
    if n < 0.0:
        return 0.0
    try:
        return math.sqrt(Conversions.NumberValue(num))
    except ValueError:
        return 0.0
Пример #22
0
def PytimeToExslt(context, t=None):
    """
    Takes a Python time value as a number and returns a date/time as if
    from EXSLT date-time()
    t - a time stamp number, as from Python's time.time()
        if omitted, use the current time
    """
    from Ft.Lib import Time as FtTime
    if t is not None:
        t = Conversions.NumberValue(t)
        return unicode(str(FtTime.FromPythonTime(t)), errors='replace')
    else:
        return unicode(str(FtTime.FromPythonTime()), errors='replace')
Пример #23
0
def Padding(context, length, chars=None):
    """
    The str:padding function creates a padding string of a certain length.

    The second argument gives a string to be used to create the padding.
    This string is repeated as many times as is necessary to create a string
    of the length specified by the first argument; if the string is more than
    a character long, it may have to be truncated to produce the required
    length. If no second argument is specified, it defaults to a space (' ').
    """
    length = int(Conversions.NumberValue(length))
    chars = chars and Conversions.StringValue(chars) or u' '
    return (chars * length)[:length]
Пример #24
0
def Range(context, lo, hi):
    """
    Returns a node-set consisting of text nodes encapsulating integers
    in the numeric range bounded by the given low and high values.
    """
    # contributed by Lars Marius Garshol;
    # originally using namespace URI 'http://garshol.priv.no/symbolic/'
    doc = context.node.rootNode

    # sanity check
    for n in (lo, hi):
        if number.isinf(n) or number.isnan(n):
            raise ValueError("Arguments to ft:range must be neither infinite nor NaN.")

    #xrange wants int, not float
    lo = int(round(Conversions.NumberValue(lo)))
    hi = int(round(Conversions.NumberValue(hi)))

    nodeset = []
    for num in xrange(lo, hi):
        nodeset.append(doc.createTextNode(str(num)))

    return nodeset
Пример #25
0
def Random(context, max=None, forceInt=0):
    """
    Returns a random number between 0 (inclusive) and max (exclusive).
    max defaults to 1. The first optional argument is a different
    value for max, and the second argument is a flag that, if set,
    causes the random number to be rounded to an integer.
    See also: EXSLT's math:random()
    """
    if max:
        max = Conversions.NumberValue(max)
    else:
        max = 1.0
    rt = DEFAULT_RNG.randrange(0, max)
    if forceInt:
        rt = round(rt)
    return rt
Пример #26
0
def Indent(context, text, levels, indentstring=None):
    """
    f:indent() returns a string with each line of the text indented the
    given number of levels. For each level, the indent string, normally
    2 spaces by default, is prepended to each line.
    """
    text = Conversions.StringValue(text)
    levels = int(Conversions.NumberValue(levels))
    if indentstring is None:
        indentstring = u'  '
    else:
        indentstring = Conversions.StringValue(indentstring)
    if indentstring and levels > 0:
        indent = indentstring * levels
        return indent + ('\n' + indent).join(text.split('\n'))
    else:
        return text
Пример #27
0
def Sum(context, nodeset, string):
    """
    The dyn:sum function calculates the sum for the nodes passed as the first
    argument, where the value of each node is calculated dynamically using an
    XPath expression passed as a string as the second argument.
    
    http://www.exslt.org/dyn/functions/sum/index.html
    """
    if type(nodeset) != type([]):
        raise XsltRuntimeException(Error.WRONG_ARGUMENT_TYPE,
                                   context.currentInstruction)
    string = Conversions.StringValue(string)
    try:
        expr = parser.new().parse(string)
    except SyntaxError:
        tb = handle_traceback()
        msg = 'Syntax error in XPath "%s", masked by empty node set return:\n%s' % (
            string, tb.getvalue())
        context.processor.warning(msg)
        return []
    return sum(
        [Conversions.NumberValue(n) for n in MapImpl(context, nodeset, expr)])
Пример #28
0
def Duration(context, seconds=None):
    """
    The date:duration function returns a duration string representing the
    number of seconds specified by the argument string. If no argument is
    given, then the result of calling date:seconds without any arguments is
    used as a default argument.

    Implements version 1.
    """
    if seconds is None:
        # The epoch for EXSLT is 1970-01-01T00:00:00Z
        # FIXME: we could code around this, but most (all?) platforms we
        # support have a time() epoch of 1970-01-01, so why bother.
        if time.mktime((1970, 1, 1, 0, 0, 0, 0, 0, 0)) != time.timezone:
            warnings.warn("platform epoch != 1970-01-01", RuntimeWarning)
        # Don't use fractional seconds to keep with constructed dateTimes
        seconds = int(time.time())
    else:
        seconds = Conversions.NumberValue(seconds)
        if not number.finite(seconds):
            # +/-Inf or NaN
            return u''
    duration = _Duration(negative=(seconds < 0), seconds=abs(seconds))
    return unicode(duration)
Пример #29
0
def Java_Integer_ToHexString(context, number):
    return '%X' % Conversions.NumberValue(number)
Пример #30
0
def Java_Color_GetBlue(context, color):
    color = Conversions.NumberValue(color)
    return long(color) & 0xff