Passed
Push — develop ( aa14d6...fc562f )
by Dean
03:00
created

CacheManager   A

Complexity

Total Complexity 16

Size/Duplication

Total Lines 113
Duplicated Lines 0 %

Test Coverage

Coverage 13.33%
Metric Value
dl 0
loc 113
ccs 6
cts 45
cp 0.1333
rs 10
wmc 16

5 Methods

Rating   Name   Duplication   Size   Complexity  
B get_paths() 0 28 3
A process() 0 3 2
B execute() 0 30 5
A sync() 0 18 3
B discover() 0 33 5
1 1
from plugin.core.environment import Environment
2 1
from plugin.core.libraries.constants import CONTENTS_PATH
3 1
from plugin.core.libraries.helpers import StorageHelper, SystemHelper
4
5 1
import filecmp
6 1
import logging
7 1
import os
8
9 1
log = logging.getLogger(__name__)
10
11
12 1
class CacheManager(object):
13 1
    @classmethod
14
    def sync(cls):
15
        """Synchronize native libraries cache, adding/updating/removing items to match bundled libraries.
16
17
        :rtype: str
18
        """
19
20
        source, destination = cls.get_paths()
0 ignored issues
show
Bug Best Practice introduced by
Attempting to unpack a non-sequence
Loading history...
Bug Best Practice introduced by
It seems like you are trying to unpack a non-sequence, which was defined at line 116.
Loading history...
21
22
        # Compare directories, discover tasks
23
        changes = filecmp.dircmp(source, destination)
24
        tasks = cls.discover(changes)
25
26
        # Execute tasks
27
        if tasks and not cls.execute(source, destination, tasks):
28
            return None
29
30
        return os.path.join(Environment.path.plugin_data, 'Libraries')
31
32 1
    @classmethod
33 1
    def discover(cls, changes, base_path='', tasks=None):
34
        """"Discover actions required to update the cache.
35
36
        :param changes: Changes between bundle + cache directories
37
        :type changes: filecmp.dircmp
38
39
        :param base_path: Current directory of changes
40
        :type base_path: str
41
42
        :param tasks: Current tasks
43
        :type tasks: list or None
44
45
        :rtype: list
46
        """
47
        if tasks is None:
48
            tasks = []
49
50
        def process(action, names):
51
            for name in names:
52
                tasks.append((action, os.path.join(base_path, name)))
53
54
        # Create tasks from `changes`
55
        process('add', changes.left_only)
56
        process('delete', changes.right_only)
57
        process('update', changes.diff_files)
58
59
        # Process sub directories
60
        for name, child in changes.subdirs.items():
61
            cls.discover(child, os.path.join(base_path, name), tasks)
62
63
        # Tasks retrieved
64
        return tasks
65
66 1
    @classmethod
67
    def execute(cls, source, destination, tasks):
68
        """Execute tasks on directories
69
70
        :param source: Native libraries source directory
71
        :type source: str
72
73
        :param destination: Native libraries cache directory
74
        :type destination: str
75
76
        :param tasks: Tasks to execute
77
        :type tasks: list
78
79
        :rtype: bool
80
        """
81
        success = True
82
83
        for action, path in tasks:
84
            if action in ['add', 'update']:
85
                action_success = StorageHelper.copy(os.path.join(source, path), os.path.join(destination, path))
86
            elif action == 'delete':
87
                action_success = StorageHelper.delete(os.path.join(destination, path))
88
            else:
89
                log.warn('Unknown task: %r - %r', action, path)
90
                action_success = False
91
92
            if not action_success:
93
                success = False
94
95
        return success
96
97 1
    @staticmethod
98
    def get_paths():
99
        """Retrieve system-specific native libraries source + destination path
100
101
        :rtype: (str, str)
102
        """
103
        # Retrieve system details
104
        system = SystemHelper.name()
105
        architecture = SystemHelper.architecture()
106
107
        if not architecture:
108
            return
109
110
        # Build source path
111
        source = os.path.join(CONTENTS_PATH, 'Libraries', system, architecture)
112
113
        # Ensure `source` directory exists
114
        if not os.path.exists(source):
115
            log.error('Unable to find native libraries for platform (name: %r, architecture: %r)', system, architecture)
116
            return None
117
118
        # Build path for native dependencies
119
        destination = os.path.join(Environment.path.plugin_data, 'Libraries', system, architecture)
120
121
        # Ensure `destination` directory has been created
122
        StorageHelper.create_directories(destination)
123
124
        return source, destination
125