[Checkins] SVN: hurry.resource/trunk/ * Implement top-level render functionality

Martijn Faassen faassen at startifact.com
Wed Dec 16 12:28:00 EST 2009


Log message for revision 106638:
  * Implement top-level render functionality
  
  * implement GroupInclusion that can be used to group other
    inclusions together.
  

Changed:
  U   hurry.resource/trunk/CHANGES.txt
  U   hurry.resource/trunk/src/hurry/resource/README.txt
  U   hurry.resource/trunk/src/hurry/resource/__init__.py
  U   hurry.resource/trunk/src/hurry/resource/core.py
  U   hurry.resource/trunk/src/hurry/resource/interfaces.py

-=-
Modified: hurry.resource/trunk/CHANGES.txt
===================================================================
--- hurry.resource/trunk/CHANGES.txt	2009-12-16 17:03:24 UTC (rev 106637)
+++ hurry.resource/trunk/CHANGES.txt	2009-12-16 17:28:00 UTC (rev 106638)
@@ -4,6 +4,19 @@
 0.4 (unreleased)
 ================
 
+* Expose a ``GroupInclusion`` that only exists to depend on other
+  inclusions. This way it becomes possible to expose a set of
+  different resources together without there being a central resource
+  that depends on them. The GroupInclusion itself is therefore not
+  rendered.
+
+* Create ``render_into_html`` and ``render_topbottom_into_html``
+  functionality, which insert the rendered inclusions into HTML.
+
+* Expose ``render``, ``render_into_html``, ``render_topbottom`` and
+  ``render_topbottom_into_html`` as top-level functions in
+  ``hurry.resource``.
+
 * Fix NameError when trying to render an inclusion with unknown extension.
 
 * Document inclusion renderers mechanism in the README.txt.

Modified: hurry.resource/trunk/src/hurry/resource/README.txt
===================================================================
--- hurry.resource/trunk/src/hurry/resource/README.txt	2009-12-16 17:03:24 UTC (rev 106637)
+++ hurry.resource/trunk/src/hurry/resource/README.txt	2009-12-16 17:28:00 UTC (rev 106638)
@@ -77,6 +77,32 @@
 
 As you can see, ``css`` resources are sorted before ``js`` resources.
 
+Grouping resources
+==================
+
+It is also possible to define a group that doesn't get rendered
+itself, but groups other resources together that should be rendered::
+
+  >>> from hurry.resource import GroupInclusion
+  >>> group = GroupInclusion([x1, x2])
+
+When we need a group, we'll get all inclusions referenced in it::
+
+  >>> needed = NeededInclusions()
+  >>> needed.need(group)
+  >>> group.inclusions()
+  [<ResourceInclusion 'a.js' in library 'foo'>, 
+   <ResourceInclusion 'b.css' in library 'foo'>]
+
+A group can also be depended on; it won't show up in the list of
+inclusions directly::
+
+  >>> more_stuff = ResourceInclusion(foo, 'more_stuff.js', depends=[group])
+  >>> more_stuff.inclusions()
+  [<ResourceInclusion 'a.js' in library 'foo'>, 
+   <ResourceInclusion 'b.css' in library 'foo'>,
+   <ResourceInclusion 'more_stuff.js' in library 'foo'>]
+
 A convenience spelling
 ======================
 
@@ -713,6 +739,52 @@
   <script type="text/javascript" src="http://localhost/static/foo/a.js"></script>
   <script type="text/javascript" src="http://localhost/static/foo/c.js"></script>
 
+Let's set this a currently needed inclusions::
+  
+  >>> request.needed = needed
+
+There is a function available as well for rendering the resources for
+the currently needed inclusion::
+
+  >>> from hurry import resource
+  >>> print resource.render()
+  <link rel="stylesheet" type="text/css" href="http://localhost/static/foo/b.css" />
+  <script type="text/javascript" src="http://localhost/static/foo/a.js"></script>
+  <script type="text/javascript" src="http://localhost/static/foo/c.js"></script>
+
+Inserting resources in HTML
+===========================
+
+When you have the HTML it can be convenient to have a way to insert
+resources directly into some HTML. 
+
+The insertion system assumes a HTML text that has a ``<head>`` tag in it::
+
+  >>> html = "<html><head>something more</head></html>"
+
+To insert the resources directly in HTML we can use ``render_into_html``
+on ``needed``::
+
+  >>> print needed.render_into_html(html)
+  <html><head>
+      <link rel="stylesheet" type="text/css" href="http://localhost/static/foo/b.css" />
+  <script type="text/javascript" src="http://localhost/static/foo/a.js"></script>
+  <script type="text/javascript" src="http://localhost/static/foo/c.js"></script>
+  something more</head></html>
+
+The top-level convenience function does this for the currently needed
+resources::
+
+  >>> print resource.render_into_html(html)
+  <html><head>
+      <link rel="stylesheet" type="text/css" href="http://localhost/static/foo/b.css" />
+  <script type="text/javascript" src="http://localhost/static/foo/a.js"></script>
+  <script type="text/javascript" src="http://localhost/static/foo/c.js"></script>
+  something more</head></html>
+
+See below for a way to insert into HTML when bottom fragments are
+involved.
+
 Top and bottom fragments
 ========================
 
@@ -797,6 +869,17 @@
   >>> print bottom
   <script type="text/javascript" src="http://localhost/static/foo/y2.js"></script>
 
+There's also a convenience function for the currently needed inclusion::
+
+  >>> request.needed = needed
+  >>> top, bottom = resource.render_topbottom()
+  >>> print top
+  <link rel="stylesheet" type="text/css" href="http://localhost/static/foo/b.css" />
+  <script type="text/javascript" src="http://localhost/static/foo/a.js"></script>
+  <script type="text/javascript" src="http://localhost/static/foo/c.js"></script>
+  >>> print bottom
+  <script type="text/javascript" src="http://localhost/static/foo/y2.js"></script>
+
 When we force bottom rendering of Javascript, there is no effect of
 making a resource bottom-safe: all ``.js`` resources will be rendered
 at the bottom anyway::
@@ -825,6 +908,35 @@
 included at the bottom of the page and still be able to depend on
 Javascript code that is.
 
+Inserting top and bottom resources in HTML
+==========================================
+
+You can also insert top and bottom fragments into HTML. This assumes a
+HTML text that has a ``<head>`` tag in it as well as a ``</body>``
+tag::
+
+  >>> html = "<html><head>rest of head</head><body>rest of body</body></html>"
+
+To insert the resources directly in HTML we can use
+``render_topbottom_into_html`` on ``needed``::
+
+  >>> print needed.render_topbottom_into_html(html)
+  <html><head>
+      <link rel="stylesheet" type="text/css" href="http://localhost/static/foo/b.css" />
+  rest of head</head><body>rest of body<script type="text/javascript" src="http://localhost/static/foo/a.js"></script>
+  <script type="text/javascript" src="http://localhost/static/foo/c.js"></script>
+  <script type="text/javascript" src="http://localhost/static/foo/y2.js"></script></body></html>
+
+There's also a function available to do this for the currently needed
+resources::
+
+  >>> print resource.render_topbottom_into_html(html)
+  <html><head>
+      <link rel="stylesheet" type="text/css" href="http://localhost/static/foo/b.css" />
+  rest of head</head><body>rest of body<script type="text/javascript" src="http://localhost/static/foo/a.js"></script>
+  <script type="text/javascript" src="http://localhost/static/foo/c.js"></script>
+  <script type="text/javascript" src="http://localhost/static/foo/y2.js"></script></body></html>
+
 bottom convenience
 ==================
 

Modified: hurry.resource/trunk/src/hurry/resource/__init__.py
===================================================================
--- hurry.resource/trunk/src/hurry/resource/__init__.py	2009-12-16 17:03:24 UTC (rev 106637)
+++ hurry.resource/trunk/src/hurry/resource/__init__.py	2009-12-16 17:28:00 UTC (rev 106638)
@@ -1,6 +1,11 @@
-from hurry.resource.core import (Library, ResourceInclusion, NeededInclusions)
+from hurry.resource.core import (Library,
+                                 ResourceInclusion,
+                                 GroupInclusion,
+                                 NeededInclusions)
 
-from hurry.resource.core import mode, bottom, rollup
+from hurry.resource.core import (mode, bottom, rollup,
+                                 render, render_topbottom, render_into_html,
+                                 render_topbottom_into_html)
 
 from hurry.resource.core import (sort_inclusions_topological,
                                  sort_inclusions_by_extension,

Modified: hurry.resource/trunk/src/hurry/resource/core.py
===================================================================
--- hurry.resource/trunk/src/hurry/resource/core.py	2009-12-16 17:03:24 UTC (rev 106637)
+++ hurry.resource/trunk/src/hurry/resource/core.py	2009-12-16 17:28:00 UTC (rev 106638)
@@ -122,12 +122,35 @@
         result.append(self)
         return result
 
+class GroupInclusion(object):
+    """An inclusion used to group resources together.
+
+    It doesn't define a resource itself.
+    """
+    implements(interfaces.IInclusion)
+
+    def __init__(self, depends):
+        self.depends = depends
+
+    def need(self):
+        needed = component.getUtility(
+            interfaces.ICurrentNeededInclusions)()
+        needed.need(self)
+
+    def inclusions(self):
+        """Get all inclusions needed by this inclusion.
+        """
+        result = []
+        for depend in self.depends:
+            result.extend(depend.inclusions())
+        return result
+
 def normalize_inclusions(library, inclusions):
     return [normalize_inclusion(library, inclusion)
             for inclusion in inclusions]
 
 def normalize_inclusion(library, inclusion):
-    if isinstance(inclusion, ResourceInclusion):
+    if interfaces.IInclusion.providedBy(inclusion):
         return inclusion
     assert isinstance(inclusion, basestring)
     return ResourceInclusion(library, inclusion)
@@ -180,7 +203,11 @@
 
     def render(self):
         return render_inclusions(self.inclusions())
-    
+
+    def render_into_html(self, html):
+        to_insert = self.render()
+        return html.replace('<head>', '<head>\n    %s\n' % to_insert, 1)
+        
     def render_topbottom(self):
         inclusions = self.inclusions()
 
@@ -208,6 +235,14 @@
         return (render_inclusions(top_inclusions, library_urls),
                 render_inclusions(bottom_inclusions, library_urls))
 
+    def render_topbottom_into_html(self, html):
+        top, bottom = self.render_topbottom()
+        if top:
+            html = html.replace('<head>', '<head>\n    %s\n' % top, 1)
+        if bottom:
+            html = html.replace('</body>', '%s</body>' % bottom, 1)
+        return html
+
 def mode(mode):
     """Set the mode for the currently needed resources.
     """
@@ -227,11 +262,31 @@
         interfaces.ICurrentNeededInclusions)()
     needed.rollup(disable)
 
+def render():
+    needed = component.getUtility(
+        interfaces.ICurrentNeededInclusions)()
+    return needed.render()
+
+def render_into_html(html):
+    needed = component.getUtility(
+        interfaces.ICurrentNeededInclusions)()
+    return needed.render_into_html(html)
+
+def render_topbottom():
+    needed = component.getUtility(
+        interfaces.ICurrentNeededInclusions)()
+    return needed.render_topbottom()
+
+def render_topbottom_into_html(html):
+    needed = component.getUtility(
+        interfaces.ICurrentNeededInclusions)()
+    return needed.render_topbottom_into_html(html)
+
 def apply_mode(inclusions, mode):
     return [inclusion.mode(mode) for inclusion in inclusions]
 
 def remove_duplicates(inclusions):
-    """Given a set of inclusions, consolidate them so each nly occurs once.
+    """Given a set of inclusions, consolidate them so each only occurs once.
     """
     seen = set()
     result = []

Modified: hurry.resource/trunk/src/hurry/resource/interfaces.py
===================================================================
--- hurry.resource/trunk/src/hurry/resource/interfaces.py	2009-12-16 17:03:24 UTC (rev 106637)
+++ hurry.resource/trunk/src/hurry/resource/interfaces.py	2009-12-16 17:28:00 UTC (rev 106638)
@@ -9,7 +9,25 @@
     """
     name = Attribute("The unique name of the library")
 
-class IResourceInclusion(Interface):
+class IInclusion(Interface):
+    """Base to all inclusions.
+    """
+    depends = Attribute("A list of inclusions that this "
+                        "resource depends on")
+    
+    def need():
+        """Express need directly for the current INeededInclusions.
+
+        This is a convenience method to help express inclusions more
+        easily, just do myinclusion.need() to have it be included in
+        the HTML that is currently being rendered.
+        """
+
+    def inclusions():
+        """Get all inclusions needed by this inclusion.
+        """
+
+class IResourceInclusion(IInclusion):
     """Resource inclusion
 
     A resource inclusion specifies how to include a single resource in a
@@ -18,8 +36,6 @@
     library = Attribute("The resource library this resource is in")
     relpath = Attribute("The relative path of the resource "
                         "within the resource library")
-    depends = Attribute("A list of ResourceInclusions that this "
-                        "resource depends on")
     rollups = Attribute("A list of potential rollup ResourceInclusions "
                         "that this resource is part of")
     bottom = Attribute("A flag. When set to True, this resource "
@@ -45,23 +61,11 @@
         If we cannot find a particular mode for a resource, the
         original resource inclusion is returned.
         """
-        
+
     def key():
         """Returns a unique, hashable identifier for the resource inclusion.
         """
 
-    def need():
-        """Express need directly for the current INeededInclusions.
-
-        This is a convenience method to help express inclusions more
-        easily, just do myinclusion.need() to have it be included in
-        the HTML that is currently being rendered.
-        """
-
-    def inclusions():
-        """Get all inclusions needed by this inclusion, including itself.
-        """
-
 class INeededInclusions(Interface):
     """A collection of inclusions that are needed for page display.
     """
@@ -136,7 +140,17 @@
         ``force_bottom`` settings are ignored; everything is always
         rendered on top.
         """
-        
+
+    def render_into_html(html):
+        """Render all resource inclusions into HTML.
+
+        The HTML supplied needs to a <head> tag available. The
+        inclusions HTML snippet will be rendered just after this.
+
+        ``force_bottom`` settings are ignored; everything is always
+        rendered on top.
+        """
+
     def render_topbottom():
         """Render all resource inclusions into top and bottom snippet.
 
@@ -162,7 +176,17 @@
         
         Returns top and bottom HTML fragments.
         """
-        
+
+    def render_topbottom_into_html(html):
+        """Render all resource inclusions into HTML (top and bottom).
+
+        The HTML supplied needs to a <head> tag available. The
+        top inclusions HTML snippet will be rendered just after this.
+
+        The HTML supplied also needs to have a </body> tag available.
+        bottom inclusions HTML snippet will be rendered just before this.
+        """
+
 class ICurrentNeededInclusions(Interface):
     def __call__():
         """Return the current needed inclusions object.



More information about the checkins mailing list