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

DatabaseBackupSource.backup()   B

Complexity

Conditions 3

Size

Total Lines 46

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 17
CRAP Score 3.0105
Metric Value
cc 3
dl 0
loc 46
ccs 17
cts 19
cp 0.8947
crap 3.0105
rs 8.9411
1 1
from plugin.core.backup.sources.base import BackupSource
2 1
from plugin.core.backup.models import BackupRevision
3 1
from plugin.core.helpers.database import db_connect, db_connection
4
5 1
from datetime import datetime
6 1
import logging
7 1
import os
8
9 1
log = logging.getLogger(__name__)
10
11
12 1
class DatabaseBackupSource(BackupSource):
13 1
    @classmethod
14 1
    def backup(cls, group, database, tag=None, metadata=None):
15 1
        timestamp = datetime.now()
16
17
        # Build backup directory/name
18 1
        directory, name, path = cls.path(group, timestamp, tag)
19 1
        destination_path = path + '.db'
20
21
        # Ensure directory exists
22 1
        if not os.path.exists(directory):
23 1
            os.makedirs(directory)
24
25 1
        log.info('[%s] Backing up database to %r', group, destination_path)
26
27
        # Backup database
28 1
        destination = db_connect(destination_path, 'raw')
29
30
        # Get `database` connection
31 1
        source = db_connection(database)
32
33
        # Copy `source` database to `destination`
34 1
        try:
35 1
            cls._copy(group, source, destination)
36
        finally:
37
            # Close `destination` database
38 1
            destination.close()
39
40
        # Ensure path exists
41 1
        if not os.path.exists(destination_path):
42
            log.error('Backup failed (file doesn\'t exist)')
43
            return False
44
45
        # Construct revision
46 1
        revision = BackupRevision(
47
            timestamp, [
48
                name + '.db'
49
            ],
50
51
            tag=tag,
52
            attributes=metadata or {}
53
        )
54
55
        # Write backup metadata
56 1
        revision.save(path + '.bre')
57
58 1
        return True
59
60 1
    @classmethod
61
    def _copy(cls, group, source, destination):
62 1
        with destination.backup('main', source, 'main') as b:
63
            # Run until backup is completed
64 1
            while not b.done:
65 1
                b.step(100)
66
67
                # Report progress
68 1
                progress = float(b.pagecount - b.remaining) / b.pagecount
69
70
                log.debug('[%s] Backup Progress: %3d%%', group, progress * 100)
71