[PEAK] Re: Trellis: Sensor.listening and iter_listeners()

Sergey Schetinin maluke at gmail.com
Wed Nov 12 14:00:28 EST 2008


I just realized that instead of going out of my way to create managers
for sensors it would make more sense to just add __enter__ / __exit__
method to the sensor itself. Anyway, I wonder if the managers have to
be used or the initialization undo-logging behavior can be changed to
work for this case reliably, because just removing the if undo should
be wrong (my tests pass though).

On Wed, Nov 12, 2008 at 20:33, Sergey Schetinin <maluke at gmail.com> wrote:
> The problem is caused by initialization not being undo-logged, so when
> the rule is initialized, its _process_reads sets .next_listener of
> some Sensor, but the Link creation is not undo-logged. Later, it all
> gets rolled back, and the schedule(self.update_connection) vanishes
> from the ctrl.commit, but the .next_listener is not rolled back, so
> next time the dependency is recreated was_seen is True and the
> _set_listener decides there's no need to schedule update_connection,
> so it never runs. Removing one "if undo" condition in final part of
> the _process_reads fixes the problem. Trellis test suite never passes
> for me (hangs up on "testSequentialCalls
> (test_trellis.TestReactorEventLoop) ..."), so I'm not sure if this
> breaks anything else.
>
> Initialization is once again a culprit of a hard to detect bug. =)
>
>
>
> On Wed, Nov 12, 2008 at 20:16, Sergey Schetinin <maluke at gmail.com> wrote:
>> Switching to a manager instead of scheduling update_connection
>> pseudo-rule fixed the issue.
>>
>> from peak.util.addons import AddOn
>>
>> class UpdateConnection(AddOn):
>>    def __init__(self, sensor):
>>        self.sensor = sensor
>>
>>    def __enter__(self):
>>        pass
>>
>>    def update_connection(self):
>>        sensor = self.sensor
>>        descr = type(sensor).listening
>>        listening = descr.__get__(sensor)
>>        if sensor.next_listener is not None:
>>            if listening is NOT_GIVEN:
>>                descr.__set__(sensor, sensor.connector.connect(self))
>>        elif listening is not NOT_GIVEN:
>>            sensor.connector.disconnect(sensor, listening)
>>            descr.__set__(sensor, NOT_GIVEN)
>>
>>    def __exit__(self, *args):
>>        self.update_connection()
>>        self.delete_from(self.sensor)
>>
>>
>> then manage(UpdateManager(self)) or
>>
>> from contextlib import contextmanager
>>
>>    @property
>>    def upd_manager(self):
>>        if not self._upd_manager:
>>            self._upd_manager = self.make_upd_manager()
>>        return self._upd_manager
>>
>>    @contextmanager
>>    def make_upd_manager(self):
>>        yield
>>        descr = type(self).listening
>>        listening = descr.__get__(self)
>>        if self.next_listener is not None:
>>            if listening is NOT_GIVEN:
>>                descr.__set__(self, self.connector.connect(self))
>>        elif listening is not NOT_GIVEN:
>>            self.connector.disconnect(self, listening)
>>            descr.__set__(self, NOT_GIVEN)
>>        if not isinstance(self, ConstantMixin):
>>            self._upd_manager = None
>>
>> then manage(self.upd_manager).
>>
>>
>>
>>
>>
>> On Wed, Nov 12, 2008 at 19:24, Sergey Schetinin <maluke at gmail.com> wrote:
>>> After adding `if self.update_connection not in pending:
>>> on_undo(pending.remove, self.update_connection)` in relevant places,
>>> the printed counts show that all of them get called, so this has to be
>>> something else.
>>>
>>>
>>> On Wed, Nov 12, 2008 at 18:25, Sergey Schetinin <maluke at gmail.com> wrote:
>>>> I forgot to mention that the same debug prints were added to
>>>> LazyCell.run right after scheduling of update_connection.
>>>>
>>>> On Wed, Nov 12, 2008 at 18:19, Sergey Schetinin <maluke at gmail.com> wrote:
>>>>> I tracked this down to the fact that not all scheduled
>>>>> update_connection get called.
>>>>>
>>>>> In attempt to find out how often does this happen I added the
>>>>> following to SensorBase._set_listener (`pending` refers to a global
>>>>> set())
>>>>>
>>>>>            print len(pending), '++'
>>>>>            pending.add(self)
>>>>>
>>>>>  and in update_connection
>>>>>
>>>>>            print len(pending), '--'
>>>>>            pending.remove(self)
>>>>>
>>>>> And the printed counts don't go back to 1 even for tests that seem to
>>>>> work correctly. Am I missing something?
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> On Wed, Nov 12, 2008 at 16:18, Sergey Schetinin <maluke at gmail.com> wrote:
>>>>>> I tracked one of the issues I was having periodically to a case when a
>>>>>> sensor did not connect when it should have.
>>>>>>
>>>>>>>>> evt_cell
>>>>>> Sensor(<bound method PyEventBinder._events of <wx._core.PyEventBinder
>>>>>> object at 0x00E5DD10>>, None, discrete[None])
>>>>>>>>> evt_cell.listening
>>>>>> NOT_GIVEN
>>>>>>>>> list(evt_cell.iter_listeners())
>>>>>> [WxCell(221), WxCell(392)]
>>>>>>
>>>>>> This state is invalid, correct?
>>>>>>
>>>>>>
>>>>>> --
>>>>>> Best Regards,
>>>>>> Sergey Schetinin
>>>>>>
>>>>>> http://s3bk.com/ -- S3 Backup
>>>>>> http://word-to-html.com/ -- Word to HTML Converter
>>>>>>
>>>>>
>>>>>
>>>>>
>>>>> --
>>>>> Best Regards,
>>>>> Sergey Schetinin
>>>>>
>>>>> http://s3bk.com/ -- S3 Backup
>>>>> http://word-to-html.com/ -- Word to HTML Converter
>>>>>
>>>>
>>>>
>>>>
>>>> --
>>>> Best Regards,
>>>> Sergey Schetinin
>>>>
>>>> http://s3bk.com/ -- S3 Backup
>>>> http://word-to-html.com/ -- Word to HTML Converter
>>>>
>>>
>>>
>>>
>>> --
>>> Best Regards,
>>> Sergey Schetinin
>>>
>>> http://s3bk.com/ -- S3 Backup
>>> http://word-to-html.com/ -- Word to HTML Converter
>>>
>>
>>
>>
>> --
>> Best Regards,
>> Sergey Schetinin
>>
>> http://s3bk.com/ -- S3 Backup
>> http://word-to-html.com/ -- Word to HTML Converter
>>
>
>
>
> --
> Best Regards,
> Sergey Schetinin
>
> http://s3bk.com/ -- S3 Backup
> http://word-to-html.com/ -- Word to HTML Converter
>



-- 
Best Regards,
Sergey Schetinin

http://s3bk.com/ -- S3 Backup
http://word-to-html.com/ -- Word to HTML Converter



More information about the PEAK mailing list