decorate()   F
last analyzed

Complexity

Conditions 13

Size

Total Lines 38

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 13
c 1
b 0
f 0
dl 0
loc 38
rs 2.7716

How to fix   Complexity   

Complexity

Complex classes like decorate() 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
'''
2
some of these should go into neovim python client
3
'''
4
from __future__ import print_function
5
6
import os
7
import time
8
from subprocess import *
9
from threading import Thread
10
import shlex
11
import string
12
import random
13
from functools import wraps
14
from distutils.spawn import find_executable
15
16
from neovim import attach
17
18
def attach_socket(path=None):
19
    '''does it auto'''
20
    def open_nvim():
21
        proc = Popen('NVIM_LISTEN_ADDRESS=/tmp/nvim nvim',
22
                    stdin=PIPE, stdout=PIPE, shell=True)
23
        proc.communicate()
24
25
    # THIS IS DOESNT WORK UNRELIBALE 
26
    #path = os.environ.get('NVIM_LISTEN_ADDRESS')
27
    if not path:
28
        print('threading')
29
        t = Thread(target=open_nvim)
30
        t.start()
31
        #todo make this give a random path
32
        return attach('socket', path='/tmp/nvim')
33
    else:
34
        print('attaching socket')
35
        return attach('socket', path=path)
36
37
38
def attach_child(nvim_args, exec_name='nvim'):
39
    nvim_binary = find_executable(exec_name)
40
    args = [nvim_binary, '--embed']
41
    if nvim_args:
42
        args.extend(nvim_args)
43
    return attach('child', argv=args)
44
45
46
def attach_headless(nvim_args=None, path=None):
47
    if not path:
48
        path = '/tmp/nvim' + rand_str(8)
49
    os.environ['NVIM_LISTEN_ADDRESS'] = path
50
    dnull = open(os.devnull)
51
    # TODO WHY USE SHLEX???
52
    cmd = shlex.split('nvim --headless')
53
    if nvim_args:
54
        cmd.extend(nvim_args)
55
    proc = Popen(cmd,
56
            stdin=dnull,
57
            stdout=dnull,
58
            stderr=dnull)
59
    dnull.close()
60
    while proc.poll() or proc.returncode is None:
61
        try:
62
            print('connected to headless socket', path)
63
            nvim = attach('socket', path=path)
64
            break
65
        except IOError:
66
            # Socket not yet ready
67
            time.sleep(0.05)
68
69
    return nvim
70
71
72
def rand_str(length):
73
    '''returns a random string of length'''
74
    chars = []
75
    for i in range(length):
76
        chars.append(random.choice(string.ascii_letters))
77
    return ''.join(char for char in chars)
78
79
80
def _stringify_key(key, state):
81
    send = []
82
    if state == 'Shift':
83
        send.append('S')
84
    elif state == 'Ctrl':
85
        send.append('C')
86
    elif state =='Alt':
87
        send.append('A')
88
    send.append(key)
89
    return '<' + '-'.join(send) + '>'
90
91
92
def _split_color(n):
93
    return ((n >> 16) & 0xff, (n >> 8) & 0xff, n & 0xff,)
94
95
96
def _invert_color(r, g, b):
97
    return (255 - r, 255 - g, 255 - b,)
98
99
100
def _stringify_color(r, g, b):
101
    return '#{0:0{1}x}'.format((r << 16) + (g << 8) + b, 6)
102
103
104
def debug_echo(func):
105
    '''used on method to simply print the function name and
106
    parameters if self.debug_echo = True,
107
    the function will not execute'''
108
    @wraps(func)
109
    def deco(*args, **kwargs):
110
        try:
111
            debug = args[0].debug_echo
112
        except AttributeError:
113
            debug = False
114
        if debug:
115
            if len(args) == 1:
116
                to_print = []
117
            else:
118
                to_print = args[1:]
119
            print(func.__name__, repr(to_print), **kwargs)
120
121
        return func(*args, **kwargs)
122
    return deco
123
124
125
def rate_limited(max_per_second, mode='wait', delay_first_call=False):
126
    """
127
    Decorator that make functions not be called faster than
128
129
    set mode to 'kill' to just ignore requests that are faster than the
130
    rate.
131
132
    set mode to 'refresh_timer' to reset the timer on successive calls
133
134
    set delay_first_call to True to delay the first call as well
135
    """
136
    lock = threading.Lock()
137
    min_interval = 1.0 / float(max_per_second)
138
    def decorate(func):
139
        last_time_called = [0.0]
140
        @wraps(func)
141
        def rate_limited_function(*args, **kwargs):
142
            def run_func():
143
                lock.release()
144
                ret = func(*args, **kwargs)
145
                last_time_called[0] = time.perf_counter()
146
                return ret
147
            lock.acquire()
148
            elapsed = time.perf_counter() - last_time_called[0]
149
            left_to_wait = min_interval - elapsed
150
            if delay_first_call:
151
                if left_to_wait > 0:
152
                    if mode == 'wait':
153
                        time.sleep(left_to_wait)
154
                        return run_func()
155
                    elif mode == 'kill':
156
                        lock.release()
157
                        return
158
                else:
159
                    return run_func()
160
            else:
161
                if not last_time_called[0] or elapsed > min_interval:
162
                    return run_func()
163
                elif mode == 'refresh_timer':
164
                    print('Ref timer')
165
                    lock.release()
166
                    last_time_called[0] += time.perf_counter()
167
                    return
168
                elif left_to_wait > 0:
169
                    if mode == 'wait':
170
                        time.sleep(left_to_wait)
171
                        return run_func()
172
                    elif mode == 'kill':
173
                        lock.release()
174
                        return
175
        return rate_limited_function
176
    return decorate
177
178