Test Failed
Push — master ( a5ee34...588b1f )
by Justin M.
34s queued 10s
created

pynvim.plugin.decorators.command()   C

Complexity

Conditions 11

Size

Total Lines 44
Code Lines 32

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 20
CRAP Score 13.1095

Importance

Changes 0
Metric Value
cc 11
eloc 32
nop 10
dl 0
loc 44
rs 5.4
c 0
b 0
f 0
ccs 20
cts 27
cp 0.7407
crap 13.1095

How to fix   Complexity    Many Parameters   

Complexity

Complex classes like pynvim.plugin.decorators.command() 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.

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
"""Decorators used by python host plugin system."""
2
3 6
import inspect
4 6
import logging
5
6 6
from ..compat import IS_PYTHON3, unicode_errors_default
7
8 6
logger = logging.getLogger(__name__)
9 6
debug, info, warn = (logger.debug, logger.info, logger.warning,)
10 6
__all__ = ('plugin', 'rpc_export', 'command', 'autocmd', 'function',
11
           'encoding', 'decode', 'shutdown_hook')
12
13
14 6
def plugin(cls):
15
    """Tag a class as a plugin.
16
17
    This decorator is required to make the class methods discoverable by the
18
    plugin_load method of the host.
19
    """
20 6
    cls._nvim_plugin = True
21
    # the _nvim_bind attribute is set to True by default, meaning that
22
    # decorated functions have a bound Nvim instance as first argument.
23
    # For methods in a plugin-decorated class this is not required, because
24
    # the class initializer will already receive the nvim object.
25 6
    predicate = lambda fn: hasattr(fn, '_nvim_bind')
26 6
    for _, fn in inspect.getmembers(cls, predicate):
27 6
        if IS_PYTHON3:
28 4
            fn._nvim_bind = False
29
        else:
30 2
            fn.im_func._nvim_bind = False
31 6
    return cls
32
33
34 6
def rpc_export(rpc_method_name, sync=False):
35
    """Export a function or plugin method as a msgpack-rpc request handler."""
36 6
    def dec(f):
37 6
        f._nvim_rpc_method_name = rpc_method_name
38 6
        f._nvim_rpc_sync = sync
39 6
        f._nvim_bind = True
40 6
        f._nvim_prefix_plugin_path = False
41 6
        return f
42 6
    return dec
43
44
45 6
def command(name, nargs=0, complete=None, range=None, count=None, bang=False,
46
            register=False, sync=False, allow_nested=False, eval=None):
47
    """Tag a function or plugin method as a Nvim command handler."""
48 6
    def dec(f):
49 6
        f._nvim_rpc_method_name = 'command:{}'.format(name)
50 6
        f._nvim_rpc_sync = sync
51 6
        f._nvim_bind = True
52 6
        f._nvim_prefix_plugin_path = True
53
54 6
        opts = {}
55
56 6
        if range is not None:
57
            opts['range'] = '' if range is True else str(range)
58 6
        elif count is not None:
59 6
            opts['count'] = count
60
61 6
        if bang:
62
            opts['bang'] = ''
63
64 6
        if register:
65
            opts['register'] = ''
66
67 6
        if nargs:
68
            opts['nargs'] = nargs
69
70 6
        if complete:
71
            opts['complete'] = complete
72
73 6
        if eval:
74
            opts['eval'] = eval
75
76 6
        if not sync and allow_nested:
77
            rpc_sync = "urgent"
78
        else:
79 6
            rpc_sync = sync
80
81 6
        f._nvim_rpc_spec = {
82
            'type': 'command',
83
            'name': name,
84
            'sync': rpc_sync,
85
            'opts': opts
86
        }
87 6
        return f
88 6
    return dec
89
90
91 6 View Code Duplication
def autocmd(name, pattern='*', sync=False, allow_nested=False, eval=None):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
92
    """Tag a function or plugin method as a Nvim autocommand handler."""
93
    def dec(f):
94
        f._nvim_rpc_method_name = 'autocmd:{}:{}'.format(name, pattern)
95
        f._nvim_rpc_sync = sync
96
        f._nvim_bind = True
97
        f._nvim_prefix_plugin_path = True
98
99
        opts = {
100
            'pattern': pattern
101
        }
102
103
        if eval:
104
            opts['eval'] = eval
105
106
        if not sync and allow_nested:
107
            rpc_sync = "urgent"
108
        else:
109
            rpc_sync = sync
110
111
        f._nvim_rpc_spec = {
112
            'type': 'autocmd',
113
            'name': name,
114
            'sync': rpc_sync,
115
            'opts': opts
116
        }
117
        return f
118
    return dec
119
120
121 6 View Code Duplication
def function(name, range=False, sync=False, allow_nested=False, eval=None):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
122
    """Tag a function or plugin method as a Nvim function handler."""
123
    def dec(f):
124
        f._nvim_rpc_method_name = 'function:{}'.format(name)
125
        f._nvim_rpc_sync = sync
126
        f._nvim_bind = True
127
        f._nvim_prefix_plugin_path = True
128
129
        opts = {}
130
131
        if range:
132
            opts['range'] = '' if range is True else str(range)
133
134
        if eval:
135
            opts['eval'] = eval
136
137
        if not sync and allow_nested:
138
            rpc_sync = "urgent"
139
        else:
140
            rpc_sync = sync
141
142
        f._nvim_rpc_spec = {
143
            'type': 'function',
144
            'name': name,
145
            'sync': rpc_sync,
146
            'opts': opts
147
        }
148
        return f
149
    return dec
150
151
152 6
def shutdown_hook(f):
153
    """Tag a function or method as a shutdown hook."""
154
    f._nvim_shutdown_hook = True
155
    f._nvim_bind = True
156
    return f
157
158
159 6
def decode(mode=unicode_errors_default):
160
    """Configure automatic encoding/decoding of strings."""
161
    def dec(f):
162
        f._nvim_decode = mode
163
        return f
164
    return dec
165
166
167 6
def encoding(encoding=True):
168
    """DEPRECATED: use pynvim.decode()."""
169
    if isinstance(encoding, str):
170
        encoding = True
171
172
    def dec(f):
173
        f._nvim_decode = encoding
174
        return f
175
    return dec
176