← Back to team overview

divmod-dev team mailing list archive

[Merge] lp:~lvh/divmod.org/storeless-conform-1118498 into lp:divmod.org

 

Laurens Van Houtven has proposed merging lp:~lvh/divmod.org/storeless-conform-1118498 into lp:divmod.org.

Requested reviews:
  Divmod-dev (divmod-dev)
Related bugs:
  Bug #1118498 in Divmod: "__conform__ should not require a store"
  https://bugs.launchpad.net/divmod.org/+bug/1118498

For more details, see:
https://code.launchpad.net/~lvh/divmod.org/storeless-conform-1118498/+merge/148490

Adds a test case for __conform__ for unstored objects, and changes the implementation to pass that test.

This means that unstored objects with in-memory powerups can be adapted to their interfaces. Previously, in-memory powerups were useless for unstored objects.
-- 
https://code.launchpad.net/~lvh/divmod.org/storeless-conform-1118498/+merge/148490
Your team Divmod-dev is requested to review the proposed merge of lp:~lvh/divmod.org/storeless-conform-1118498 into lp:divmod.org.
=== modified file 'Axiom/axiom/item.py'
--- Axiom/axiom/item.py	2010-04-03 22:36:04 +0000
+++ Axiom/axiom/item.py	2013-02-14 16:09:23 +0000
@@ -193,10 +193,10 @@
         return value is the powerup.  These are used only by the callable
         interface adaption API, not C{powerupsFor}.
     """
-
     aggregateInterfaces = {
         IService: serviceSpecialCase,
-        IServiceCollection: serviceSpecialCase}
+        IServiceCollection: serviceSpecialCase
+    }
 
     def inMemoryPowerUp(self, powerup, interface):
         """
@@ -314,19 +314,22 @@
         special rules.  The full list of such interfaces is present in the
         'aggregateInterfaces' class attribute.
         """
-        if (self.store is None  # Don't bother doing a *query* if we're not
-                                # even stored in a store yet
-            or interface is IPowerupIndirector): # you can't do a query for
-                                                 # IPowerupIndirector, that
-                                                 # would just start an infinite
-                                                 # loop.
-            return
-        pups = self.powerupsFor(interface)
-        agg = self.aggregateInterfaces
-        if interface in agg:
-            return agg[interface](self, pups)
-        for p in pups:
-            return p
+        if interface is IPowerupIndirector:
+            # This would cause an infinite loop, since powerupsFor will try to
+            # adapt every popwerup to IPowerupIndirector, calling this method.
+            return
+
+        try:
+            pups = self.powerupsFor(interface)
+        except AttributeError:  # self.store is None -> self.store.query...
+            return
+
+        aggregator = self.aggregateInterfaces.get(interface, None)
+        if aggregator is not None:
+            return aggregator(self, pups)
+
+        for pup in pups:
+            return pup  # return first one, or None if no powerups
 
 
     def powerupsFor(self, interface):

=== modified file 'Axiom/axiom/test/test_powerup.py'
--- Axiom/axiom/test/test_powerup.py	2008-10-09 13:17:41 +0000
+++ Axiom/axiom/test/test_powerup.py	2013-02-14 16:09:23 +0000
@@ -289,14 +289,19 @@
     """
     Tests for the behavior of powerups which are not database-resident.
     """
+    def _createEmpowered(self, withStore=True):
+        powerup = object()
+        item = SumContributor(store=Store() if withStore else None)
+        item.inMemoryPowerUp(powerup, ISumProducer)
+        return powerup, item
+
+
     def test_powerupsFor(self):
         """
         L{Item.powerupsFor} returns a list the first element of which is the
         object previously passed to L{Item.inMemoryPowerUp}.
         """
-        powerup = object()
-        item = SumContributor(store=Store())
-        item.inMemoryPowerUp(powerup, ISumProducer)
+        powerup, item = self._createEmpowered()
         self.assertEqual(list(item.powerupsFor(ISumProducer)), [powerup])
 
 
@@ -306,8 +311,15 @@
         that item for that interface even if there are database-resident
         powerups on that item for that interface.
         """
-        powerup = object()
-        item = SumContributor(store=Store())
-        item.inMemoryPowerUp(powerup, ISumProducer)
+        powerup, item = self._createEmpowered()
         item.powerUp(item, ISumProducer)
         self.assertIdentical(ISumProducer(item), powerup)
+
+
+    def test_conformWithoutStore(self):
+        """
+        Adaptation (through L{Item.__conform__}) should be allowed even if the
+        object is not stored, as long as it has an in-memory powerup.
+        """
+        powerup, item = self._createEmpowered(withStore=False)
+        self.assertIdentical(ISumProducer(item), powerup)


Follow ups