Coding Phase 3 - Part 1

GSoC 2019 with coala

Posted by Akshat on August 8, 2019

So I successfully completed Phase 2 of GSoC. It has not been a smooth ride, mainly because one of my mentor backed out of the project and one has not been active in forever. So I have not been getting many reviews on my work.

Anyways, I had completed most of my work in the first two phases, or so I thought. But I ran into a problem while work on a custom action for DuplicateFileBear. The action is DeleteFileAction, on applying it deletes a file. But that is not the problem, the problem arised when two instances of DeleteFileAction were passed by the bear. It was giving unexpected results, and the problem turned out that coala forms and action_dict, a dictionary with key as the name of the class of action object and value as the action object. Naturally key should be unique, and so the problem arised. I did face an similar problem in Phase 2, when more that one instances of AlternatePatchAction was added to the list of actions. That time I had added a custom get_metadata function to AlternatePatchAction class, but now this was not feasible. I needed a generic solution, first thought that came to my mind was to use a key which was unique to an object. After discussing with @abhishalya and @Makman2, I decided to change the key of action_dict to id of action object.

I spent most of my time doing this and fixing tests that were broken because of this. One of the change that was made was to remove staticmethod from get_metadata function. This led to some other changes in Processing module and one the tests in Processing module was breaking. I faced this issue in Phase 1 as well, but I could figure out the cause for this, so @abhishalya suggested a workaround for this. It worked that time, but now those changes had to be made, and I still couldn’t figure out why the test was failing.

To provide some context the test which was failing was this.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
    def test_without_default_action_and_unapplicable(self):
        # Use a result where no default action is supplied for and another one
        # where the action is not applicable.
        old_is_applicable = ApplyPatchAction.is_applicable
        ApplyPatchAction.is_applicable = staticmethod(
            lambda *args: 'The ApplyPatchAction cannot be applied'
        )

        self.section.append(Setting(
            'default_actions',
            'NoBear: ApplyPatchAction, YBear: ApplyPatchAction'))
        with LogCapture() as capture:
            ret = autoapply_actions(self.results,
                                    {},
                                    {},
                                    self.section,
                                    self.log_printer)
        self.assertEqual(ret, self.results)
        capture.check(
            ('root', 'WARNING', 'YBear: The ApplyPatchAction cannot be applied')
        )

        ApplyPatchAction.is_applicable = old_is_applicable

        self.section.append(Setting(
            'no_autoapply_warn', True))
        with LogCapture() as capture:
            autoapply_actions(self.results,
                              {},
                              {},
                              self.section,
                              self.log_printer)
        capture.check()

(Wow, the colour scheme sucks) And the solution was adding one word:

1
ApplyPatchAction.is_applicable = staticmethod(old_is_applicable)

You wouldn’t believe how many hours I wasted debugging this, and the cause turned out to be so silly. I knew that is_applicable was a staticmethod but never realised that reference to it, old_is_applicable was not.

Now there is only one and half week till Phase 3 evalutions start and I plan to finish all my work is this week itself. This will give me some time to get reviews on my PR and hopefully get them merged.