[PEAK] interpreting CircularityError

Phillip J. Eby pje at telecommunity.com
Tue Oct 21 20:39:04 EDT 2008


At 02:16 AM 10/22/2008 +0300, Sergey Schetinin wrote:
>If I understand correctly, when CircularityError is raised it's
>supposed that routes parameter describes the circularity in question.
>It's a dict that maps cells that need to run to sets of dependent
>cells. So the circularity means there should be a cycle in there, i.e.
>no possible order to calculate the tree running each cell rule no more
>than once. I can't see it this error I get:
>
>{LazyCell(<bound method AutoSize.y of AutoSize(376, 178)>, 178):
>     set([LazyCell(<function <lambda> at 0x01C162B0>, 158)]),
>  LazyCell(<function <lambda> at 0x01C162B0>, 158):
>     set([LazyCell(<bound method OffsetPoint.y of OffsetPoint(384, 
> 194)>, 194)]),
>  LazyCell(<bound method OffsetPoint.y of OffsetPoint(384, 194)>, 194):
>     set([Cell(<bound method OptionalPanel.track_rect of
><gui5.models.OptionalPanel object at 0x00E00830>>, None),
>         LazyCell(<bound method AutoSize.y of AutoSize(376, 20)>, 20)]),
>  LazyCell(<bound method AutoSize.y of AutoSize(376, 20)>, 20):
>     set([Cell(<bound method OptionalPanel.track_rect of
><gui5.models.OptionalPanel object at 0x00E00830>>, None)])}
>
>
>This happens in response to resizing the window and it only happens
>once, after first 1px change, after that everything works as intended
>and without a glitch, which suggests it's a fluke of finding the
>proper order for running the rules. I'll also try to create a smaller
>test to reproduce it, so for now I'm just seeking assistance with
>.routes interpretation.

Hm.  It appears it's possible for the cycle detection to be 
over-enthusiastic.  It declares a cycle if any retried rule triggers 
the recalc of any other retried rule.  It does not actually verify 
that the rule triggers *itself*.

So, the raising of a circularity error should be replaced with a 
check for an actual cycle, probably by calling a check_circularity 
function, e.g.:

     def check_circularity(item, routes, start=None, seen=None):
         if seen is None: seen = {}
         if start is None: start = item
         for via in routes.get(item, ()):
             if via is start:
                 raise CircularityError(routes, start)
             elif via not in seen:
                 seen[via] = 1
                 check_circularity(via, routes, start, seen)




More information about the PEAK mailing list