Passed
Push — develop ( 1b4b8c...fa1775 )
by Dean
03:19
created

Bootstrap.update_proxies()   F

Complexity

Conditions 13

Size

Total Lines 66

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
dl 0
loc 66
c 1
b 0
f 0
rs 2.649
cc 13

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Complexity

Complex classes like Bootstrap.update_proxies() 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
from core.state import State
2
3
from plugin.core.constants import PLUGIN_VERSION, PLUGIN_NAME
4
from plugin.core.helpers.thread import spawn
5
6
from datetime import datetime
7
import inspect
8
9
# http://bugs.python.org/issue7980
10
datetime.strptime('', '')
11
12
13
def task(*args, **kwargs):
14
    def wrapper(func):
15
        func.optional = kwargs.get('optional', False)
16
17
        func.priority = args
18
        func.task = True
19
20
        return func
21
22
    return wrapper
23
24
25
class Bootstrap(object):
26
    class Groups(object):
27
        Initialize  = 10
0 ignored issues
show
Coding Style introduced by
Exactly one space required before assignment
Initialize = 10
^
Loading history...
28
        Configure   = 20
0 ignored issues
show
Coding Style introduced by
Exactly one space required before assignment
Configure = 20
^
Loading history...
29
        Start       = 30
0 ignored issues
show
Coding Style introduced by
Exactly one space required before assignment
Start = 30
^
Loading history...
30
31
    debug = False
32
33
    def discover(self):
34
        tasks = []
35
36
        for name in dir(self):
37
            if name.startswith('_'):
38
                continue
39
40
            value = getattr(self, name)
41
42
            if not inspect.ismethod(value):
43
                continue
44
45
            if not hasattr(value, 'task') or not hasattr(value, 'priority'):
46
                continue
47
48
            tasks.append(value)
49
50
        return sorted(tasks, key=lambda t: t.priority)
51
52
    def start(self):
53
        spawn(self.run, daemon=True, thread_name='bootstrap')
54
55
    def run(self):
56
        tasks = self.discover()
57
58
        if self.debug:
59
            Log.Debug('Starting %d task(s)...' % (len(tasks),))
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'Log'
Loading history...
60
61
        for func in tasks:
62
            name = func.__name__
63
64
            if self.debug:
65
                Log.Debug('Task \'%s\' started' % (name,))
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'Log'
Loading history...
66
67
            if func.priority and type(func.priority) is tuple:
68
                State.set(func.priority[0])
69
70
            try:
71
                func()
72
73
                if self.debug:
74
                    Log.Debug('Task \'%s\' finished' % (name,))
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'Log'
Loading history...
75
            except Exception as ex:
0 ignored issues
show
Best Practice introduced by
Catching very general exceptions such as Exception is usually not recommended.

Generally, you would want to handle very specific errors in the exception handler. This ensure that you do not hide other types of errors which should be fixed.

So, unless you specifically plan to handle any error, consider adding a more specific exception.

Loading history...
76
                if not func.optional:
77
                    Log.Error('Unable to start plugin, task \'%s\' raised: %s' % (name, ex))
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'Log'
Loading history...
78
79
                    State.set(State.Types.error, ex)
80
                    return False
81
82
                Log.Warn('Task \'%s\' raised: %s' % (name, ex))
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'Log'
Loading history...
83
84
        if self.debug:
85
            Log.Debug('Finished %d task(s)' % (len(tasks),))
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'Log'
Loading history...
86
87
        State.set(State.Types.started)
88
        return True
89
90
    #
91
    # Header
92
    #
93
94
    @task()
95
    def header(self):
0 ignored issues
show
Coding Style introduced by
This method could be written as a function/class method.

If a method does not access any attributes of the class, it could also be implemented as a function or static method. This can help improve readability. For example

class Foo:
    def some_method(self, x, y):
        return x + y;

could be written as

class Foo:
    @classmethod
    def some_method(cls, x, y):
        return x + y;
Loading history...
96
        def line(contents):
97
            Log.Info('| ' + str(contents))
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'Log'
Loading history...
98
99
        def separator(ch):
100
            Log.Info(ch * 50)
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'Log'
Loading history...
101
102
        separator('=')
103
        line(PLUGIN_NAME)
104
        line('https://github.com/trakt/Plex-Trakt-Scrobbler')
105
        separator('-')
106
        line('Current Version: %s' % (PLUGIN_VERSION,))
107
        separator('=')
108
109
    #
110
    # Initialize
111
    #
112
113
    @task(Groups.Initialize, 10)
114
    def initialize_environment(self):
0 ignored issues
show
Coding Style introduced by
This method could be written as a function/class method.

If a method does not access any attributes of the class, it could also be implemented as a function or static method. This can help improve readability. For example

class Foo:
    def some_method(self, x, y):
        return x + y;

could be written as

class Foo:
    @classmethod
    def some_method(cls, x, y):
        return x + y;
Loading history...
115
        from plugin.core.environment import Environment
116
        import os
117
118
        Environment.setup(Core, Dict, Platform, Prefs)
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'Core'
Loading history...
Comprehensibility Best Practice introduced by
Undefined variable 'Dict'
Loading history...
Comprehensibility Best Practice introduced by
Undefined variable 'Platform'
Loading history...
Comprehensibility Best Practice introduced by
Undefined variable 'Prefs'
Loading history...
119
120
        # plex.database.py
121
        os.environ['LIBRARY_DB'] = os.path.join(
122
            Environment.path.plugin_support, 'Databases',
123
            'com.plexapp.plugins.library.db'
124
        )
125
126
    @task(Groups.Initialize, 20)
127
    def initialize_filesystem(self):
0 ignored issues
show
Coding Style introduced by
This method could be written as a function/class method.

If a method does not access any attributes of the class, it could also be implemented as a function or static method. This can help improve readability. For example

class Foo:
    def some_method(self, x, y):
        return x + y;

could be written as

class Foo:
    @classmethod
    def some_method(cls, x, y):
        return x + y;
Loading history...
128
        from fs_migrator import FSMigrator
129
130
        FSMigrator.run()
131
132
    @task(Groups.Initialize, 30)
133
    def initialize_logging(self):
0 ignored issues
show
Coding Style introduced by
This method could be written as a function/class method.

If a method does not access any attributes of the class, it could also be implemented as a function or static method. This can help improve readability. For example

class Foo:
    def some_method(self, x, y):
        return x + y;

could be written as

class Foo:
    @classmethod
    def some_method(cls, x, y):
        return x + y;
Loading history...
134
        from plugin.core.logger import LoggerManager
135
136
        LoggerManager.setup(storage=False)
137
        LoggerManager.refresh()
138
139
    @task(Groups.Initialize, 40)
140
    def initialize_interface_messages(self):
0 ignored issues
show
Coding Style introduced by
This method could be written as a function/class method.

If a method does not access any attributes of the class, it could also be implemented as a function or static method. This can help improve readability. For example

class Foo:
    def some_method(self, x, y):
        return x + y;

could be written as

class Foo:
    @classmethod
    def some_method(cls, x, y):
        return x + y;
Loading history...
141
        from plugin.core.message import InterfaceMessages
142
143
        InterfaceMessages.bind()
144
145
    @task(Groups.Initialize, 50)
146
    def initialize_locale(self):
0 ignored issues
show
Coding Style introduced by
This method could be written as a function/class method.

If a method does not access any attributes of the class, it could also be implemented as a function or static method. This can help improve readability. For example

class Foo:
    def some_method(self, x, y):
        return x + y;

could be written as

class Foo:
    @classmethod
    def some_method(cls, x, y):
        return x + y;
Loading history...
147
        from plugin.core.environment import Environment
148
149
        Environment.setup_locale()
150
        Environment.setup_translation()
151
152
    @task(Groups.Initialize, 60)
153
    def initialize_native_libraries(self):
0 ignored issues
show
Coding Style introduced by
This method could be written as a function/class method.

If a method does not access any attributes of the class, it could also be implemented as a function or static method. This can help improve readability. For example

class Foo:
    def some_method(self, x, y):
        return x + y;

could be written as

class Foo:
    @classmethod
    def some_method(cls, x, y):
        return x + y;
Loading history...
154
        from plugin.core.libraries.manager import LibrariesManager
155
156
        LibrariesManager.setup(cache=True)
157
        LibrariesManager.test()
158
159
    @task(Groups.Initialize, 70)
160
    def initialize_warnings(self):
0 ignored issues
show
Coding Style introduced by
This method could be written as a function/class method.

If a method does not access any attributes of the class, it could also be implemented as a function or static method. This can help improve readability. For example

class Foo:
    def some_method(self, x, y):
        return x + y;

could be written as

class Foo:
    @classmethod
    def some_method(cls, x, y):
        return x + y;
Loading history...
161
        from requests.packages.urllib3.exceptions import InsecurePlatformWarning, SNIMissingWarning
162
        import warnings
163
164
        warnings.filterwarnings('once', category=InsecurePlatformWarning)
165
        warnings.filterwarnings('once', category=SNIMissingWarning)
166
167
    @task(Groups.Initialize, 90)
168
    def initialize_singleton(self):
0 ignored issues
show
Coding Style introduced by
This method could be written as a function/class method.

If a method does not access any attributes of the class, it could also be implemented as a function or static method. This can help improve readability. For example

class Foo:
    def some_method(self, x, y):
        return x + y;

could be written as

class Foo:
    @classmethod
    def some_method(cls, x, y):
        return x + y;
Loading history...
169
        from plugin.core.singleton import Singleton
170
171
        if not Singleton.acquire():
172
            Log.Warn('Unable to acquire plugin instance')
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'Log'
Loading history...
173
174
    @task(Groups.Initialize, 100)
175
    def initialize_logging_storage(self):
0 ignored issues
show
Coding Style introduced by
This method could be written as a function/class method.

If a method does not access any attributes of the class, it could also be implemented as a function or static method. This can help improve readability. For example

class Foo:
    def some_method(self, x, y):
        return x + y;

could be written as

class Foo:
    @classmethod
    def some_method(cls, x, y):
        return x + y;
Loading history...
176
        from plugin.core.logger import LoggerManager
177
178
        LoggerManager.setup(storage=True)
179
180
    #
181
    # Configure
182
    #
183
184
    @task(Groups.Configure, 10)
185
    def configure_proxies(self):
186
        # Update proxies (for requests)
187
        self.update_proxies()
188
189
    @task(Groups.Configure, 20)
190
    def configure_loggers(self):
0 ignored issues
show
Coding Style introduced by
This method could be written as a function/class method.

If a method does not access any attributes of the class, it could also be implemented as a function or static method. This can help improve readability. For example

class Foo:
    def some_method(self, x, y):
        return x + y;

could be written as

class Foo:
    @classmethod
    def some_method(cls, x, y):
        return x + y;
Loading history...
191
        from plugin.core.logger import LoggerManager
192
193
        # Refresh logger levels
194
        LoggerManager.refresh()
195
196
    @task(Groups.Configure, 30)
197
    def configure_trakt(self):
198
        from plugin.core.configuration import Configuration
199
200
        from requests.packages.urllib3.util import Retry
201
        from trakt import Trakt
202
203
        config = Configuration.advanced['trakt']
204
205
        # Build timeout value
206
        timeout = (
207
            config.get_float('connect_timeout', 6.05),
208
            config.get_float('read_timeout', 24)
209
        )
210
211
        # Client
212
        Trakt.configuration.defaults.client(
213
            id='c9ccd3684988a7862a8542ae0000535e0fbd2d1c0ca35583af7ea4e784650a61',
214
            secret='bf00575b1ad252b514f14b2c6171fe650d474091daad5eb6fa890ef24d581f65'
215
        )
216
217
        # Application
218
        Trakt.configuration.defaults.app(
219
            name='trakt (for Plex)',
220
            version=PLUGIN_VERSION
221
        )
222
223
        # Http
224
        Trakt.base_url = (
225
            config.get('protocol', 'https') + '://' +
226
            config.get('hostname', 'api.trakt.tv')
227
        )
228
229
        Trakt.configuration.defaults.http(
230
            timeout=timeout
231
        )
232
233
        # Configure keep-alive
234
        Trakt.http.keep_alive = config.get_boolean('keep_alive', True)
235
236
        # Configure requests adapter
237
        Trakt.http.adapter_kwargs = {
238
            'pool_connections': config.get_int('pool_connections', 10),
239
            'pool_maxsize': config.get_int('pool_size', 10),
240
            'max_retries': Retry(
241
                total=config.get_int('connect_retries', 3),
242
                read=0
243
            )
244
        }
245
246
        Trakt.http.rebuild()
247
248
        # Bind to events
249
        Trakt.on('oauth.refresh', self.on_trakt_refresh)
250
        Trakt.on('oauth.refresh.rejected', self.on_trakt_refresh_rejected)
251
252
        Log.Info('Configured trakt.py (timeout=%r, base_url=%r, keep_alive=%r, adapter_kwargs=%r)' % (
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'Log'
Loading history...
253
            timeout,
254
            Trakt.base_url,
255
            Trakt.http.keep_alive,
256
            Trakt.http.adapter_kwargs,
257
        ))
258
259
    @task(Groups.Configure, 40)
260
    def configure_plex(self):
0 ignored issues
show
Coding Style introduced by
This method could be written as a function/class method.

If a method does not access any attributes of the class, it could also be implemented as a function or static method. This can help improve readability. For example

class Foo:
    def some_method(self, x, y):
        return x + y;

could be written as

class Foo:
    @classmethod
    def some_method(cls, x, y):
        return x + y;
Loading history...
261
        from plugin.core.logger import LOG_HANDLER
262
263
        from plex import Plex
264
        from plex_activity import Activity
265
        from plex_metadata import Metadata
266
        import os
267
        import uuid
268
269
        # Ensure client identifier has been generated
270
        if not Dict['plex.client.identifier']:
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'Dict'
Loading history...
271
            # Generate identifier
272
            Dict['plex.client.identifier'] = uuid.uuid4()
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'Dict'
Loading history...
273
274
        # Retrieve current client identifier
275
        client_id = Dict['plex.client.identifier']
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'Dict'
Loading history...
276
277
        if isinstance(client_id, uuid.UUID):
278
            client_id = str(client_id)
279
280
        # plex.py
281
        Plex.configuration.defaults.authentication(
282
            os.environ.get('PLEXTOKEN')
283
        )
284
285
        Plex.configuration.defaults.client(
286
            identifier=client_id,
287
288
            product='trakt (for Plex)',
289
            version=PLUGIN_VERSION
290
        )
291
292
        # plex.activity.py
293
        path = os.path.join(LOG_HANDLER.baseFilename, '..', '..', 'Plex Media Server.log')
294
        path = os.path.abspath(path)
295
296
        Activity['logging'].add_hint(path)
297
298
        # plex.metadata.py
299
        Metadata.configure(
300
            client=Plex.client
301
        )
302
303
    #
304
    # Start
305
    #
306
307
    @task(Groups.Start, 0)
308
    def start_module_initialization(self):
0 ignored issues
show
Coding Style introduced by
This method could be written as a function/class method.

If a method does not access any attributes of the class, it could also be implemented as a function or static method. This can help improve readability. For example

class Foo:
    def some_method(self, x, y):
        return x + y;

could be written as

class Foo:
    @classmethod
    def some_method(cls, x, y):
        return x + y;
Loading history...
309
        from plugin.modules.core.manager import ModuleManager
310
311
        # Initialize modules
312
        ModuleManager.initialize()
313
314
    @task(Groups.Start, 10)
315
    def start_token_exists(self):
0 ignored issues
show
Coding Style introduced by
This method could be written as a function/class method.

If a method does not access any attributes of the class, it could also be implemented as a function or static method. This can help improve readability. For example

class Foo:
    def some_method(self, x, y):
        return x + y;

could be written as

class Foo:
    @classmethod
    def some_method(cls, x, y):
        return x + y;
Loading history...
316
        import os
317
318
        Log.Info('X-Plex-Token: %s', 'available' if os.environ.get('PLEXTOKEN') else 'unavailable')
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'Log'
Loading history...
319
320
    @task(Groups.Start, 20)
321
    def start_check_server_state(self):
322
        from plex import Plex
323
324
        # Check startup state
325
        server = Plex.detail()
326
327
        if server is None:
328
            Log.Info('Unable to check startup state, detail request failed')
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'Log'
Loading history...
329
            return
330
331
        # Check server startup state
332
        if server.start_state is None:
333
            return
334
335
        if server.start_state == 'startingPlugins':
336
            return self.on_starting_plugins()
337
338
        Log.Warn('Unhandled server start state %r' % (server.start_state,))
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'Log'
Loading history...
339
340
    @task(Groups.Start, 100)
341
    def start_modules(self):
0 ignored issues
show
Coding Style introduced by
This method could be written as a function/class method.

If a method does not access any attributes of the class, it could also be implemented as a function or static method. This can help improve readability. For example

class Foo:
    def some_method(self, x, y):
        return x + y;

could be written as

class Foo:
    @classmethod
    def some_method(cls, x, y):
        return x + y;
Loading history...
342
        from plugin.core.helpers.thread import module_start
343
        from plugin.modules.core.manager import ModuleManager
344
345
        # Start old-style modules
346
        module_start()
347
348
        # Start new-style modules
349
        ModuleManager.start()
350
351
    @task(Groups.Start, 200)
352
    def start_plex_activity(self):
0 ignored issues
show
Coding Style introduced by
This method could be written as a function/class method.

If a method does not access any attributes of the class, it could also be implemented as a function or static method. This can help improve readability. For example

class Foo:
    def some_method(self, x, y):
        return x + y;

could be written as

class Foo:
    @classmethod
    def some_method(cls, x, y):
        return x + y;
Loading history...
353
        from plugin.core.constants import ACTIVITY_MODE
354
        from plugin.preferences import Preferences
355
356
        from plex_activity import Activity
357
358
        # Start plex.activity.py
359
        Activity.start(ACTIVITY_MODE.get(Preferences.get('activity.mode')))
360
361
    @task(Groups.Start, 210)
362
    def start_update_checker(self):
0 ignored issues
show
Coding Style introduced by
This method could be written as a function/class method.

If a method does not access any attributes of the class, it could also be implemented as a function or static method. This can help improve readability. For example

class Foo:
    def some_method(self, x, y):
        return x + y;

could be written as

class Foo:
    @classmethod
    def some_method(cls, x, y):
        return x + y;
Loading history...
363
        from core.update_checker import UpdateChecker
364
365
        checker = UpdateChecker()
366
        checker.start()
367
368
    #
369
    # Event handlers
370
    #
371
372
    @classmethod
373
    def on_configuration_changed(cls):
374
        from plugin.core.logger import LoggerManager
375
376
        # Update proxies (for requests)
377
        cls.update_proxies()
378
379
        # Refresh logger levels
380
        LoggerManager.refresh()
381
382
    @staticmethod
383
    def on_starting_plugins():
384
        from plugin.scrobbler.core.session_prefix import SessionPrefix
385
386
        Log.Debug('Server is starting up, incrementing session prefix...')
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'Log'
Loading history...
387
388
        SessionPrefix.increment()
389
390
    @staticmethod
391
    def on_trakt_refresh(username, authorization):
392
        from plugin.managers.account import TraktAccountManager
393
        from plugin.models import TraktAccount
394
395
        from trakt import Trakt
396
397
        Log.Debug('[Trakt.tv] Token has been refreshed for %r' % (username,))
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'Log'
Loading history...
398
399
        # Retrieve trakt account matching this `authorization`
400
        with Trakt.configuration.http(retry=True).oauth(token=authorization.get('access_token')):
401
            settings = Trakt['users/settings'].get(validate_token=False)
402
403
        if not settings:
404
            Log.Warn('[Trakt.tv] Unable to retrieve account details for token')
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'Log'
Loading history...
405
            return False
406
407
        # Retrieve trakt account username from `settings`
408
        s_username = settings.get('user', {}).get('username')
409
410
        if not s_username:
411
            Log.Warn('[Trakt.tv] Unable to retrieve username for token')
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'Log'
Loading history...
412
            return False
413
414
        if s_username != username:
415
            Log.Warn('[Trakt.tv] Token mismatch (%r != %r)', s_username, username)
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'Log'
Loading history...
416
            return False
417
418
        # Find matching trakt account
419
        trakt_account = (TraktAccount
420
            .select()
421
            .where(
422
                TraktAccount.username == username
423
            )
424
        ).first()
425
426
        if not trakt_account:
427
            Log.Warn('[Trakt.tv] Unable to find account with the username: %r', username)
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'Log'
Loading history...
428
            return False
429
430
        # Update OAuth credential
431
        TraktAccountManager.update.from_dict(
432
            trakt_account, {
433
                'authorization': {
434
                    'oauth': authorization
435
                }
436
            },
437
            settings=settings
438
        )
439
440
        Log.Info('[Trakt.tv] Token updated for %r', trakt_account)
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'Log'
Loading history...
441
        return True
442
443
    @staticmethod
444
    def on_trakt_refresh_rejected(username):
445
        from plugin.managers.m_trakt.credential import TraktOAuthCredentialManager
446
        from plugin.models import TraktAccount
447
448
        Log.Debug('[Trakt.tv] Token refresh for %r has been rejected', username)
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'Log'
Loading history...
449
450
        # Find matching trakt account
451
        account = (TraktAccount
452
            .select()
453
            .where(
454
                TraktAccount.username == username
455
            )
456
        ).first()
457
458
        if not account:
459
            Log.Warn('[Trakt.tv] Unable to find account with the username: %r', username)
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'Log'
Loading history...
460
            return False
461
462
        # Delete OAuth credential
463
        TraktOAuthCredentialManager.delete(
464
            account=account.id
465
        )
466
467
        Log.Info('[Trakt.tv] Token cleared for %r', account)
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'Log'
Loading history...
468
        return True
469
470
    #
471
    # Actions
472
    #
473
474
    @staticmethod
475
    def update_proxies():
476
        from six.moves.urllib.parse import quote_plus, urlsplit, urlunsplit
477
        from trakt import Trakt
478
        import os
479
480
        # Retrieve proxy host
481
        host = Prefs['proxy_host']
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'Prefs'
Loading history...
482
483
        if not host:
484
            if not Trakt.http.proxies and not os.environ.get('HTTP_PROXY') and not os.environ.get('HTTPS_PROXY'):
485
                return
486
487
            # Update trakt client
488
            Trakt.http.proxies = {}
489
490
            # Update environment variables
491
            if 'HTTP_PROXY' in os.environ:
492
                del os.environ['HTTP_PROXY']
493
494
            if 'HTTPS_PROXY' in os.environ:
495
                del os.environ['HTTPS_PROXY']
496
497
            Log.Info('HTTP Proxy has been disabled')
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'Log'
Loading history...
498
            return
499
500
        # Parse URL
501
        host_parsed = urlsplit(host)
502
503
        # Expand components
504
        scheme, netloc, path, query, fragment = host_parsed
505
506
        if not scheme:
507
            scheme = 'http'
508
509
        # Retrieve proxy credentials
510
        username = Prefs['proxy_username']
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'Prefs'
Loading history...
511
        password = Prefs['proxy_password']
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'Prefs'
Loading history...
512
513
        # Build URL
514
        if username and password and '@' not in netloc:
515
            netloc = '%s:%s@%s' % (
516
                quote_plus(username),
517
                quote_plus(password),
518
                netloc
519
            )
520
521
        url = urlunsplit((scheme, netloc, path, query, fragment))
522
523
        # Update trakt client
524
        Trakt.http.proxies = {
525
            'http': url,
526
            'https': url
527
        }
528
529
        # Update environment variables
530
        os.environ.update({
531
            'HTTP_PROXY': url,
532
            'HTTPS_PROXY': url
533
        })
534
535
        # Display message in log file
536
        if not host_parsed.username and not host_parsed.password:
537
            Log.Info('HTTP Proxy has been enabled (host: %r)' % (host,))
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'Log'
Loading history...
538
        else:
539
            Log.Info('HTTP Proxy has been enabled (host: <sensitive>)')
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'Log'
Loading history...
540
541
542
bootstrap = Bootstrap()
543