• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

smartondev / gwbackupy / 7dfccd0c-e35b-4402-8ef2-fef38193a0b7

pending completion
7dfccd0c-e35b-4402-8ef2-fef38193a0b7

Pull #55

circleci

Márton Somogyi
#24
Pull Request #55: #24 storage add content hash property

38 of 38 new or added lines in 2 files covered. (100.0%)

668 of 1249 relevant lines covered (53.48%)

0.53 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

17.89
/gwbackupy/gwbackupy_cli.py
1
import argparse
1✔
2
import logging
1✔
3
import sys
1✔
4
import threading
1✔
5

6
import pytz as pytz
1✔
7
from tzlocal import get_localzone
1✔
8

9
import gwbackupy.global_properties as global_properties
1✔
10
from gwbackupy.filters.gmail_filter import GmailFilter
1✔
11
from gwbackupy.gmail import Gmail
1✔
12
from gwbackupy.helpers import parse_date
1✔
13
from gwbackupy.providers.gapi_gmail_service_wrapper import GapiGmailServiceWrapper
1✔
14
from gwbackupy.providers.gmail_service_provider import GmailServiceProvider
1✔
15
from gwbackupy.storage.file_storage import FileStorage
1✔
16

17
lock = threading.Lock()
1✔
18

19

20
def parse_arguments() -> argparse.Namespace:
1✔
21
    log_levels = {
×
22
        "finest": global_properties.log_finest,
23
        "debug": logging.DEBUG,
24
        "info": logging.INFO,
25
        "warning": logging.WARN,
26
        "error": logging.ERROR,
27
        "critical": logging.CRITICAL,
28
    }
29

30
    parser = argparse.ArgumentParser(
×
31
        description="Google Workspace Backup Tool " + global_properties.version,
32
        add_help=False,
33
    )
34
    parser.set_defaults(feature=True)
×
35
    parser.add_argument(
×
36
        "-h",
37
        "--help",
38
        action="help",
39
        default=argparse.SUPPRESS,
40
        help="Show this help message and exit.",
41
    )
42
    parser.add_argument(
×
43
        "--dry", default=False, help="Run in dry mode", action="store_true"
44
    )
45
    parser.add_argument(
×
46
        "--timezone",
47
        type=lambda s: pytz.timezone(s),
48
        help="time zone",
49
        default=get_localzone(),
50
    )
51
    parser.add_argument(
×
52
        "--log-level",
53
        type=str.lower,
54
        help="Logging level: {keys}".format(keys=", ".join(log_levels.keys())),
55
        default="info",
56
        choices=log_levels,
57
    )
58
    parser.add_argument("--batch-size", type=int, help="Concurrent threads", default=5)
×
59
    parser.add_argument(
×
60
        "--service-account-email",
61
        type=str,
62
        default=None,
63
        help="Email of the service account (required for p12 keyfile)",
64
    )
65
    parser.add_argument(
×
66
        "--service-account-key-filepath",
67
        type=str,
68
        help="Path to the service account key file",
69
        required=False,
70
    )
71
    parser.add_argument(
×
72
        "--credentials-filepath",
73
        type=str,
74
        help="Path to the credentials file",
75
        required=False,
76
    )
77
    parser.add_argument(
×
78
        "--workdir",
79
        type=str,
80
        help="Path to the workdir",
81
        required=False,
82
        default="./data",
83
    )
84
    service_parser = parser.add_subparsers(dest="service")
×
85
    gmail_parser = service_parser.add_parser("gmail", help="GMail service commands")
×
86
    gmail_command_parser = gmail_parser.add_subparsers(dest="command")
×
87

88
    gmail_backup_parser = gmail_command_parser.add_parser("backup", help="Backup gmail")
×
89
    gmail_backup_parser.add_argument(
×
90
        "--email", type=str, help="Email of the account", required=True
91
    )
92
    gmail_backup_parser.add_argument(
×
93
        "--quick-sync-days",
94
        type=int,
95
        default=None,
96
        help="Quick sync number of days back. (It does not delete messages from local "
97
        "storage.)",
98
    )
99

100
    gmail_restore_parser = gmail_command_parser.add_parser(
×
101
        "restore", help="Restore gmail"
102
    )
103
    gmail_restore_parser.add_argument(
×
104
        "--email", type=str, help="Email from which restore", required=True
105
    )
106
    gmail_restore_parser.add_argument(
×
107
        "--to-email",
108
        type=str,
109
        help="Destination email account, if not specified, then --email is used",
110
    )
111
    gmail_restore_parser.add_argument(
×
112
        "--add-label",
113
        type=str,
114
        action="append",
115
        help="Add label to restored emails",
116
        default=None,
117
        dest="add_labels",
118
    )
119
    gmail_restore_parser.add_argument(
×
120
        "--restore-deleted",
121
        help="Restore deleted emails",
122
        default=False,
123
        action="store_true",
124
    )
125
    gmail_restore_parser.add_argument(
×
126
        "--restore-missing",
127
        help="Restore missing emails",
128
        default=False,
129
        action="store_true",
130
    )
131
    gmail_restore_parser.add_argument(
×
132
        "--filter-date-from",
133
        type=str,
134
        help="Filter date from (inclusive, format: yyyy-mm-dd or yyyy-mm-dd hh:mm:ss)",
135
        default=None,
136
    )
137
    gmail_restore_parser.add_argument(
×
138
        "--filter-date-to",
139
        type=str,
140
        help="Filter date to (exclusive, format: yyyy-mm-dd or yyyy-mm-dd hh:mm:ss)",
141
        default=None,
142
    )
143
    if len(sys.argv) == 1 or "--help" in sys.argv:
×
144
        parser.print_help(sys.stderr)
×
145
        sys.exit(1)
×
146
    args = parser.parse_args(args=sys.argv[1:])
×
147
    Log_Format = "%(levelname)s %(asctime)s - %(message)s"
×
148
    logging.addLevelName(global_properties.log_finest, "FINEST")
×
149
    logging.basicConfig(
×
150
        # filename="logfile.log",
151
        stream=sys.stdout,
152
        filemode="w",
153
        format=Log_Format,
154
        level=log_levels[args.log_level],
155
    )
156
    if (
×
157
        args.credentials_filepath is None and args.service_account_key_filepath is None
158
    ) or (
159
        args.credentials_filepath is not None
160
        and args.service_account_key_filepath is not None
161
    ):
162
        parser.error(
×
163
            "at least one of --credentials-filepath and --service-account-key-filepath required"
164
        )
165
    return args
×
166

167

168
def cli_startup():
1✔
169
    try:
×
170
        args = parse_arguments()
×
171
        if args.service == "gmail":
×
172
            storage = FileStorage(args.workdir + "/" + args.email + "/gmail")
×
173
            service_provider = GmailServiceProvider(
×
174
                credentials_file_path=args.credentials_filepath,
175
                service_account_email=args.service_account_email,
176
                service_account_file_path=args.service_account_key_filepath,
177
                storage=storage,
178
            )
179
            service_wrapper = GapiGmailServiceWrapper(
×
180
                service_provider=service_provider,
181
                dry_mode=args.dry,
182
            )
183
            gmail = Gmail(
×
184
                email=args.email,
185
                service_wrapper=service_wrapper,
186
                batch_size=args.batch_size,
187
                storage=storage,
188
                dry_mode=args.dry,
189
            )
190
            if args.command == "backup":
×
191
                if gmail.backup(quick_sync_days=args.quick_sync_days):
×
192
                    exit(0)
×
193
                else:
194
                    exit(1)
×
195
            if args.command == "restore":
×
196
                if args.add_labels is None:
×
197
                    args.add_labels = ["gwbackupy"]
×
198
                item_filter = GmailFilter()
×
199
                if args.restore_deleted:
×
200
                    item_filter.is_deleted()
×
201
                    logging.info("Filter options: deleted")
×
202
                if args.restore_missing:
×
203
                    item_filter.is_missing()
×
204
                    logging.info("Filter options: missing")
×
205
                if args.filter_date_from is not None:
×
206
                    dt = parse_date(args.filter_date_from, args.timezone)
×
207
                    item_filter.date_from(dt)
×
208
                    logging.info(f"Filter options: date from {dt}")
×
209
                if args.filter_date_to is not None:
×
210
                    dt = parse_date(args.filter_date_to, args.timezone)
×
211
                    item_filter.date_to(dt)
×
212
                    logging.info(f"Filter options: date to {dt}")
×
213
                if gmail.restore(
×
214
                    to_email=args.to_email,
215
                    item_filter=item_filter,
216
                    restore_deleted=args.restore_deleted,
217
                    restore_missing=args.restore_missing,
218
                    add_labels=args.add_labels,
219
                ):
220
                    exit(0)
×
221
                else:
222
                    exit(1)
×
223
            else:
224
                raise Exception("Unknown command")
×
225
    except KeyboardInterrupt:
×
226
        logging.warning("Process is interrupted")
×
227
        exit(1)
×
228
    except SystemExit as e:
×
229
        exit(e.code)
×
230
    except BaseException:
×
231
        logging.exception("CLI startup/run failed")
×
232
        exit(1)
×
233

234

235
if __name__ == "__main__":
1✔
236
    cli_startup()
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc