dirutility.backup.ZipBackup._backup_pb_tqdm()   A
last analyzed

Complexity

Conditions 3

Size

Total Lines 5
Code Lines 4

Duplication

Lines 5
Ratio 100 %

Importance

Changes 0
Metric Value
cc 3
eloc 4
nop 2
dl 5
loc 5
rs 10
c 0
b 0
f 0
1
# Copies an entire folder and its contents into a zip file whose filename increments.
2
import os
3
import shutil
4
from zipfile import ZipFile
5
6
from tqdm import tqdm
7
8
from dirutility.walk import DirPaths
9
10
11 View Code Duplication
class ZipBackup:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
12
13
    def __init__(self, source, destination=None, compress_level=0, delete_source=False, overwrite=False):
14
        """
15
        Create zip file backup of a directory.
16
17
        Backup the entire contents of "source" into a zip file.
18
        or
19
        Backup all "source" files to destination zip file.
20
21
        :param source: Source folder path or iterable of paths
22
        :param destination: Defaults source parent directory
23
        :param compress_level: Compression level
24
        """
25
        # TODO: Add multiprocessing support
26
        self.compress_level = compress_level
27
        self.delete_source = delete_source
28
        self.overwrite = overwrite
29
        self.source, self.zip_filename = self._set_paths(source, destination)
30
31
    def __call__(self, *args, **kwargs):
32
        self.backup()
33
        return self.zip_filename
34
35
    def __str__(self):
36
        return self.zip_filename
37
38
    @staticmethod
39
    def _resolve_file_name(source, destination):
40
        """Create a filename for the destination zip file."""
41
        number = 1
42
        if os.path.exists(os.path.join(destination, os.path.basename(source) + '.zip')):
43
            while True:
44
                zip_filename = os.path.join(destination, os.path.basename(source) + '_' + str(number) + '.zip')
45
                if not os.path.exists(zip_filename):
46
                    break
47
                number = number + 1
48
        else:
49
            zip_filename = os.path.join(destination, os.path.basename(source) + '.zip')
50
        return zip_filename
51
52
    def _set_paths(self, source, destination):
53
        # make sure folder is absolute
54
        source = os.path.abspath(source)
55
56
        # Set destination to next to source folder if not manually set
57
        if not destination:
58
            destination = os.path.dirname(source)
59
60
        # Create new file_name
61
        if not self.overwrite:
62
            zip_filename = self._resolve_file_name(source, destination)
63
        else:
64
            zip_filename = os.path.join(destination, os.path.basename(source) + '.zip')
65
            if os.path.exists(zip_filename):
66
                os.remove(zip_filename)
67
68
        return source, zip_filename
69
70
    def _get_paths(self):
71
        return DirPaths(self.source, full_paths=True).walk()
72
73
    def _backup_compresslevel(self, dirs):
74
        """Create a backup file with a compresslevel parameter."""
75
        # Only supported in Python 3.7+
76
        with ZipFile(self.zip_filename, 'w', compresslevel=self.compress_level) as backup_zip:
77
            for path in tqdm(dirs, desc='Writing Zip Files', total=len(dirs)):
78
                backup_zip.write(path, path[len(self.source):len(path)])
79
80
    def _backup_pb_gui(self, dirs):
81
        """Create a zip backup with a GUI progress bar."""
82
        import PySimpleGUI as sg
83
        # Legacy support
84
        with ZipFile(self.zip_filename, 'w') as backup_zip:
85
            for count, path in enumerate(dirs):
86
                backup_zip.write(path, path[len(self.source):len(path)])
87
                if not sg.OneLineProgressMeter('Writing Zip Files', count + 1, len(dirs) - 1, 'Files'):
88
                    break
89
90
    def _backup_pb_tqdm(self, dirs):
91
        """Create a backup with a tqdm progress bar."""
92
        with ZipFile(self.zip_filename, 'w') as backup_zip:
93
            for path in tqdm(dirs, desc='Writing Zip Files', total=len(dirs)):
94
                backup_zip.write(path, path[len(self.source):len(path)])
95
96
    def backup(self, paths=None):
97
        """Backup method driver."""
98
        if not paths:
99
            paths = self._get_paths()
100
101
        try:
102
            self._backup_compresslevel(paths)
103
        except TypeError:
104
            try:
105
                self._backup_pb_gui(paths)
106
            except ImportError:
107
                self._backup_pb_tqdm(paths)
108
109
        # Delete source if specified
110
        if self.delete_source:
111
            shutil.rmtree(self.source)
112
        return self.zip_filename
113
114
115 View Code Duplication
def main():
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
116
    try:
117
        from dirutility.gui import BackupZipGUI
118
        root = BackupZipGUI().source
119
        ZipBackup(root).backup()
120
    except ImportError:
121
        print('**pip install PySimpleGUI to run BackupZipGUI module**')
122
        from argparse import ArgumentParser
123
124
        # Declare argparse argument descriptions
125
        usage = 'ZipBackup your files'
126
        description = 'Create a zip backup of a file or directory.'
127
        helpers = {
128
            'files': "Input paths you would like to zip",
129
        }
130
131
        # construct the argument parse and parse the arguments
132
        ap = ArgumentParser(usage=usage, description=description)
133
        ap.add_argument('files', help=helpers['files'], nargs='+')
134
        args = vars(ap.parse_args())
135
136
        for f in args['files']:
137
            ZipBackup(f).backup()
138
139
140
if __name__ == "__main__":
141
    main()
142