[Checkins] SVN: z3c.cssresource/trunk/src/z3c/cssresource/ Totally reimplemented this code and gave it a different name. Now we

Stephan Richter srichter at cosmos.phy.tufts.edu
Tue Aug 15 11:57:07 EDT 2006


Log message for revision 69510:
  Totally reimplemented this code and gave it a different name. Now we 
  have a really small mini-language that can be embedded into any 
  programming language.
  
  This will temporary break the functionality until I am done with 
  renaming.
  
  

Changed:
  U   z3c.cssresource/trunk/src/z3c/cssresource/README.txt
  U   z3c.cssresource/trunk/src/z3c/cssresource/SETUP.cfg
  U   z3c.cssresource/trunk/src/z3c/cssresource/__init__.py
  D   z3c.cssresource/trunk/src/z3c/cssresource/cssresource.py
  A   z3c.cssresource/trunk/src/z3c/cssresource/interfaces.py
  U   z3c.cssresource/trunk/src/z3c/cssresource/meta.zcml
  A   z3c.cssresource/trunk/src/z3c/cssresource/processor.py
  A   z3c.cssresource/trunk/src/z3c/cssresource/replace.py
  U   z3c.cssresource/trunk/src/z3c/cssresource/tests.py
  D   z3c.cssresource/trunk/src/z3c/cssresource/z3c.cssresource-meta.zcml
  A   z3c.cssresource/trunk/src/z3c/cssresource/z3c.zrtresource-meta.zcml
  U   z3c.cssresource/trunk/src/z3c/cssresource/zcml.py
  U   z3c.cssresource/trunk/src/z3c/cssresource/zcml.txt
  A   z3c.cssresource/trunk/src/z3c/cssresource/zrtresource.py

-=-
Modified: z3c.cssresource/trunk/src/z3c/cssresource/README.txt
===================================================================
--- z3c.cssresource/trunk/src/z3c/cssresource/README.txt	2006-08-15 15:11:36 UTC (rev 69509)
+++ z3c.cssresource/trunk/src/z3c/cssresource/README.txt	2006-08-15 15:57:07 UTC (rev 69510)
@@ -1,31 +1,38 @@
-==================
-CSS File Resources
-==================
+===================
+Templated Resources
+===================
 
 One of the design goals of Zope is to allow designers to check in HTML
 template, CSS and Javascript files, which just work (with some additional
-information). For templates we use Zope's Page Templates to accomplish this
-objective. For CSS and Javascript we did not need such a feature, since
-nothing should be dynamic, due to chaching.
+information). For HTML code we use Zope's Page Templates to accomplish this
+objective. For CSS and Javascript we did not need such a feature until now,
+since those files were largely static or variables could be inserted using
+other ways at runtime.
 
-However, now URLs -- for example for background images -- are frequently
-inserted into CSS files. However, the path layout for the designer might not
-equal that to the resource file structure. This package provides a simple
-mechanism to replace strings by another.
+However, in CSS URLs -- for example for background images -- are now
+frequently inserted into CSS directives. However, the path layout for the
+designer might not equal the resource file structure. This package provides a
+simple mechanism to replace strings by another.
 
-To accomplish this task, a custom CSS file resource is provided. The replace
-syntax is provided inside CSS comments. The commands are as follows:
+To accomplish this, a templated resource is provided. The template syntax is
+provided in a way that it does not interfere with the syntax of the
+resource. For both, Javascript and CSS, this is a comment of the form ``/*
+... */``.
 
-- ``/* zope-global-replace: "ORIGINAL" "FINAL" */``
+Here is the general syntax::
 
-(Yes, for now it is only one.)
+  <COMMAND-BEGIN> <ZRT-COMMAND>: <COMMAND-ARGUMENTS> <COMMAND-END>
 
+Here is an example for CSS:
+
+  /* zrt-replace: ".." "@@" */
+
 To demonstrate this feature, we first have to create a CSS file.
 
   >>> import tempfile
   >>> fn = tempfile.mktemp('.css')
   >>> open(fn, 'w').write('''\
-  ... /* zope-global-replace: "../img1" "++resource++/img" */
+  ... /* zrt-replace: "../img1" "++resource++/img" */
   ... h1 {
   ...   color: red;
   ...   background: url('../img1/mybackground.gif');
@@ -35,19 +42,23 @@
   ...   color: red;
   ...   background: url('../img2/mybackground.gif');
   ... }
-  ... /* zope-global-replace: "../img2" "++resource++/img" */
+  ... /* zrt-replace: "../img2" "++resource++/img" */
   ... ''')
 
-As you can see, the command can be placed anywhere.
+The global replace command replaces a string with another. It is only active
+in the lines *after* it was declared. Thus, in this case, the second command
+is meaningless.
 
-Now we create a CSS resource from the resource factory:
+Now we create a ZRT resource from the resource factory ...
 
-  >>> from z3c.cssresource import CSSFileResourceFactory
-  >>> cssFactory = CSSFileResourceFactory(fn, None, 'site.css')
+  >>> from z3c.zrtresource import ZRTFileResourceFactory
+  >>> cssFactory = ZRTFileResourceFactory(fn, None, 'site.css')
 
   >>> from zope.publisher.browser import TestRequest
   >>> css = cssFactory(TestRequest())
 
+and render the resource:
+
   >>> print css.GET()
   h1 {
     color: red;
@@ -56,55 +67,182 @@
   <BLANKLINE>
   h2 {
     color: red;
-    background: url('++resource++/img/mybackground.gif');
+    background: url('../img2/mybackground.gif');
   }
-  <BLANKLINE>
 
+As you can see only the first URL was replaced, because of the incorrect
+position of the second statement.
+
 And that's all! In your ZCML you can use this factory as follows::
 
-  <resource
+  <zrt-resource
       name="site.css"
       path="css/site.css"
-      factory="z3c.cssresource.CSSFileResourceFactory"
       />
 
 
-Global Replace
---------------
+Replacing Strings
+=================
 
-As seen in the example above, ``zope-global-replace`` calls can be placed
+The ``zrt-replace`` command replaces any matches with the output string as
+many times as specified. Here is the syntax:
+
+  zrt-replace: <EXPR-TYPE>"<INPUT-EXPR>" <EXPR-TYPE>"<OUTPUT-EXPR>" <NUM>
+
+As seen in the example above, ``zrt-replace`` calls can be placed
 anywhere in the file. Let's make sure that some special cases work as well:
 
-  >>> from z3c.cssresource import CSSFileResource
-  >>> resource = CSSFileResource(None, None)
+  >>> from z3c.zrtresource import processor, replace
+  >>> def process(text):
+  ...     p = processor.ZRTProcessor(
+  ...         text, commands={'replace': replace.Replace})
+  ...     return p.process(None, None)
 
-  >>> print resource.process('''\
-  ...        /* zope-global-replace: "foo" "bar" */
+  >>> print process('''\
+  ...        /* zrt-replace: "foo" "bar" */
   ... foo''')
   bar
 
-  >>> print resource.process('''\
-  ... /*      zope-global-replace: "foo" "bar"      */
+  >>> print process('''\
+  ... /*      zrt-replace: "foo" "bar"      */
   ... foo''')
   bar
 
-  >>> print resource.process('''\
-  ... /* zope-global-replace:   "foo"         "bar" */
+  >>> print process('''\
+  ... /* zrt-replace:   "foo"         "bar" */
   ... foo''')
   bar
 
 But the following does not work:
 
-  >>> print resource.process('''\
-  ... /* zope-global-replace : "foo" "bar" */
+  >>> print process('''\
+  ... /* zrt-replace : "foo" "bar" */
   ... foo''')
-  /* zope-global-replace : "foo" "bar" */
+  /* zrt-replace : "foo" "bar" */
   foo
 
-  >>> print resource.process('''\
-  ... /* zope -global-replace : "foo" "bar" */
+  >>> print process('''\
+  ... /* zrt -replace : "foo" "bar" */
   ... foo''')
-  /* zope -global-replace : "foo" "bar" */
+  /* zrt -replace : "foo" "bar" */
   foo
 
+Until now we have only considered multiple replacements. Let's now restrict
+the number of replacements with the final argument. Initially all occurences
+of a matching string are replaced:
 
+  >>> print process('''\
+  ... /* zrt-replace: "foo" "bar" */
+  ... foo foo foo foo foo''')
+  bar bar bar bar bar
+
+When we specify a number of replacements, then only that amount is replaced:
+
+  >>> print process('''\
+  ... /* zrt-replace: "foo" "bar" 1 */
+  ... foo foo foo foo foo''')
+  bar foo foo foo foo
+
+  >>> print process('''\
+  ... /* zrt-replace: "foo" "bar" 3 */
+  ... foo foo foo foo foo''')
+  bar bar bar foo foo
+
+  >>> print process('''\
+  ... /* zrt-replace: "foo" "bar" 6 */
+  ... foo foo foo foo foo''')
+  bar bar bar bar bar
+
+
+The String Expression
+---------------------
+
+Until now we have only dealt with simple string replacement, since it is the
+default expression type. Another way of spelling the expression type is:
+
+  >>> print process('''\
+  ... /* zrt-replace: str"foo" "bar" */
+  ... foo''')
+  bar
+
+  >>> print process('''\
+  ... /* zrt-replace: "foo" str"bar" */
+  ... foo''')
+  bar
+
+  >>> print process('''\
+  ... /* zrt-replace: str"foo" str"bar" */
+  ... foo''')
+  bar
+
+
+The Regex Expression
+--------------------
+
+Regular expressions make only sense as input expressions, so they are only
+supported there:
+
+  >>> print process('''\
+  ... /* zrt-replace: re"foo" "bar" */
+  ... foo''')
+  bar
+
+  >>> print process('''\
+  ... /* zrt-replace: re"[a-z]*foo" "bar" */
+  ... myfoo''')
+  bar
+
+We also support groups:
+
+  >>> print process('''\
+  ... /* zrt-replace: re"([a-z]*)foo" "bar" */
+  ... myfoo''')
+  bar
+
+  >>> print process('''\
+  ... /* zrt-replace: re"([a-z]*)foo" "bar" */
+  ... myfoo''')
+  bar
+
+  >>> print process('''\
+  ... /* zrt-replace: re"([a-z]*)foo" "bar" */
+  ... myfoo mybar''')
+  bar mybar
+
+Yes, even group replacement works:
+
+  >>> print process('''\
+  ... /* zrt-replace: re"([a-z]*)foo" "bar\\1" */
+  ... myfoo a9foo''')
+  barmy a9bar
+
+  >>> print process('''\
+  ... /* zrt-replace: re"(?P<prefix>[a-z]*)foo" "bar\\g<prefix>" */
+  ... myfoo a9foo''')
+  barmy a9bar
+
+
+The TALES Expression
+--------------------
+
+What would be a Zope-based templating language without TALES expressions. This
+is particularly useful, if you want create absolute URLs and other dynamic
+bits based on the request and the context:
+
+  >>> import zope.interface
+  >>> from zope.traversing.interfaces import IContainmentRoot
+  >>> class Root(object):
+  ...     zope.interface.implements(IContainmentRoot)
+
+  >>> from zope.publisher.browser import TestRequest
+  >>> def process(text):
+  ...     p = processor.ZRTProcessor(
+  ...         text, commands={'replace': replace.Replace})
+  ...     return p.process(Root(), TestRequest())
+
+  >>> print process('''\
+  ... /* zrt-replace: "foo" tal"string:${context/@@absolute_url}/@@/foo" */
+  ... foo''')
+  http://127.0.0.1/@@/foo
+
+

Modified: z3c.cssresource/trunk/src/z3c/cssresource/SETUP.cfg
===================================================================
--- z3c.cssresource/trunk/src/z3c/cssresource/SETUP.cfg	2006-08-15 15:11:36 UTC (rev 69509)
+++ z3c.cssresource/trunk/src/z3c/cssresource/SETUP.cfg	2006-08-15 15:57:07 UTC (rev 69510)
@@ -1,3 +1,3 @@
 <data-files zopeskel/etc/package-includes>
-  z3c.cssresource-*.zcml
+  z3c.zrtresource-*.zcml
 </data-files>

Modified: z3c.cssresource/trunk/src/z3c/cssresource/__init__.py
===================================================================
--- z3c.cssresource/trunk/src/z3c/cssresource/__init__.py	2006-08-15 15:11:36 UTC (rev 69509)
+++ z3c.cssresource/trunk/src/z3c/cssresource/__init__.py	2006-08-15 15:57:07 UTC (rev 69510)
@@ -1,2 +1,2 @@
 # Make a package
-from cssresource import CSSFileResource, CSSFileResourceFactory
+from zrtresource import ZRTFileResource, ZRTFileResourceFactory

Deleted: z3c.cssresource/trunk/src/z3c/cssresource/cssresource.py
===================================================================
--- z3c.cssresource/trunk/src/z3c/cssresource/cssresource.py	2006-08-15 15:11:36 UTC (rev 69509)
+++ z3c.cssresource/trunk/src/z3c/cssresource/cssresource.py	2006-08-15 15:57:07 UTC (rev 69510)
@@ -1,57 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2001, 2002 Zope Foundation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
-# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
-# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE.
-#
-##############################################################################
-"""CSS Resource
-
-$Id$
-"""
-import re
-
-from zope.app.publisher.fileresource import File
-from zope.app.publisher.browser.fileresource import FileResource
-
-# Allows matches of the form: /* ZOPE-COMMAND: "ORIGINAL" "FINAL" */
-directive_regex = r' */\* *%s: *"([^ "]*)" *"([^ "]*)" *\*/'
-global_replace = re.compile(directive_regex %'zope-global-replace')
-
-class CSSFileResource(FileResource):
-
-    def process(self, data):
-        # Find all directives
-        directives = re.compile(
-            directive_regex %'zope-global-replace').findall(data)
-        # Remove directives from file
-        data = re.compile(
-            (directive_regex+'\n') %'zope-global-replace').sub('', data)
-        # Now execute directives
-        for orig, final in directives:
-            data = data.replace(orig, final)
-        return data
-
-    def GET(self):
-        data = super(CSSFileResource, self).GET()
-        return self.process(data)
-
-
-class CSSFileResourceFactory(object):
-
-    def __init__(self, path, checker, name):
-        self.__file = File(path, name)
-        self.__checker = checker
-        self.__name = name
-
-    def __call__(self, request):
-        resource = CSSFileResource(self.__file, request)
-        resource.__Security_checker__ = self.__checker
-        resource.__name__ = self.__name
-        return resource

Added: z3c.cssresource/trunk/src/z3c/cssresource/interfaces.py
===================================================================
--- z3c.cssresource/trunk/src/z3c/cssresource/interfaces.py	2006-08-15 15:11:36 UTC (rev 69509)
+++ z3c.cssresource/trunk/src/z3c/cssresource/interfaces.py	2006-08-15 15:57:07 UTC (rev 69510)
@@ -0,0 +1,92 @@
+##############################################################################
+#
+# Copyright (c) 2006 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Templated Resource Interfaces
+
+$Id$
+"""
+__docformat__='restructuredtext'
+
+import zope.interface
+import zope.schema
+
+
+class UnknownZRTCommand(ValueError):
+    """An unknown ZRT Command was specified"""
+
+
+class ArgumentError(ValueError):
+    """Error while parsing the command arguments."""
+
+
+class IZRTProcessor(zope.interface.Interface):
+    """ZRT Processor"""
+
+    source = zope.schema.Bytes(
+        title=u'Source',
+        description=u'The source of the expression.')
+
+    def compile():
+        """Compile the source to binary form."""
+
+    def process(context, request):
+        """Process the source with given context and request.
+
+        Return the result string.
+        """
+
+
+class IZRTCommand(zope.interface.Interface):
+    """A ZRT command"""
+
+    isAvailable = zope.schema.Bool(
+        title=u'Is Available',
+        description=u'Tell whether the command is still available.')
+
+    def process(text, context, request):
+        """Process the given text with given context and request.
+
+        Return the result string.
+        """
+
+class IZRTExpression(zope.interface.Interface):
+    """An expression to be used in a command."""
+
+    source = zope.schema.Bytes(
+        title=u'Source',
+        description=u'The source of the expression.')
+
+    context = zope.schema.Object(
+        title=u'Context',
+        description=u'Context of the template, usually a site.',
+        schema=zope.interface.Interface)
+
+    request = zope.schema.Object(
+        title=u'Request',
+        description=u'Request of the template, usually a site.',
+        schema=zope.interface.Interface)
+
+
+class IZRTInputExpression(IZRTExpression):
+
+    def process(text, outputExpr):
+        """Evaluate the expression and update the """
+
+
+class IZRTOutputExpression(IZRTExpression):
+
+    def process(**kw):
+        """Process the expression and return the output string.
+
+        The keyword arguments are additional namespaces.
+        """


Property changes on: z3c.cssresource/trunk/src/z3c/cssresource/interfaces.py
___________________________________________________________________
Name: svn:keywords
   + Id

Modified: z3c.cssresource/trunk/src/z3c/cssresource/meta.zcml
===================================================================
--- z3c.cssresource/trunk/src/z3c/cssresource/meta.zcml	2006-08-15 15:11:36 UTC (rev 69509)
+++ z3c.cssresource/trunk/src/z3c/cssresource/meta.zcml	2006-08-15 15:57:07 UTC (rev 69510)
@@ -5,9 +5,9 @@
   <meta:directives namespace="http://namespaces.zope.org/browser">
 
     <meta:directive
-        name="css-resource"
+        name="zrt-resource"
         schema=".zcml.ICSSResourceDirective"
-        handler=".zcml.cssresource"
+        handler=".zcml.zrtresource"
         />
 
   </meta:directives>

Added: z3c.cssresource/trunk/src/z3c/cssresource/processor.py
===================================================================
--- z3c.cssresource/trunk/src/z3c/cssresource/processor.py	2006-08-15 15:11:36 UTC (rev 69509)
+++ z3c.cssresource/trunk/src/z3c/cssresource/processor.py	2006-08-15 15:57:07 UTC (rev 69510)
@@ -0,0 +1,100 @@
+##############################################################################
+#
+# Copyright (c) 2006 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Templated Resource Processor
+
+$Id$
+"""
+__docformat__='restructuredtext'
+import re
+import zope.interface
+from z3c.zrtresource import interfaces
+
+# <COMMAND-BEGIN> <ZRT-COMMAND>: <COMMAND-ARGUMENTS> <COMMAND-END>
+NAME = r'[a-zA-Z0-9_-]*'
+COMMAND_REGEX = r'%%s(%s):\s*(.*?)\s*%%s' %NAME
+
+TEXTBLOCK=0
+COMMAND=1
+
+class ZRTProcessor(object):
+    """A ZRT Processor"""
+    zope.interface.implements(interfaces.IZRTProcessor)
+
+    commandStartRegex = r'/\*\s*zrt-'
+    commandEndRegex = r'\*/'
+
+    def __init__(self, source, commands=None):
+        self.source = source
+        if not commands:
+            commands = {}
+        self.commands = commands
+        self._bytecode = None
+
+    def compile(self):
+        """See interfaces.IZRTProcessor"""
+        bytecode = []
+        pos = 0
+        # Regular Expression to find commands.
+        regex = re.compile(COMMAND_REGEX %(self.commandStartRegex,
+                                           self.commandEndRegex))
+        # Find all commands
+        for match in regex.finditer(self.source):
+            command, args = match.groups()
+
+            # Make sure the command exists
+            if command not in self.commands:
+                raise interfaces.UnknownZRTCommand(command)
+
+            # Add the previous text block and update position
+            bytecode.append((TEXTBLOCK, self.source[pos:match.start()]))
+            pos = match.end() + 1
+
+            # Add the command
+            bytecode.append(
+                (COMMAND, (command, args, match.start(), match.end())))
+
+        # Add the final textblock
+        bytecode.append((TEXTBLOCK, self.source[pos:]))
+
+        self._bytecode = bytecode
+
+
+    def process(self, context, request):
+        """See interfaces.IZRTProcessor"""
+        if self._bytecode is None:
+            self.compile()
+
+        # List active commands
+        active = []
+        result = []
+        for type, value in self._bytecode:
+            # If the type is a command, simply add it to the list of commands
+            if type is COMMAND:
+                cmd, args, start, end = value
+                active.append(
+                    self.commands[cmd](args, start, end))
+            # If we have a textblock, then work on it.
+            elif type is TEXTBLOCK:
+                # Process any command
+                for cmd in active:
+                    value = cmd.process(value, context, request)
+                    # If the command is no longer available, remove it
+                    if not cmd.isAvailable:
+                        active.remove(cmd)
+                # This block is fully processed now.
+                result.append(value)
+            else:
+                raise ValueError(type)
+
+        return ''.join(result)


Property changes on: z3c.cssresource/trunk/src/z3c/cssresource/processor.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: z3c.cssresource/trunk/src/z3c/cssresource/replace.py
===================================================================
--- z3c.cssresource/trunk/src/z3c/cssresource/replace.py	2006-08-15 15:11:36 UTC (rev 69509)
+++ z3c.cssresource/trunk/src/z3c/cssresource/replace.py	2006-08-15 15:57:07 UTC (rev 69510)
@@ -0,0 +1,123 @@
+##############################################################################
+#
+# Copyright (c) 2006 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Templated Resource Processor
+
+$Id$
+"""
+__docformat__='restructuredtext'
+import re
+import zope.interface
+from zope.app.pagetemplate import engine
+from z3c.cssresource import interfaces
+
+# <EXPR-TYPE>"<INPUT-EXPR>" <EXPR-TYPE>"<OUTPUT-EXPR>" <NUM>
+NAME = r'[a-zA-Z0-9_-]*'
+ARGS_REGEX = re.compile(r' *(%s)"([^ "]*)" *(%s)"([^ "]*)" *([0-9]*)' %(NAME, NAME))
+
+
+class BaseExpression(object):
+
+    def __init__(self, source, context, request):
+        self.source = source
+        self.context = context
+        self.request = request
+
+
+class StringInputExpression(BaseExpression):
+    """A simple string input expression"""
+    zope.interface.implements(interfaces.IZRTInputExpression)
+
+    def process(self, text, outputExpr, count=None):
+        regex = re.compile(re.escape(self.source))
+        return regex.subn(outputExpr.process(), text, count or 0)
+
+
+class StringOutputExpression(BaseExpression):
+    """A simple string input expression"""
+    zope.interface.implements(interfaces.IZRTOutputExpression)
+
+    def process(self, **kw):
+        # Ignore any keyword arguments, since this is static replacement
+        return self.source
+
+
+class RegexInputExpression(BaseExpression):
+    """A regex string input expression"""
+    zope.interface.implements(interfaces.IZRTInputExpression)
+
+    def process(self, text, outputExpr, count=None):
+        regex = re.compile(self.source)
+        return regex.subn(outputExpr.process(), text, count or 0)
+
+
+class TALESOutputExpression(BaseExpression):
+    """A simple string input expression"""
+    zope.interface.implements(interfaces.IZRTOutputExpression)
+
+    def process(self, **kw):
+        expr = engine.TrustedEngine.compile(self.source)
+        kw.update({'context': self.context, 'request': self.request})
+        econtext = engine.TrustedEngine.getContext(kw)
+        return expr(econtext)
+
+
+class Replace(object):
+    """A ZRT Command to replace sub-strings of the text"""
+    zope.interface.implements(interfaces.IZRTCommand)
+
+    inputExpressions = {
+        '': StringInputExpression,
+        'str': StringInputExpression,
+        're': RegexInputExpression,
+        }
+
+    outputExpressions = {
+        '': StringOutputExpression,
+        'str': StringOutputExpression,
+        'tal': TALESOutputExpression,
+        }
+
+    def __init__(self, args, start, end):
+        self.start = start
+        self.end = end
+        self.processArguments(args)
+
+    @property
+    def isAvailable(self):
+        return self.num is None or self.num > 0
+
+    def processArguments(self, args):
+        match = ARGS_REGEX.match(args)
+        if match is None:
+            raise interfaces.ArgumentError(args)
+
+        self.itype, self.input, self.otype, self.output, self.num = match.groups()
+        self.num = self.num and int(self.num) or None
+
+        if self.itype not in self.inputExpressions:
+            raise ValueError(self.itype)
+
+        if self.otype not in self.outputExpressions:
+            raise ValueError(self.otype)
+
+
+    def process(self, text, context, request):
+        iexpr = self.inputExpressions[self.itype](
+            self.input, context, request)
+        oexpr = self.outputExpressions[self.otype](
+            self.output, context, request)
+        text, num = iexpr.process(text, oexpr, self.num)
+        if self.num is not None:
+            self.num -= num
+        return text


Property changes on: z3c.cssresource/trunk/src/z3c/cssresource/replace.py
___________________________________________________________________
Name: svn:keywords
   + Id

Modified: z3c.cssresource/trunk/src/z3c/cssresource/tests.py
===================================================================
--- z3c.cssresource/trunk/src/z3c/cssresource/tests.py	2006-08-15 15:11:36 UTC (rev 69509)
+++ z3c.cssresource/trunk/src/z3c/cssresource/tests.py	2006-08-15 15:57:07 UTC (rev 69510)
@@ -19,13 +19,26 @@
 
 import doctest
 import unittest
+import zope.component
 from zope.app.testing import placelesssetup
 from zope.testing.doctestunit import DocFileSuite
+from zope.traversing import testing
+from zope.traversing.interfaces import ITraversable
+from zope.traversing.namespace import view
 
+
+def setUp(test):
+    placelesssetup.setUp(test)
+    testing.setUp()
+    zope.component.provideAdapter(view, (None, None), ITraversable, name="view")
+
+
 def test_suite():
 
     return unittest.TestSuite((
         DocFileSuite('README.txt',
+                     setUp=setUp,
+                     tearDown=placelesssetup.tearDown,
                      optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS,
                      ),
         DocFileSuite('zcml.txt',

Deleted: z3c.cssresource/trunk/src/z3c/cssresource/z3c.cssresource-meta.zcml
===================================================================
--- z3c.cssresource/trunk/src/z3c/cssresource/z3c.cssresource-meta.zcml	2006-08-15 15:11:36 UTC (rev 69509)
+++ z3c.cssresource/trunk/src/z3c/cssresource/z3c.cssresource-meta.zcml	2006-08-15 15:57:07 UTC (rev 69510)
@@ -1 +0,0 @@
-<include package="z3c.cssresource" file="meta.zcml" />

Copied: z3c.cssresource/trunk/src/z3c/cssresource/z3c.zrtresource-meta.zcml (from rev 69499, z3c.cssresource/trunk/src/z3c/cssresource/z3c.cssresource-meta.zcml)
===================================================================
--- z3c.cssresource/trunk/src/z3c/cssresource/z3c.cssresource-meta.zcml	2006-08-15 02:20:28 UTC (rev 69499)
+++ z3c.cssresource/trunk/src/z3c/cssresource/z3c.zrtresource-meta.zcml	2006-08-15 15:57:07 UTC (rev 69510)
@@ -0,0 +1 @@
+<include package="z3c.zrtresource" file="meta.zcml" />

Modified: z3c.cssresource/trunk/src/z3c/cssresource/zcml.py
===================================================================
--- z3c.cssresource/trunk/src/z3c/cssresource/zcml.py	2006-08-15 15:11:36 UTC (rev 69509)
+++ z3c.cssresource/trunk/src/z3c/cssresource/zcml.py	2006-08-15 15:57:07 UTC (rev 69510)
@@ -23,7 +23,7 @@
 from zope.security.checker import CheckerPublic, NamesChecker
 from zope.app.publisher.browser import metadirectives, resourcemeta
 
-import z3c.cssresource
+import z3c.zrtresource
 
 
 class ICSSResourceDirective(metadirectives.IBasicResourceInformation):
@@ -56,7 +56,7 @@
 
     checker = NamesChecker(resourcemeta.allowed_names, permission)
 
-    factory = z3c.cssresource.CSSFileResourceFactory(file, checker, name)
+    factory = z3c.zrtresource.CSSFileResourceFactory(file, checker, name)
 
     _context.action(
         discriminator = ('resource', name, browser.IBrowserRequest, layer),

Modified: z3c.cssresource/trunk/src/z3c/cssresource/zcml.txt
===================================================================
--- z3c.cssresource/trunk/src/z3c/cssresource/zcml.txt	2006-08-15 15:11:36 UTC (rev 69509)
+++ z3c.cssresource/trunk/src/z3c/cssresource/zcml.txt	2006-08-15 15:57:07 UTC (rev 69510)
@@ -1,5 +1,5 @@
 ==========================
-``css-resource`` Directive
+``zrt-resource`` Directive
 ==========================
 
 This package provides a new directive to use the special resource
@@ -8,7 +8,7 @@
   >>> from zope.configuration import xmlconfig
   >>> context = xmlconfig.string('''
   ... <configure i18n_domain="zope">
-  ...   <include package="z3c.cssresource" file="meta.zcml" />
+  ...   <include package="z3c.zrtresource" file="meta.zcml" />
   ... </configure>
   ... ''')
 
@@ -17,22 +17,16 @@
   >>> import tempfile
   >>> fn = tempfile.mktemp('.css')
   >>> open(fn, 'w').write('''\
-  ... /* zope-global-replace: "../img1" "++resource++/img" */
+  ... /* zrt-replace: "../img1" "++resource++/img" */
   ... h1 {
   ...   color: red;
   ...   background: url('../img1/mybackground.gif');
   ... }
-  ...
-  ... h2 {
-  ...   color: red;
-  ...   background: url('../img2/mybackground.gif');
-  ... }
-  ... /* zope-global-replace: "../img2" "++resource++/img" */
   ... ''')
 
   >>> context = xmlconfig.string('''
   ... <configure xmlns="http://namespaces.zope.org/browser" i18n_domain="zope">
-  ...   <css-resource
+  ...   <zrt-resource
   ...       name="test.css"
   ...       file="%s" />
   ... </configure>
@@ -53,9 +47,3 @@
     color: red;
     background: url('++resource++/img/mybackground.gif');
   }
-  <BLANKLINE>
-  h2 {
-    color: red;
-    background: url('++resource++/img/mybackground.gif');
-  }
-  <BLANKLINE>

Copied: z3c.cssresource/trunk/src/z3c/cssresource/zrtresource.py (from rev 69499, z3c.cssresource/trunk/src/z3c/cssresource/cssresource.py)
===================================================================
--- z3c.cssresource/trunk/src/z3c/cssresource/cssresource.py	2006-08-15 02:20:28 UTC (rev 69499)
+++ z3c.cssresource/trunk/src/z3c/cssresource/zrtresource.py	2006-08-15 15:57:07 UTC (rev 69510)
@@ -0,0 +1,46 @@
+##############################################################################
+#
+# Copyright (c) 2001, 2002 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""CSS Resource
+
+$Id$
+"""
+__docformat__='restructuredtext'
+from zope.app.component.hooks import getSite
+from zope.app.publisher.fileresource import File
+from zope.app.publisher.browser.fileresource import FileResource
+
+from z3c.zrtresource import processor, replace
+
+
+class CSSFileResource(FileResource):
+
+    def GET(self):
+        data = super(CSSFileResource, self).GET()
+        # Process the file
+        p = processor.ZRTProcessor(data, commands={'replace': replace.Replace})
+        return p.process(self.request, getSite())
+
+
+class CSSFileResourceFactory(object):
+
+    def __init__(self, path, checker, name):
+        self.__file = File(path, name)
+        self.__checker = checker
+        self.__name = name
+
+    def __call__(self, request):
+        resource = CSSFileResource(self.__file, request)
+        resource.__Security_checker__ = self.__checker
+        resource.__name__ = self.__name
+        return resource



More information about the Checkins mailing list