Completed
Pull Request — master (#35)
by Björn
37s
created

UIBridge.apply_updates()   F

Complexity

Conditions 10

Size

Total Lines 26

Duplication

Lines 0
Ratio 0 %

Importance

Changes 5
Bugs 0 Features 0
Metric Value
cc 10
c 5
b 0
f 0
dl 0
loc 26
rs 3.1304

How to fix   Complexity   

Complexity

Complex classes like UIBridge.apply_updates() often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
"""Bridge for connecting a UI instance to nvim."""
2
import sys
3
import os
4
from threading import Semaphore, Thread
5
from traceback import format_exc
6
from inspect import signature
7
8
9
class UIBridge(object):
10
11
    """UIBridge class. Connects a Nvim instance to a UI class."""
12
13
    def connect(self, nvim, ui, profile=None, notify=False):
14
        """Connect nvim and the ui.
15
16
        This will start loops for handling the UI and nvim events while
17
        also synchronizing both.
18
        """
19
        self._notify = notify
0 ignored issues
show
Coding Style introduced by
The attribute _notify was defined outside __init__.

It is generally a good practice to initialize all attributes to default values in the __init__ method:

class Foo:
    def __init__(self, x=None):
        self.x = x
Loading history...
20
        self._error = None
0 ignored issues
show
Coding Style introduced by
The attribute _error was defined outside __init__.

It is generally a good practice to initialize all attributes to default values in the __init__ method:

class Foo:
    def __init__(self, x=None):
        self.x = x
Loading history...
21
        self._nvim = nvim
0 ignored issues
show
Coding Style introduced by
The attribute _nvim was defined outside __init__.

It is generally a good practice to initialize all attributes to default values in the __init__ method:

class Foo:
    def __init__(self, x=None):
        self.x = x
Loading history...
22
        self._ui = ui
0 ignored issues
show
Coding Style introduced by
The attribute _ui was defined outside __init__.

It is generally a good practice to initialize all attributes to default values in the __init__ method:

class Foo:
    def __init__(self, x=None):
        self.x = x
Loading history...
23
        self._profile = profile
0 ignored issues
show
Coding Style introduced by
The attribute _profile was defined outside __init__.

It is generally a good practice to initialize all attributes to default values in the __init__ method:

class Foo:
    def __init__(self, x=None):
        self.x = x
Loading history...
24
        self._sem = Semaphore(0)
0 ignored issues
show
Coding Style introduced by
The attribute _sem was defined outside __init__.

It is generally a good practice to initialize all attributes to default values in the __init__ method:

class Foo:
    def __init__(self, x=None):
        self.x = x
Loading history...
25
        self.debug_events = len(os.environ.get("NVIM_PYTHON_UI_DEBUG", "")) > 0
0 ignored issues
show
Coding Style introduced by
The attribute debug_events was defined outside __init__.

It is generally a good practice to initialize all attributes to default values in the __init__ method:

class Foo:
    def __init__(self, x=None):
        self.x = x
Loading history...
26
        t = Thread(target=self._nvim_event_loop)
27
        t.daemon = True
28
        t.start()
29
        self._ui_event_loop()
30
        if self._error:
31
            print(self._error)
32
        if self._profile:
33
            print(self._profile)
34
35
    def exit(self):
36
        """Disconnect by exiting nvim."""
37
        self.detach()
38
        self._call(self._nvim.quit)
39
40
    def input(self, input_str):
41
        """Send input to nvim."""
42
        self._call(self._nvim.input, input_str)
43
44
    def resize(self, columns, rows):
45
        """Send a resize request to nvim."""
46
        self._call(self._nvim.ui_try_resize, columns, rows)
47
48
    def attach(self, columns, rows, **options):
49
        """Attach the UI to nvim."""
50
        self._call(self._nvim.api.ui_attach, columns, rows, options)
51
52
    def detach(self):
53
        """Detach the UI from nvim."""
54
        self._call(self._nvim.ui_detach)
55
56
    def _call(self, fn, *args):
57
        self._nvim.async_call(fn, *args)
58
59
    def _ui_event_loop(self):
60
        self._sem.acquire()
61
        if self._profile:
62
            import StringIO
0 ignored issues
show
Configuration introduced by
The import StringIO could not be resolved.

This can be caused by one of the following:

1. Missing Dependencies

This error could indicate a configuration issue of Pylint. Make sure that your libraries are available by adding the necessary commands.

# .scrutinizer.yml
before_commands:
    - sudo pip install abc # Python2
    - sudo pip3 install abc # Python3
Tip: We are currently not using virtualenv to run pylint, when installing your modules make sure to use the command for the correct version.

2. Missing __init__.py files

This error could also result from missing __init__.py files in your module folders. Make sure that you place one file in each sub-folder.

Loading history...
63
            import cProfile
64
            import pstats
65
            pr = cProfile.Profile()
66
            pr.enable()
67
        self._ui.start(self)
68
        if self._profile:
69
            pr.disable()
70
            s = StringIO.StringIO()
71
            ps = pstats.Stats(pr, stream=s)
72
            ps.strip_dirs().sort_stats(self._profile).print_stats(30)
73
            self._profile = s.getvalue()
0 ignored issues
show
Coding Style introduced by
The attribute _profile was defined outside __init__.

It is generally a good practice to initialize all attributes to default values in the __init__ method:

class Foo:
    def __init__(self, x=None):
        self.x = x
Loading history...
74
75
    def _nvim_event_loop(self):
76
        def on_setup():
77
            self._sem.release()
78
79
        def on_request(method, args):
0 ignored issues
show
Unused Code introduced by
The argument args seems to be unused.
Loading history...
Unused Code introduced by
The argument method seems to be unused.
Loading history...
80
            raise Exception('Not implemented')
81
82
        def on_notification(method, updates):
83
            def apply_updates():
84
                if self._notify:
85
                    sys.stdout.write('attached\n')
86
                    sys.stdout.flush()
87
                    self._notify = False
0 ignored issues
show
Coding Style introduced by
The attribute _notify was defined outside __init__.

It is generally a good practice to initialize all attributes to default values in the __init__ method:

class Foo:
    def __init__(self, x=None):
        self.x = x
Loading history...
88
                try:
89
                    for update in updates:
90
                        # import sys
91
                        # l = [','.join([str(a) for a in args])
92
                        #      for args in update[1:]]
93
                        # print >> sys.stderr, update[0], ' '.join(l)
94
                        try:
95
                            handler = getattr(self._ui, '_nvim_' + update[0])
96
                            nparam = len(signature(handler).parameters)
97
98
                        except AttributeError:
99
                            if self.debug_events:
100
                                print(repr(update),file=sys.stderr)
101
                        else:
102
                            if self.debug_events and len(update[1]) > nparam:
103
                                print(repr(update),file=sys.stderr)
104
                            for args in update[1:]:
105
                                handler(*args[:nparam])
106
                except:
0 ignored issues
show
Coding Style Best Practice introduced by
General except handlers without types should be used sparingly.

Typically, you would use general except handlers when you intend to specifically handle all types of errors, f.e. when logging. Otherwise, such general error handlers can mask errors in your application that you want to know of.

Loading history...
107
                    self._error = format_exc()
0 ignored issues
show
Coding Style introduced by
The attribute _error was defined outside __init__.

It is generally a good practice to initialize all attributes to default values in the __init__ method:

class Foo:
    def __init__(self, x=None):
        self.x = x
Loading history...
108
                    self._call(self._nvim.quit)
109
            if method == 'redraw':
110
                self._ui.schedule_screen_update(apply_updates)
111
112
        self._nvim.run_loop(on_request, on_notification, on_setup)
113
        self._ui.quit()
114