Passed
Push — master ( aeb165...d9ae97 )
by Dean
03:04
created

StorageHelper   A

Complexity

Total Complexity 25

Size/Duplication

Total Lines 175
Duplicated Lines 0 %

Test Coverage

Coverage 32.89%
Metric Value
wmc 25
dl 0
loc 175
ccs 25
cts 76
cp 0.3289
rs 10

8 Methods

Rating   Name   Duplication   Size   Complexity  
A is_framework_path() 0 10 3
A is_relative_path() 0 21 4
B to_relative_path() 0 25 4
A copy() 0 20 3
A copy_tree() 0 17 2
A delete_tree() 0 16 2
A delete() 0 19 3
A create_directories() 0 20 4
1 1
from plugin.core.helpers import regex as re
2
3 1
import logging
4 1
import os
5 1
import shutil
6
7 1
log = logging.getLogger(__name__)
8
9
10 1
class StorageHelper(object):
11 1
    base_names = [
12
        'plug-ins',
13
        'plug-in support',
14
        'trakttv.bundle'
15
    ]
16
17 1
    framework_patterns = re.compile_list([
18
        # Windows
19
        r'plex media server$',
20
        r'plex media server\/dlls',
21
        r'plex media server\/exts',
22
        r'plex media server\/python27.zip$',
23
        r'plex media server\/resources\/plug-ins-\w+',
24
25
        # Linux
26
        r'resources\/plug-ins-\w+',
27
        r'resources\/python'
28
    ], re.IGNORECASE)
29
30 1
    @classmethod
31
    def create_directories(cls, path, *args, **kwargs):
32
        """Create directory at `path` include any parent directories
33
34
        :type path: str
35
        """
36
37
        try:
38
            os.makedirs(path, *args, **kwargs)
39
            return True
40
        except OSError, ex:
41
            if ex.errno == 17:
42
                # Directory already exists
43
                return True
44
45
            log.warn('Unable to create directories: %r - (%s) %s', cls.to_relative_path(path), ex.errno, ex)
46
        except Exception, ex:
47
            log.warn('Unable to create directories: %r - (%s) %s', cls.to_relative_path(path), type(ex), ex)
48
49
        return False
50
51 1
    @classmethod
52
    def copy(cls, source, destination):
53
        """Copy the file at `source` to `destination`
54
55
        :type source: str
56
        :type destination: str
57
        """
58
59
        if os.path.isdir(source):
60
            return cls.copy_tree(source, destination)
61
62
        try:
63
            shutil.copy2(source, destination)
64
65
            log.debug('Copied %r to %r', cls.to_relative_path(source), cls.to_relative_path(destination))
66
            return True
67
        except Exception, ex:
68
            log.warn('Unable to copy %r to %r - %s', cls.to_relative_path(source), cls.to_relative_path(destination), ex)
69
70
        return False
71
72 1
    @classmethod
73
    def copy_tree(cls, source, destination):
74
        """Copy the directory at `source` to `destination`
75
76
        :type source: str
77
        :type destination: str
78
        """
79
80
        try:
81
            shutil.copytree(source, destination)
82
83
            log.debug('Copied %r to %r', cls.to_relative_path(source), cls.to_relative_path(destination))
84
            return True
85
        except Exception, ex:
86
            log.warn('Unable to copy %r to %r - %s', cls.to_relative_path(source), cls.to_relative_path(destination), ex)
87
88
        return False
89
90 1
    @classmethod
91
    def delete(cls, path):
92
        """Delete the file (at `path`)
93
94
        :type path: str
95
        """
96
97
        if os.path.isdir(path):
98
            return cls.delete_tree(path)
99
100
        try:
101
            os.remove(path)
102
103
            log.debug('Deleted %r', cls.to_relative_path(path))
104
            return True
105
        except Exception, ex:
106
            log.warn('Unable to delete file: %r - %s', cls.to_relative_path(path), ex)
107
108
        return False
109
110 1
    @classmethod
111
    def delete_tree(cls, path):
112
        """Delete the directory (at `path`)
113
114
        :type path: str
115
        """
116
117
        try:
118
            shutil.rmtree(path)
119
120
            log.debug('Deleted %r', cls.to_relative_path(path))
121
            return True
122
        except Exception, ex:
123
            log.warn('Unable to delete directory: %r - %s', cls.to_relative_path(path), ex)
124
125
        return False
126
127 1
    @classmethod
128
    def to_relative_path(cls, path):
129
        """Convert `path` to be relative to `StorageHelper.base_names`
130
131
        :type path: str
132
        """
133
134 1
        path_lower = path.lower()
135
136
        # Find base path
137 1
        base_path = None
138
139 1
        for base in cls.base_names:
140 1
            if base not in path_lower:
141 1
                continue
142
143 1
            base_path = path[:path_lower.find(base)]
144 1
            break
145
146
        # Check if `base_path` was found
147 1
        if not base_path:
148 1
            return path
149
150
        # Return relative path
151 1
        return os.path.relpath(path, base_path)
152
153 1
    @classmethod
154
    def is_relative_path(cls, path):
155
        """Check if `path` is relative to `StorageHelper.base_names`
156
157
        :type path: str
158
        """
159
160
        path = path.lower()
161
162
        # Ignore framework paths
163
        if 'framework.bundle' in path:
164
            return False
165
166
        # Find base path
167
        for base in cls.base_names:
168
            if base not in path:
169
                continue
170
171
            return True
172
173
        return False
174
175 1
    @classmethod
176
    def is_framework_path(cls, path):
177 1
        path = path.replace('\\', '/')
178
179
        # Check for framework fragments
180 1
        for pattern in cls.framework_patterns:
181 1
            if pattern.search(path):
182
                return True
183
184
        return False
185