Commits

nilo  committed 058ba8b

Slots can now specify a default resource to fill in if no resource is given in need().
It is a bit tricky, because if a slot has a default, required can't be set to False, because
it will be filled in any case.

  • Participants
  • Parent commits 16e05e4

Comments (0)

Files changed (2)

File fanstatic/core.py

         needed.need(self, slots)
 
 
+REQUIRED_DEFAULT_MARKER = object()
+
+
 # XXX have to lie here: a slot itself is not directly renderable,
 # that's a FilledSlot.
 class Slot(Renderable, Dependable):
       the same dependencies as that of the slot, or a strict subset.
     """
 
-    def __init__(self, library, extension, depends=None, required=True):
+    def __init__(self, library, extension, depends=None,
+                 required=REQUIRED_DEFAULT_MARKER,
+                 default=None):
+        #We need to detect if required was set to true explicitly.
+        if required is True and default is not None:
+            raise ValueError('A slot with a default is not required and can '
+                             'not be made required.')
+        if required is REQUIRED_DEFAULT_MARKER:
+            required = True
+        self.default = default
         self.library = library
         assert extension.startswith('.')
         self.ext = extension
                 continue
             fill_resource = self._slots.get(resource)
             if fill_resource is None:
-                if not resource.required:
+                if resource.default is not None:
+                    fill_resource = resource.default
+                elif not resource.required:
                     continue
-                raise SlotError("slot %r was required but not filled in" %
+                else:
+                    raise SlotError("slot %r was required but not filled in" %
                                 resource)
             result.add(FilledSlot(resource, fill_resource))
         return result

File tests/test_slot.py

 from fanstatic import NeededResources, Library, Resource, Slot, SlotError
 
 
-def test_fill_slot():
-    needed = NeededResources()
+@pytest.fixture(scope='function')
+def needed():
+    return NeededResources()
 
-    lib = Library('lib', '')
 
+@pytest.fixture(scope='function')
+def lib():
+    return Library('lib', '')
+
+
+def test_fill_slot(needed, lib):
     slot = Slot(lib, '.js')
     a = Resource(lib, 'a.js', depends=[slot])
 
     assert resources[0].relpath is b.relpath
 
 
-def test_dont_fill_required_slot():
-    needed = NeededResources()
-
-    lib = Library('lib', '')
-
+def test_dont_fill_required_slot(needed, lib):
     slot = Slot(lib, '.js')
     a = Resource(lib, 'a.js', depends=[slot])
 
         needed.resources()
 
 
-def test_no_need_to_fill_in_not_required():
-    needed = NeededResources()
-
-    lib = Library('lib', '')
+def test_no_need_to_fill_in_not_required(needed, lib):
 
     slot = Slot(lib, '.js', required=False)
     a = Resource(lib, 'a.js', depends=[slot])
     assert needed.resources() == [a]
 
 
-def test_fill_slot_wrong_extension():
-    needed = NeededResources()
+def test_slot_with_default_uses_default_if_nothing_given_in_need(needed, lib):
+    default_resource_for_slot = Resource(lib, 'b.js')
+    slot = Slot(lib, '.js', default=default_resource_for_slot)
+    a = Resource(lib, 'a.js', depends=[slot])
+    needed.need(a)
+    relpaths = [r.relpath for r in needed.resources()]
+    assert relpaths == ['b.js', 'a.js']
 
-    lib = Library('lib', '')
+
+def test_default_can_be_overridden(needed, lib):
+    default_resource_for_slot = Resource(lib, 'b.js')
+    slot = Slot(lib, '.js', default=default_resource_for_slot)
+    a = Resource(lib, 'a.js', depends=[slot])
+    custom_resource_for_slot = Resource(lib, 'c.js')
+    needed.need(a, {slot: custom_resource_for_slot})
+    relpaths = [r.relpath for r in needed.resources()]
+    assert relpaths == ['c.js', 'a.js']
+
+
+def test_slot_with_default_can_not_set_required_explicitly(lib):
+    a = Resource(lib, 'a.js')
+    with pytest.raises(ValueError):
+        slot = Slot(lib, '.js', default=a, required=True)
+
+
+def test_fill_slot_wrong_extension(needed, lib):
 
     slot = Slot(lib, '.js')
     a = Resource(lib, 'a.js', depends=[slot])
         needed.resources()
 
 
-def test_fill_slot_wrong_dependencies():
-    needed = NeededResources()
-
-    lib = Library('lib', '')
+def test_fill_slot_wrong_dependencies(needed, lib):
 
     slot = Slot(lib, '.js')
     a = Resource(lib, 'a.js', depends=[slot])
         needed.resources()
 
 
-def test_render_filled_slots():
-    needed = NeededResources()
-
-    lib = Library('lib', '')
-
+def test_render_filled_slots(needed, lib):
     slot = Slot(lib, '.js')
     a = Resource(lib, 'a.js', depends=[slot])
 
 <script type="text/javascript" src="/fanstatic/lib/a.js"></script>'''
 
 
-def test_slot_depends():
-
-    needed = NeededResources()
-
-    lib = Library('lib', '')
-
+def test_slot_depends(needed, lib):
     c = Resource(lib, 'c.js')
     slot = Slot(lib, '.js', depends=[c])
     a = Resource(lib, 'a.js', depends=[slot])
 <script type="text/javascript" src="/fanstatic/lib/a.js"></script>'''
 
 
-def test_slot_depends_subset():
-    needed = NeededResources()
-
-    lib = Library('lib', '')
+def test_slot_depends_subset(needed, lib):
 
     c = Resource(lib, 'c.js')
     slot = Slot(lib, '.js', depends=[c])
 <script type="text/javascript" src="/fanstatic/lib/a.js"></script>'''
 
 
-def test_slot_depends_incorrect():
-    needed = NeededResources()
-
-    lib = Library('lib', '')
-
+def test_slot_depends_incorrect(needed, lib):
     c = Resource(lib, 'c.js')
     slot = Slot(lib, '.js', depends=[c])
     a = Resource(lib, 'a.js', depends=[slot])
         needed.render()
 
 
-def test_slot_minified():
+def test_slot_minified(lib):
     needed = NeededResources(minified=True)
-
-    lib = Library('lib', '')
-
     slot = Slot(lib, '.js')
     a = Resource(lib, 'a.js', depends=[slot])
 
 <script type="text/javascript" src="/fanstatic/lib/a.js"></script>'''
 
 
-def test_resource_need_should_pass_slots_to_needed():
+def test_resource_need_should_pass_slots_to_needed(lib):
     import fanstatic
-    lib = Library('lib', '')
     c = Resource(lib, 'c.js')
     slot = Slot(lib, '.js', depends=[c])
     a = Resource(lib, 'a.js', depends=[slot])
     assert slot in needed._slots
 
 
-def test_group_need_should_pass_slots_to_needed():
+def test_group_need_should_pass_slots_to_needed(lib):
     import fanstatic
-    lib = Library('lib', '')
     c = Resource(lib, 'c.js')
     slot = Slot(lib, '.js', depends=[c])
     a = Resource(lib, 'a.js', depends=[slot])