Passed
Push — develop ( 6fb855...7cfc9a )
by Dean
02:39
created

BackupRevision.delete()   B

Complexity

Conditions 4

Size

Total Lines 30

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 17.8222
Metric Value
cc 4
dl 0
loc 30
ccs 1
cts 21
cp 0.0476
crap 17.8222
rs 8.5806
1 1
from plugin.core.helpers.variable import json_date_serializer
2
3 1
from datetime import datetime
4 1
import json
5 1
import logging
6 1
import os
7
8 1
log = logging.getLogger(__name__)
9
10
11 1
class BackupRevision(object):
12 1
    def __init__(self, timestamp, contents, tag=None, attributes=None, path=None):
13 1
        self.timestamp = timestamp
14 1
        self.contents = contents
15
16 1
        self.tag = tag
17 1
        self.attributes = attributes or {}
18
19 1
        self.path = path
20
21 1
    def delete(self):
22
        if not self.path:
23
            log.warn('Revision has no "path" defined, unable to delete revision')
24
            return False
25
26
        log.info('Deleting revision: %r', self)
27
28
        # Delete revision metadata
29
        try:
30
            os.remove(self.path)
31
        except Exception, ex:
32
            log.warn('Unable to delete revision metadata file: %r - %s', self.path, ex, exc_info=True)
33
            return False
34
35
        # Delete revision contents
36
        directory = os.path.dirname(self.path)
37
38
        for name in self.contents:
39
            path = os.path.join(directory, name)
40
41
            if not os.path.exists(path):
42
                continue
43
44
            try:
45
                os.remove(path)
46
            except Exception, ex:
47
                log.warn('Unable to delete revision file: %r - %s', path, ex, exc_info=True)
48
                return False
49
50
        return True
51
52 1
    def dict(self):
53
        # Construct dictionary of data
54 1
        result = {
55
            'timestamp': self.timestamp,
56
            'contents': self.contents,
57
        }
58
59
        # Add revision "tag"
60 1
        if self.tag:
61 1
            result['tag'] = self.tag
62
63
        # Merge attributes
64 1
        result.update(self.attributes)
65
66 1
        return result
67
68 1
    @classmethod
69
    def load(cls, path):
70
        # Read json from `path`
71
        with open(path, 'rb') as fp:
72
            metadata = json.load(fp)
73
74
        if not metadata:
75
            raise ValueError('Invalid revision metadata: %r' % metadata)
76
77
        # Parse timestamp
78
        timestamp = metadata.pop('timestamp')
79
80
        if timestamp:
81
            timestamp = datetime.strptime(timestamp, '%Y-%m-%dT%H:%M:%S.%f')
82
83
        # Construct `BackupRevision` object
84
        return cls(
85
            timestamp,
86
            metadata.pop('contents'),
87
88
            tag=metadata.pop('tag', None),
89
            attributes=metadata,
90
            path=path
91
        )
92
93 1
    def save(self, path):
94 1
        log.debug('Writing backup revision metadata to %r', path)
95
96
        # Write revision metadata to disk
97 1
        with open(path, 'wb') as fp:
98 1
            json.dump(self.dict(), fp, default=json_date_serializer)
99
100
        # Update current revision path
101 1
        self.path = path
102
103 1
    def __repr__(self):
104
        properties = []
105
106
        if self.timestamp:
107
            properties.append(('timestamp', self.timestamp.isoformat()))
108
109
        if self.tag:
110
            properties.append(('tag', self.tag))
111
112
        if self.path:
113
            properties.append(('path', self.path))
114
115
        return '<BackupRevision %s>' % (
116
            ', '.join([
117
                '%s: %r' % (key, value)
118
                for key, value in properties
119
            ])
120
        )
121