[Checkins] SVN: hurry.resource/trunk/src/hurry/resource/ Helper code for generating code for resources.

Martijn Faassen faassen at infrae.com
Wed Sep 24 12:50:16 EDT 2008


Log message for revision 91446:
  Helper code for generating code for resources.
  

Changed:
  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

-=-
Modified: hurry.resource/trunk/src/hurry/resource/README.txt
===================================================================
--- hurry.resource/trunk/src/hurry/resource/README.txt	2008-09-24 16:06:44 UTC (rev 91445)
+++ hurry.resource/trunk/src/hurry/resource/README.txt	2008-09-24 16:50:15 UTC (rev 91446)
@@ -452,6 +452,35 @@
   <script type="text/javascript" src="http://localhost/static/foo/a.js"></script>
   <script type="text/javascript" src="http://localhost/static/foo/c.js"></script>
 
+Generating resource code
+------------------------
+
+Sometimes it is useful to generate code that expresses a complex
+resource dependency structure. One example of that is in
+``hurry.yui``. We can use this to render a list of resources::
+
+  >>> from hurry.resource import generate_code
+  >>> print generate_code([a1, a2, a3, a4, a5])
+  from hurry.resource import Library, ResourceInclusion
+  <BLANKLINE>
+  foo = Library('foo')
+  <BLANKLINE>
+  a1 = ResourceInclusion(foo, 'a1.js')
+  a2 = ResourceInclusion(foo, 'a2.js', depends=[a1])
+  a3 = ResourceInclusion(foo, 'a3.js', depends=[a2])
+  a4 = ResourceInclusion(foo, 'a4.js', depends=[a1])
+  a5 = ResourceInclusion(foo, 'a5.js', depends=[a4, a3])
+
+Let's look at an example with modes and rollups::
+
+  >>> print generate_code([b4, b5])
+  from hurry.resource import Library, ResourceInclusion
+  <BLANKLINE>
+  foo = Library('foo')
+  <BLANKLINE>
+  b4 = ResourceInclusion(foo, 'b4.js', rollups=['giant.js'], debug=ResourceInclusion(foo, 'b4-debug.js', rollups=['giant-debug.js']))
+  b5 = ResourceInclusion(foo, 'b5.js', rollups=['giant.js'], debug=ResourceInclusion(foo, 'b5-debug.js', rollups=['giant-debug.js']))
+
 Sorting inclusions by dependency
 --------------------------------
 

Modified: hurry.resource/trunk/src/hurry/resource/__init__.py
===================================================================
--- hurry.resource/trunk/src/hurry/resource/__init__.py	2008-09-24 16:06:44 UTC (rev 91445)
+++ hurry.resource/trunk/src/hurry/resource/__init__.py	2008-09-24 16:50:15 UTC (rev 91446)
@@ -1,2 +1,3 @@
 from hurry.resource.core import (Library, ResourceInclusion, NeededInclusions,
-                                 sort_inclusions_topological)
+                                 sort_inclusions_topological,
+                                 generate_code)

Modified: hurry.resource/trunk/src/hurry/resource/core.py
===================================================================
--- hurry.resource/trunk/src/hurry/resource/core.py	2008-09-24 16:06:44 UTC (rev 91445)
+++ hurry.resource/trunk/src/hurry/resource/core.py	2008-09-24 16:50:15 UTC (rev 91446)
@@ -45,14 +45,14 @@
         self.library = library
         self.relpath = relpath
 
+        assert not isinstance(depends, basestring)
+        depends = depends or []
+        self.depends = normalize_inclusions(library, depends)
+    
         assert not isinstance(rollups, basestring)
         rollups = rollups or []
         self.rollups = normalize_inclusions(library, rollups)
 
-        assert not isinstance(depends, basestring)
-        depends = depends or []
-        self.depends = normalize_inclusions(library, depends)
-
         normalized_modes = {}
         for mode_name, inclusion in kw.items():
             normalized_modes[mode_name] = normalize_inclusion(
@@ -233,3 +233,91 @@
             "Unknown resource extension %s for resource inclusion: %s" %
             (inclusion.ext(), repr(inclusion)))
     return renderer(url)
+
+def generate_code(inclusions):
+    # libraries with the same name are the same libraries
+    libraries = {}
+    for inclusion in inclusions:
+        libraries[inclusion.library.name] = inclusion.library
+    libraries = sorted(libraries.values())
+
+    result = []
+    # import on top
+    result.append("from hurry.resource import Library, ResourceInclusion")
+    result.append("")
+    # define libraries
+    for library in libraries:
+        result.append("%s = Library('%s')" % (library.name, library.name))
+    result.append("")
+
+    # figure out inclusion names, try to base on filename 
+    used_names = set()
+    inclusion_to_name = {}
+    inclusions = sort_inclusions_by_extension(
+        sort_inclusions_topological(inclusions))
+    for inclusion in inclusions:
+        name = generate_inclusion_name(inclusion, used_names)
+        inclusion_to_name[inclusion.key()] = name
+
+    # now generate inclusion code
+    for inclusion in inclusions:
+        s = "%s = ResourceInclusion(%s, '%s'" % (
+            inclusion_to_name[inclusion.key()],
+            inclusion.library.name,
+            inclusion.relpath)
+        if inclusion.depends:
+            depends_s = ', depends=[%s]' % ', '.join(
+                [inclusion_to_name[d.key()] for d in inclusion.depends])
+            s += depends_s
+        if inclusion.rollups:
+            s += ', ' + _generate_inline_rollups(inclusion)
+        if inclusion.modes:
+            items = []
+            for mode_name, mode in inclusion.modes.items():
+                items.append((mode_name,
+                              generate_inline_inclusion(mode, inclusion)))
+            items = sorted(items)
+            modes_s = ', %s' % ', '.join(["%s=%s" % (name, mode) for
+                                          (name, mode) in items])
+            s += modes_s
+        s += ')'
+        result.append(s)
+    return '\n'.join(result)
+
+def generate_inline_inclusion(inclusion, associated_inclusion):
+    if (inclusion.library.name == associated_inclusion.library.name and
+        not inclusion.rollups):
+        return "'%s'" % inclusion.relpath
+    else:
+        s = "ResourceInclusion(%s, '%s'" % (inclusion.library.name,
+                                            inclusion.relpath)
+        if inclusion.rollups:
+            s += ', ' + _generate_inline_rollups(inclusion)
+        s += ')'
+        return s
+
+def _generate_inline_rollups(inclusion):
+    return 'rollups=[%s]' % ', '.join(
+        [generate_inline_inclusion(r, inclusion)
+         for r in inclusion.rollups])
+        
+def generate_inclusion_name(inclusion, used_names):
+    rest, fullname = os.path.split(inclusion.relpath)
+    name, ext = os.path.splitext(fullname)
+    if name not in used_names:
+        used_names.add(name)
+        return name
+    name = name + ext
+    name = name.replace('.', '_')
+    if name not in used_names:
+        used_names.add(name)
+        return name
+    i = 0
+    while True:
+        name = name + str(i)
+        if name not in used_names:
+            used_names.add(name)
+            return name
+    assert False, "Not possible to generate a unique name!"
+
+    



More information about the Checkins mailing list