Passed
Push — develop ( fc562f...b9b638 )
by Dean
02:34
created

CacheManager.get_paths()   B

Complexity

Conditions 3

Size

Total Lines 28

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 9.933
Metric Value
cc 3
dl 0
loc 28
ccs 1
cts 12
cp 0.0833
crap 9.933
rs 8.8571
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 121.
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
                # Ignore "*.pyc" files
53
                if name.endswith('.pyc'):
54
                    continue
55
56
                # Append task to list
57
                tasks.append((action, os.path.join(base_path, name)))
58
59
        # Create tasks from `changes`
60
        process('add', changes.left_only)
61
        process('delete', changes.right_only)
62
        process('update', changes.diff_files)
63
64
        # Process sub directories
65
        for name, child in changes.subdirs.items():
66
            cls.discover(child, os.path.join(base_path, name), tasks)
67
68
        # Tasks retrieved
69
        return tasks
70
71 1
    @classmethod
72
    def execute(cls, source, destination, tasks):
73
        """Execute tasks on directories
74
75
        :param source: Native libraries source directory
76
        :type source: str
77
78
        :param destination: Native libraries cache directory
79
        :type destination: str
80
81
        :param tasks: Tasks to execute
82
        :type tasks: list
83
84
        :rtype: bool
85
        """
86
        success = True
87
88
        for action, path in tasks:
89
            if action in ['add', 'update']:
90
                action_success = StorageHelper.copy(os.path.join(source, path), os.path.join(destination, path))
91
            elif action == 'delete':
92
                action_success = StorageHelper.delete(os.path.join(destination, path))
93
            else:
94
                log.warn('Unknown task: %r - %r', action, path)
95
                action_success = False
96
97
            if not action_success:
98
                success = False
99
100
        return success
101
102 1
    @staticmethod
103
    def get_paths():
104
        """Retrieve system-specific native libraries source + destination path
105
106
        :rtype: (str, str)
107
        """
108
        # Retrieve system details
109
        system = SystemHelper.name()
110
        architecture = SystemHelper.architecture()
111
112
        if not architecture:
113
            return
114
115
        # Build source path
116
        source = os.path.join(CONTENTS_PATH, 'Libraries', system, architecture)
117
118
        # Ensure `source` directory exists
119
        if not os.path.exists(source):
120
            log.error('Unable to find native libraries for platform (name: %r, architecture: %r)', system, architecture)
121
            return None
122
123
        # Build path for native dependencies
124
        destination = os.path.join(Environment.path.plugin_data, 'Libraries', system, architecture)
125
126
        # Ensure `destination` directory has been created
127
        StorageHelper.create_directories(destination)
128
129
        return source, destination
130