Exemplo n.º 1
0
 def proxy(*args, **kwargs):
     """ Proxy function """
     from tdi import c
     if c.load(test) is None:
         skip("c extension not found")
     for mod in module:
         reload(mod)
     return func(*args, **kwargs)
Exemplo n.º 2
0
 def proxy(*args, **kwargs):
     """ Proxy function """
     from tdi import c
     if c.load(test) is None:
         raise SkipTest("c extension not found")
     for mod in module:
         reload(mod)
     return func(*args, **kwargs)
Exemplo n.º 3
0
def test_load_none(imp, os):
    """ c.load() returns None if overridden """
    imp.side_effect = []
    os.environ.get.side_effect = ["1"]

    result = _c.load('foo')

    assert_equals(result, None)
    assert_equals(map(tuple, imp.mock_calls), [])
    assert_equals(map(tuple, os.mock_calls), [
        ('environ.get', ('TDI_NO_C_OVERRIDE',), {}),
    ])
Exemplo n.º 4
0
def test_load_tpl(imp, os, glob, loc):
    """ c.load() accepts different template """
    imp.side_effect = ['lalala']
    os.environ.get.side_effect = [None]
    glob.side_effect = [dict(a=1, b=2)]
    loc.side_effect = [dict(c=4, d=5)]

    result = _c.load('foo', tpl='_xx_%s_yy_')

    assert_equals(result, 'lalala')
    assert_equals(map(tuple, imp.mock_calls), [
        ('', ('_xx_foo_yy_', {'a': 1, 'b': 2}, {'c': 4, 'd': 5}, ['*']), {}),
    ])
    assert_equals(map(tuple, os.mock_calls), [
        ('environ.get', ('TDI_NO_C_OVERRIDE',), {}),
    ])
    assert_equals(map(tuple, glob.mock_calls), [('', (), {})])
    assert_equals(map(tuple, loc.mock_calls), [('', (), {})])
Exemplo n.º 5
0
def test_load_override(imp, os, glob, loc):
    """ c.load() accepts different override """
    imp.side_effect = ['lalala']
    os.environ.get.side_effect = [None]
    glob.side_effect = [dict(a=1, b=2)]
    loc.side_effect = [dict(c=4, d=5)]

    result = _c.load('foo', env_override='YO')

    assert_equals(result, 'lalala')
    assert_equals(map(tuple, imp.mock_calls), [
        ('', ('tdi.c._tdi_foo', {'a': 1, 'b': 2}, {'c': 4, 'd': 5}, ['*']),
         {}),
    ])
    assert_equals(map(tuple, os.mock_calls), [
        ('environ.get', ('YO',), {}),
    ])
    assert_equals(map(tuple, glob.mock_calls), [('', (), {})])
    assert_equals(map(tuple, loc.mock_calls), [('', (), {})])
Exemplo n.º 6
0
def test_load(imp, os, glob, loc):
    """ c.load() imports and returns a module """
    imp.side_effect = ['lalala']
    os.environ.get.side_effect = [None]
    glob.side_effect = [dict(a=1, b=2)]
    loc.side_effect = [dict(c=4, d=5)]

    result = _c.load('foo')

    assert_equals(result, 'lalala')
    assert_equals(map(tuple, imp.mock_calls), [
        ('', ('tdi.c._tdi_foo', {'a': 1, 'b': 2}, {'c': 4, 'd': 5}, ['*']),
         {}),
    ])
    assert_equals(map(tuple, os.mock_calls), [
        ('environ.get', ('TDI_NO_C_OVERRIDE',), {}),
    ])
    assert_equals(map(tuple, glob.mock_calls), [('', (), {})])
    assert_equals(map(tuple, loc.mock_calls), [('', (), {})])
Exemplo n.º 7
0
def test_load_space_delc(imp, os, glob, loc):
    """ c.load() modifies space and deletes 'c' """
    mod = _test.Bunch(bar='BAZ', plop='blub')
    imp.side_effect = [mod]
    os.environ.get.side_effect = [None]
    glob.side_effect = [dict(a=1, b=2)]
    loc.side_effect = [dict(c=4, d=5)]
    space = dict(plop=42, c='something', d='else')

    result = _c.load('foo', space)

    assert_equals(space, {'plop': 'blub', 'd': 'else'})
    assert_equals(result, mod)
    assert_equals(map(tuple, imp.mock_calls), [
        ('', ('tdi.c._tdi_foo', {'a': 1, 'b': 2}, {'c': 4, 'd': 5}, ['*']),
         {}),
    ])
    assert_equals(map(tuple, os.mock_calls), [
        ('environ.get', ('TDI_NO_C_OVERRIDE',), {}),
    ])
    assert_equals(map(tuple, glob.mock_calls), [('', (), {})])
    assert_equals(map(tuple, loc.mock_calls), [('', (), {})])
Exemplo n.º 8
0
                        flags = node.hiddenelement and '-' or '+'
                        if noauto:
                            flags += '*'
                        if sep:
                            flags += ':'
                        node[tdi_attr] = flags + name
                        node.hiddenelement = False

                def separate(node, ctx):
                    """ Separator """
                    node.ctx = ctx
                    return render(node, sep=True)

                node.repeat(repeat, (0, 1), node.ctx, separate=separate)

            if name is None:
                return setscope
            return render

        self.modelmethod = modelmethod
        self.new = new

        return self


from tdi import c
c = c.load('impl')
if c is not None:
    RenderAdapter = c.RenderAdapter
del c
Exemplo n.º 9
0
def _make_decode():
    """ Make decoder """
    # pylint: disable = R0912

    from tdi import c
    c = c.load('impl')
    if c is not None:
        return c.htmldecode

    sub = _re.compile(ur'&([^& \t\n\r\f;]*);').sub
    unicode_, unichr_, str_, int_ = unicode, unichr, str, int
    isinstance_ = isinstance
    default_entities = dict(_htmlentities.htmlentities)

    # pylint: disable = W0621
    def decode(value, encoding='latin-1', errors='strict', entities=None):
        """
        Decode HTML encoded text

        :Parameters:
          `value` : ``basestring``
            HTML content to decode

          `encoding` : ``str``
            Unicode encoding to be applied before value is being processed
            further. If value is already a unicode instance, the encoding is
            ignored. If omitted, 'latin-1' is applied (because it can't fail
            and maps bytes 1:1 to unicode codepoints).

          `errors` : ``str``
            Error handling, passed to .decode() and evaluated for entities.
            If the entity name or character codepoint could not be found or
            not be parsed then the error handler has the following semantics:

            ``strict`` (or anything different from the other tokens below)
                A ``ValueError`` is raised.

            ``ignore``
                The original entity is passed through

            ``replace``
                The character is replaced by the replacement character
                (U+FFFD)

          `entities` : ``dict``
            Entity name mapping (unicode(name) -> unicode(value)). If
            omitted or ``None``, the `HTML5 entity list`_ is applied.

            .. _HTML5 entity list: http://www.w3.org/TR/html5/
               syntax.html#named-character-references

        :Return: The decoded content
        :Rtype: ``unicode``
        """
        # pylint: disable = E1101
        # pylint: disable = R0912
        if not isinstance_(value, unicode_):
            value = str_(value).decode(encoding, errors)
        if entities is None:
            entities = default_entities
        def subber(match):
            """ Substituter """
            name = match.group(1)
            if not name.startswith(u'#'):
                try:
                    return entities[name]
                except KeyError:
                    pass
            else:
                if name.startswith(u'#x') or name.startswith(u'#X'):
                    base = 16
                    name = name[2:]
                else:
                    base = 10
                    name = name[1:]
                try:
                    return unichr_(int_(name, base))
                except (ValueError, TypeError, OverflowError):
                    pass

            if errors == 'ignore':
                return match.group(0)
            elif errors == 'replace':
                return u'\ufffd'
            else:
                raise ValueError(
                    "Unresolved entity %r" % (match.group(0),)
                )

        return sub(subber, value)
    return decode
Exemplo n.º 10
0
def _make_cssmin(python_only=False):
    """
    Generate CSS minifier.

    :Parameters:
      `python_only` : ``bool``
        Use only the python variant. If true, the c extension is not even
        tried to be loaded. (tdi.c._tdi_rcssmin)

    :Return: Minifier
    :Rtype: ``callable``
    """
    # pylint: disable = W0612
    # ("unused" variables)

    # pylint: disable = R0911, R0912, R0914, R0915
    # (too many anything)

    if not python_only:
        from tdi import c
        rcssmin = c.load('rcssmin')
        if rcssmin is not None:
            return rcssmin.cssmin

    nl = r'(?:[\n\f]|\r\n?)' # pylint: disable = C0103
    spacechar = r'[\r\n\f\040\t]'

    unicoded = r'[0-9a-fA-F]{1,6}(?:[\040\n\t\f]|\r\n?)?'
    escaped = r'[^\n\r\f0-9a-fA-F]'
    escape = r'(?:\\(?:%(unicoded)s|%(escaped)s))' % locals()

    nmchar = r'[^\000-\054\056\057\072-\100\133-\136\140\173-\177]'
    #nmstart = r'[^\000-\100\133-\136\140\173-\177]'
    #ident = (r'(?:'
    #    r'-?(?:%(nmstart)s|%(escape)s)%(nmchar)s*(?:%(escape)s%(nmchar)s*)*'
    #r')') % locals()

    comment = r'(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/)'

    # only for specific purposes. The bang is grouped:
    _bang_comment = r'(?:/\*(!?)[^*]*\*+(?:[^/*][^*]*\*+)*/)'

    string1 = \
        r'(?:\047[^\047\\\r\n\f]*(?:\\[^\r\n\f][^\047\\\r\n\f]*)*\047)'
    string2 = r'(?:"[^"\\\r\n\f]*(?:\\[^\r\n\f][^"\\\r\n\f]*)*")'
    strings = r'(?:%s|%s)' % (string1, string2)

    nl_string1 = \
        r'(?:\047[^\047\\\r\n\f]*(?:\\(?:[^\r]|\r\n?)[^\047\\\r\n\f]*)*\047)'
    nl_string2 = r'(?:"[^"\\\r\n\f]*(?:\\(?:[^\r]|\r\n?)[^"\\\r\n\f]*)*")'
    nl_strings = r'(?:%s|%s)' % (nl_string1, nl_string2)

    uri_nl_string1 = r'(?:\047[^\047\\]*(?:\\(?:[^\r]|\r\n?)[^\047\\]*)*\047)'
    uri_nl_string2 = r'(?:"[^"\\]*(?:\\(?:[^\r]|\r\n?)[^"\\]*)*")'
    uri_nl_strings = r'(?:%s|%s)' % (uri_nl_string1, uri_nl_string2)

    nl_escaped = r'(?:\\%(nl)s)' % locals()

    space = r'(?:%(spacechar)s|%(comment)s)' % locals()

    ie7hack = r'(?:>/\*\*/)'

    uri = (r'(?:'
        r'(?:[^\000-\040"\047()\\\177]*'
            r'(?:%(escape)s[^\000-\040"\047()\\\177]*)*)'
        r'(?:'
            r'(?:%(spacechar)s+|%(nl_escaped)s+)'
            r'(?:'
                r'(?:[^\000-\040"\047()\\\177]|%(escape)s|%(nl_escaped)s)'
                r'[^\000-\040"\047()\\\177]*'
                r'(?:%(escape)s[^\000-\040"\047()\\\177]*)*'
            r')+'
        r')*'
    r')') % locals()

    nl_unesc_sub = _re.compile(nl_escaped).sub

    uri_space_sub = _re.compile((
        r'(%(escape)s+)|%(spacechar)s+|%(nl_escaped)s+'
    ) % locals()).sub
    uri_space_subber = lambda m: m.groups()[0] or ''

    space_sub_simple = _re.compile((
        r'[\r\n\f\040\t;]+|(%(comment)s+)'
    ) % locals()).sub
    space_sub_banged = _re.compile((
        r'[\r\n\f\040\t;]+|(%(_bang_comment)s+)'
    ) % locals()).sub

    post_esc_sub = _re.compile(r'[\r\n\f\t]+').sub

    main_sub = _re.compile((
        r'([^\\"\047u>@\r\n\f\040\t/;:{}]+)'
        r'|(?<=[{}(=:>+[,!])(%(space)s+)'
        r'|^(%(space)s+)'
        r'|(%(space)s+)(?=(([:{});=>+\],!])|$)?)'
        r'|;(%(space)s*(?:;%(space)s*)*)(?=(\})?)'
        r'|(\{)'
        r'|(\})'
        r'|(%(strings)s)'
        r'|(?<!%(nmchar)s)url\(%(spacechar)s*('
                r'%(uri_nl_strings)s'
                r'|%(uri)s'
            r')%(spacechar)s*\)'
        r'|(@(?:'
              r'[mM][eE][dD][iI][aA]'
              r'|[sS][uU][pP][pP][oO][rR][tT][sS]'
              r'|[dD][oO][cC][uU][mM][eE][nN][tT]'
              r'|(?:-(?:'
                  r'[wW][eE][bB][kK][iI][tT]|[mM][oO][zZ]|[oO]|[mM][sS]'
                r')-)?'
                r'[kK][eE][yY][fF][rR][aA][mM][eE][sS]'
            r'))(?!%(nmchar)s)'
        r'|(%(ie7hack)s)(%(space)s*)'
        r'|(:[fF][iI][rR][sS][tT]-[lL]'
            r'(?:[iI][nN][eE]|[eE][tT][tT][eE][rR]))'
            r'(%(space)s*)(?=[{,])'
        r'|(%(nl_strings)s)'
        r'|(%(escape)s[^\\"\047u>@\r\n\f\040\t/;:{}]*)'
    ) % locals()).sub

    #print main_sub.__self__.pattern

    def main_subber(keep_bang_comments):
        """ Make main subber """
        in_macie5, in_rule, at_group = [0], [0], [0]

        if keep_bang_comments:
            space_sub = space_sub_banged
            def space_subber(match):
                """ Space|Comment subber """
                if match.lastindex:
                    group1, group2 = match.group(1, 2)
                    if group2:
                        if group1.endswith(r'\*/'):
                            in_macie5[0] = 1
                        else:
                            in_macie5[0] = 0
                        return group1
                    elif group1:
                        if group1.endswith(r'\*/'):
                            if in_macie5[0]:
                                return ''
                            in_macie5[0] = 1
                            return r'/*\*/'
                        elif in_macie5[0]:
                            in_macie5[0] = 0
                            return '/**/'
                return ''
        else:
            space_sub = space_sub_simple
            def space_subber(match):
                """ Space|Comment subber """
                if match.lastindex:
                    if match.group(1).endswith(r'\*/'):
                        if in_macie5[0]:
                            return ''
                        in_macie5[0] = 1
                        return r'/*\*/'
                    elif in_macie5[0]:
                        in_macie5[0] = 0
                        return '/**/'
                return ''

        def fn_space_post(group):
            """ space with token after """
            if group(5) is None or (
                    group(6) == ':' and not in_rule[0] and not at_group[0]):
                return ' ' + space_sub(space_subber, group(4))
            return space_sub(space_subber, group(4))

        def fn_semicolon(group):
            """ ; handler """
            return ';' + space_sub(space_subber, group(7))

        def fn_semicolon2(group):
            """ ; handler """
            if in_rule[0]:
                return space_sub(space_subber, group(7))
            return ';' + space_sub(space_subber, group(7))

        def fn_open(group):
            """ { handler """
            # pylint: disable = W0613
            if at_group[0]:
                at_group[0] -= 1
            else:
                in_rule[0] = 1
            return '{'

        def fn_close(group):
            """ } handler """
            # pylint: disable = W0613
            in_rule[0] = 0
            return '}'

        def fn_at_group(group):
            """ @xxx group handler """
            at_group[0] += 1
            return group(13)

        def fn_ie7hack(group):
            """ IE7 Hack handler """
            if not in_rule[0] and not at_group[0]:
                in_macie5[0] = 0
                return group(14) + space_sub(space_subber, group(15))
            return '>' + space_sub(space_subber, group(15))

        table = (
            None,
            None,
            None,
            None,
            fn_space_post,                      # space with token after
            fn_space_post,                      # space with token after
            fn_space_post,                      # space with token after
            fn_semicolon,                       # semicolon
            fn_semicolon2,                      # semicolon
            fn_open,                            # {
            fn_close,                           # }
            lambda g: g(11),                    # string
            lambda g: 'url(%s)' % uri_space_sub(uri_space_subber, g(12)),
                                                # url(...)
            fn_at_group,                        # @xxx expecting {...}
            None,
            fn_ie7hack,                         # ie7hack
            None,
            lambda g: g(16) + ' ' + space_sub(space_subber, g(17)),
                                                # :first-line|letter followed
                                                # by [{,] (apparently space
                                                # needed for IE6)
            lambda g: nl_unesc_sub('', g(18)),  # nl_string
            lambda g: post_esc_sub(' ', g(19)), # escape
        )

        def func(match):
            """ Main subber """
            idx, group = match.lastindex, match.group
            if idx > 3:
                return table[idx](group)

            # shortcuts for frequent operations below:
            elif idx == 1:     # not interesting
                return group(1)
            #else: # space with token before or at the beginning
            return space_sub(space_subber, group(idx))

        return func

    def cssmin(style, keep_bang_comments=False): # pylint: disable = W0621
        """
        Minify CSS.

        :Parameters:
          `style` : ``str``
            CSS to minify

          `keep_bang_comments` : ``bool``
            Keep comments starting with an exclamation mark? (``/*!...*/``)

        :Return: Minified style
        :Rtype: ``str``
        """
        return main_sub(main_subber(keep_bang_comments), style)

    return cssmin
Exemplo n.º 11
0
Arquivo: rjsmin.py Projeto: AvdN/tdi
def _make_jsmin(python_only=False):
    """
    Generate JS minifier based on `jsmin.c by Douglas Crockford`_

    .. _jsmin.c by Douglas Crockford:
       http://www.crockford.com/javascript/jsmin.c

    :Parameters:
      `python_only` : ``bool``
        Use only the python variant. If true, the c extension is not even
        tried to be loaded. (tdi.c._tdi_rjsmin)

    :Return: Minifier
    :Rtype: ``callable``
    """
    # pylint: disable = R0912, R0914, W0612
    if not python_only:
        from tdi import c
        rjsmin = c.load('rjsmin')
        if rjsmin is not None:
            return rjsmin.jsmin
    try:
        xrange
    except NameError:
        xrange = range # pylint: disable = W0622

    space_chars = r'[\000-\011\013\014\016-\040]'

    line_comment = r'(?://[^\r\n]*)'
    space_comment = r'(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/)'
    string1 = \
        r'(?:\047[^\047\\\r\n]*(?:\\(?:[^\r\n]|\r?\n|\r)[^\047\\\r\n]*)*\047)'
    string2 = r'(?:"[^"\\\r\n]*(?:\\(?:[^\r\n]|\r?\n|\r)[^"\\\r\n]*)*")'
    strings = r'(?:%s|%s)' % (string1, string2)

    charclass = r'(?:\[[^\\\]\r\n]*(?:\\[^\r\n][^\\\]\r\n]*)*\])'
    nospecial = r'[^/\\\[\r\n]'
    regex = r'(?:/(?![\r\n/*])%s*(?:(?:\\[^\r\n]|%s)%s*)*/)' % (
        nospecial, charclass, nospecial
    )
    space = r'(?:%s|%s)' % (space_chars, space_comment)
    newline = r'(?:%s?[\r\n])' % line_comment

    def fix_charclass(result):
        """ Fixup string of chars to fit into a regex char class """
        pos = result.find('-')
        if pos >= 0:
            result = r'%s%s-' % (result[:pos], result[pos + 1:])

        def sequentize(string):
            """
            Notate consecutive characters as sequence

            (1-4 instead of 1234)
            """
            first, last, result = None, None, []
            for char in map(ord, string):
                if last is None:
                    first = last = char
                elif last + 1 == char:
                    last = char
                else:
                    result.append((first, last))
                    first = last = char
            if last is not None:
                result.append((first, last))
            return ''.join(['%s%s%s' % (
                chr(first),
                last > first + 1 and '-' or '',
                last != first and chr(last) or ''
            ) for first, last in result])

        return _re.sub(r'([\000-\040\047])', # for better portability
            lambda m: '\\%03o' % ord(m.group(1)), (sequentize(result)
                .replace('\\', '\\\\')
                .replace('[', '\\[')
                .replace(']', '\\]')
            )
        )

    def id_literal_(what):
        """ Make id_literal like char class """
        match = _re.compile(what).match
        result = ''.join([
            chr(c) for c in xrange(127) if not match(chr(c))
        ])
        return '[^%s]' % fix_charclass(result)

    def not_id_literal_(keep):
        """ Make negated id_literal like char class """
        match = _re.compile(id_literal_(keep)).match
        result = ''.join([
            chr(c) for c in xrange(127) if not match(chr(c))
        ])
        return r'[%s]' % fix_charclass(result)

    not_id_literal = not_id_literal_(r'[a-zA-Z0-9_$]')
    preregex1 = r'[(,=:\[!&|?{};\r\n]'
    preregex2 = r'%(not_id_literal)sreturn' % locals()

    id_literal = id_literal_(r'[a-zA-Z0-9_$]')
    id_literal_open = id_literal_(r'[a-zA-Z0-9_${\[(!+-]')
    id_literal_close = id_literal_(r'[a-zA-Z0-9_$}\])"\047+-]')

    dull = r'[^\047"/\000-\040]'

    space_sub = _re.compile((
        r'(%(dull)s+)'
        r'|(%(strings)s%(dull)s*)'
        r'|(?<=%(preregex1)s)'
            r'%(space)s*(?:%(newline)s%(space)s*)*'
            r'(%(regex)s%(dull)s*)'
        r'|(?<=%(preregex2)s)'
            r'%(space)s*(?:%(newline)s%(space)s)*'
            r'(%(regex)s%(dull)s*)'
        r'|(?<=%(id_literal_close)s)'
            r'%(space)s*(?:(%(newline)s)%(space)s*)+'
            r'(?=%(id_literal_open)s)'
        r'|(?<=%(id_literal)s)(%(space)s)+(?=%(id_literal)s)'
        r'|(?<=\+)(%(space)s)+(?=\+)'
        r'|(?<=-)(%(space)s)+(?=-)'
        r'|%(space)s+'
        r'|(?:%(newline)s%(space)s*)+'
    ) % locals()).sub
    #print space_sub.__self__.pattern

    def space_subber(match):
        """ Substitution callback """
        # pylint: disable = C0321, R0911
        groups = match.groups()
        if groups[0]: return groups[0]
        elif groups[1]: return groups[1]
        elif groups[2]: return groups[2]
        elif groups[3]: return groups[3]
        elif groups[4]: return '\n'
        elif groups[5] or groups[6] or groups[7]: return ' '
        else: return ''

    def jsmin(script): # pylint: disable = W0621
        r"""
        Minify javascript based on `jsmin.c by Douglas Crockford`_\.

        Instead of parsing the stream char by char, it uses a regular
        expression approach which minifies the whole script with one big
        substitution regex.

        .. _jsmin.c by Douglas Crockford:
           http://www.crockford.com/javascript/jsmin.c

        :Parameters:
          `script` : ``str``
            Script to minify

        :Return: Minified script
        :Rtype: ``str``
        """
        return space_sub(space_subber, '\n%s\n' % script).strip()

    return jsmin