GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

qtsass.watchers.api.Watcher.compile_and_dispatch()   A
last analyzed

Complexity

Conditions 2

Size

Total Lines 11
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 8
dl 0
loc 11
rs 10
c 0
b 0
f 0
cc 2
nop 1
1
# -*- coding: utf-8 -*-
2
# -----------------------------------------------------------------------------
3
# Copyright (c) 2015 Yann Lanthony
4
# Copyright (c) 2017-2018 Spyder Project Contributors
5
#
6
# Licensed under the terms of the MIT License
7
# (See LICENSE.txt for details)
8
# -----------------------------------------------------------------------------
9
"""The filesystem watcher api."""
10
11
# yapf: disable
12
13
from __future__ import absolute_import
14
15
# Standard library imports
16
import functools
17
import logging
18
import time
19
20
21
_log = logging.getLogger(__name__)
22
23
24
def retry(n, interval=0.1):
25
    """Retry a function or method n times before raising an exception.
26
27
    :param n: Number of times to retry
28
    :param interval: Time to sleep before attempts
29
    """
30
    def decorate(fn):
31
        @functools.wraps(fn)
32
        def attempt(*args, **kwargs):
33
            attempts = 0
34
            while True:
35
                try:
36
                    return fn(*args, **kwargs)
37
                except Exception:
38
                    attempts += 1
39
                    if n <= attempts:
40
                        raise
41
                    time.sleep(interval)
42
43
        return attempt
44
45
    return decorate
46
47
# yapf: enable
48
49
50
class Watcher(object):
51
    """Watcher base class.
52
53
    Watchers monitor a file or directory and call the on_change method when a
54
    change occurs. The on_change method should trigger the compiler function
55
    passed in during construction and dispatch the result to all connected
56
    callbacks.
57
58
    Watcher implementations must inherit from this base class. Subclasses
59
    should perform any setup required in the setup method, rather than
60
    overriding __init__.
61
    """
62
63
    def __init__(self, watch_dir, compiler, args=None, kwargs=None):
64
        """Store initialization values and call Watcher.setup."""
65
        self._watch_dir = watch_dir
66
        self._compiler = compiler
67
        self._args = args or ()
68
        self._kwargs = kwargs or {}
69
        self._callbacks = set()
70
        self._log = _log
71
        self.setup()
72
73
    def setup(self):
74
        """Perform any setup required here.
75
76
        Rather than implement __init__, subclasses can perform any setup in
77
        this method.
78
        """
79
        return NotImplemented
80
81
    def start(self):
82
        """Start this Watcher."""
83
        return NotImplemented
84
85
    def stop(self):
86
        """Stop this Watcher."""
87
        return NotImplemented
88
89
    def join(self):
90
        """Wait for this Watcher to finish."""
91
        return NotImplemented
92
93
    @retry(5)
94
    def compile(self):
95
        """Call the Watcher's compiler."""
96
        self._log.debug(
97
            'Compiling sass...%s(*%s, **%s)',
98
            self._compiler,
99
            self._args,
100
            self._kwargs,
101
        )
102
        return self._compiler(*self._args, **self._kwargs)
103
104
    def compile_and_dispatch(self):
105
        """Compile and dispatch the resulting css to connected callbacks."""
106
        self._log.debug('Compiling and dispatching....')
107
108
        try:
109
            css = self.compile()
110
        except Exception:
111
            self._log.exception('Failed to compile...')
112
            return
113
114
        self.dispatch(css)
115
116
    def dispatch(self, css):
117
        """Dispatch css to connected callbacks."""
118
        self._log.debug('Dispatching callbacks...')
119
        for callback in self._callbacks:
120
            callback(css)
121
122
    def on_change(self):
123
        """Call when a change is detected.
124
125
        Subclasses must call this method when they detect a change. Subclasses
126
        may also override this method in order to manually compile and dispatch
127
        callbacks. For example, a Qt implementation may use signals and slots
128
        to ensure that compiling and executing callbacks happens in the main
129
        GUI thread.
130
        """
131
        self._log.debug('Change detected...')
132
        self.compile_and_dispatch()
133
134
    def connect(self, fn):
135
        """Connect a callback to this Watcher.
136
137
        All callbacks are called when a change is detected. Callbacks are
138
        passed the compiled css.
139
        """
140
        self._log.debug('Connecting callback: %s', fn)
141
        self._callbacks.add(fn)
142
143
    def disconnect(self, fn):
144
        """Disconnect a callback from this Watcher."""
145
        self._log.debug('Disconnecting callback: %s', fn)
146
        self._callbacks.discard(fn)
147