halib 0.2.30__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- halib/__init__.py +94 -0
- halib/common/__init__.py +0 -0
- halib/common/common.py +326 -0
- halib/common/rich_color.py +285 -0
- halib/common.py +151 -0
- halib/csvfile.py +48 -0
- halib/cuda.py +39 -0
- halib/dataset.py +209 -0
- halib/exp/__init__.py +0 -0
- halib/exp/core/__init__.py +0 -0
- halib/exp/core/base_config.py +167 -0
- halib/exp/core/base_exp.py +147 -0
- halib/exp/core/param_gen.py +170 -0
- halib/exp/core/wandb_op.py +117 -0
- halib/exp/data/__init__.py +0 -0
- halib/exp/data/dataclass_util.py +41 -0
- halib/exp/data/dataset.py +208 -0
- halib/exp/data/torchloader.py +165 -0
- halib/exp/perf/__init__.py +0 -0
- halib/exp/perf/flop_calc.py +190 -0
- halib/exp/perf/gpu_mon.py +58 -0
- halib/exp/perf/perfcalc.py +470 -0
- halib/exp/perf/perfmetrics.py +137 -0
- halib/exp/perf/perftb.py +778 -0
- halib/exp/perf/profiler.py +507 -0
- halib/exp/viz/__init__.py +0 -0
- halib/exp/viz/plot.py +754 -0
- halib/filesys.py +117 -0
- halib/filetype/__init__.py +0 -0
- halib/filetype/csvfile.py +192 -0
- halib/filetype/ipynb.py +61 -0
- halib/filetype/jsonfile.py +19 -0
- halib/filetype/textfile.py +12 -0
- halib/filetype/videofile.py +266 -0
- halib/filetype/yamlfile.py +87 -0
- halib/gdrive.py +179 -0
- halib/gdrive_mkdir.py +41 -0
- halib/gdrive_test.py +37 -0
- halib/jsonfile.py +22 -0
- halib/listop.py +13 -0
- halib/online/__init__.py +0 -0
- halib/online/gdrive.py +229 -0
- halib/online/gdrive_mkdir.py +53 -0
- halib/online/gdrive_test.py +50 -0
- halib/online/projectmake.py +131 -0
- halib/online/tele_noti.py +165 -0
- halib/plot.py +301 -0
- halib/projectmake.py +115 -0
- halib/research/__init__.py +0 -0
- halib/research/base_config.py +100 -0
- halib/research/base_exp.py +157 -0
- halib/research/benchquery.py +131 -0
- halib/research/core/__init__.py +0 -0
- halib/research/core/base_config.py +144 -0
- halib/research/core/base_exp.py +157 -0
- halib/research/core/param_gen.py +108 -0
- halib/research/core/wandb_op.py +117 -0
- halib/research/data/__init__.py +0 -0
- halib/research/data/dataclass_util.py +41 -0
- halib/research/data/dataset.py +208 -0
- halib/research/data/torchloader.py +165 -0
- halib/research/dataset.py +208 -0
- halib/research/flop_csv.py +34 -0
- halib/research/flops.py +156 -0
- halib/research/metrics.py +137 -0
- halib/research/mics.py +74 -0
- halib/research/params_gen.py +108 -0
- halib/research/perf/__init__.py +0 -0
- halib/research/perf/flop_calc.py +190 -0
- halib/research/perf/gpu_mon.py +58 -0
- halib/research/perf/perfcalc.py +363 -0
- halib/research/perf/perfmetrics.py +137 -0
- halib/research/perf/perftb.py +778 -0
- halib/research/perf/profiler.py +301 -0
- halib/research/perfcalc.py +361 -0
- halib/research/perftb.py +780 -0
- halib/research/plot.py +758 -0
- halib/research/profiler.py +300 -0
- halib/research/torchloader.py +162 -0
- halib/research/viz/__init__.py +0 -0
- halib/research/viz/plot.py +754 -0
- halib/research/wandb_op.py +116 -0
- halib/rich_color.py +285 -0
- halib/sys/__init__.py +0 -0
- halib/sys/cmd.py +8 -0
- halib/sys/filesys.py +124 -0
- halib/system/__init__.py +0 -0
- halib/system/_list_pc.csv +6 -0
- halib/system/cmd.py +8 -0
- halib/system/filesys.py +164 -0
- halib/system/path.py +106 -0
- halib/tele_noti.py +166 -0
- halib/textfile.py +13 -0
- halib/torchloader.py +162 -0
- halib/utils/__init__.py +0 -0
- halib/utils/dataclass_util.py +40 -0
- halib/utils/dict.py +317 -0
- halib/utils/dict_op.py +9 -0
- halib/utils/gpu_mon.py +58 -0
- halib/utils/list.py +17 -0
- halib/utils/listop.py +13 -0
- halib/utils/slack.py +86 -0
- halib/utils/tele_noti.py +166 -0
- halib/utils/video.py +82 -0
- halib/videofile.py +139 -0
- halib-0.2.30.dist-info/METADATA +237 -0
- halib-0.2.30.dist-info/RECORD +110 -0
- halib-0.2.30.dist-info/WHEEL +5 -0
- halib-0.2.30.dist-info/licenses/LICENSE.txt +17 -0
- halib-0.2.30.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import time
|
|
2
|
+
import networkx as nx
|
|
3
|
+
from rich import inspect
|
|
4
|
+
from rich.pretty import pprint
|
|
5
|
+
from rich.console import Console
|
|
6
|
+
|
|
7
|
+
from omegaconf import OmegaConf
|
|
8
|
+
from argparse import ArgumentParser
|
|
9
|
+
|
|
10
|
+
from ..system.path import *
|
|
11
|
+
|
|
12
|
+
console = Console()
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def _load_yaml_recursively(
|
|
16
|
+
yaml_file, yaml_files=[], share_nx_graph=nx.DiGraph(), log_info=False
|
|
17
|
+
):
|
|
18
|
+
conf = OmegaConf.load(yaml_file)
|
|
19
|
+
yaml_files.append(yaml_file)
|
|
20
|
+
if "__base__" in conf:
|
|
21
|
+
parent = conf["__base__"]
|
|
22
|
+
if isinstance(parent, str):
|
|
23
|
+
parent = [parent]
|
|
24
|
+
for p in parent:
|
|
25
|
+
edge = (yaml_file, p)
|
|
26
|
+
share_nx_graph.add_edge(*edge)
|
|
27
|
+
for cycle in nx.simple_cycles(share_nx_graph):
|
|
28
|
+
assert False, f"Cyclic dependency detected: {cycle}"
|
|
29
|
+
# update conf with parent; BY loading parent and merging with conf (the child)
|
|
30
|
+
conf = OmegaConf.merge(
|
|
31
|
+
_load_yaml_recursively(p, yaml_files, share_nx_graph), conf
|
|
32
|
+
)
|
|
33
|
+
if log_info:
|
|
34
|
+
console.rule()
|
|
35
|
+
console.print(f"current yaml_file: {yaml_file}")
|
|
36
|
+
inspect(yaml_files)
|
|
37
|
+
pprint(OmegaConf.to_container(conf, resolve=True))
|
|
38
|
+
time.sleep(1)
|
|
39
|
+
return conf
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def load_yaml(yaml_file, to_dict=False, log_info=False):
|
|
43
|
+
yaml_files = []
|
|
44
|
+
share_nx_graph = nx.DiGraph()
|
|
45
|
+
omgconf = _load_yaml_recursively(
|
|
46
|
+
yaml_file,
|
|
47
|
+
yaml_files=yaml_files,
|
|
48
|
+
share_nx_graph=share_nx_graph,
|
|
49
|
+
log_info=log_info,
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
if to_dict:
|
|
53
|
+
return OmegaConf.to_container(omgconf, resolve=True)
|
|
54
|
+
else:
|
|
55
|
+
return omgconf
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def load_yaml_with_PC_abbr(
|
|
59
|
+
yaml_file, abbr_disk_map=ABBR_DISK_MAP
|
|
60
|
+
):
|
|
61
|
+
# load yaml file
|
|
62
|
+
data_dict = load_yaml(yaml_file=yaml_file, to_dict=True)
|
|
63
|
+
# Normalize paths in the loaded data
|
|
64
|
+
data_dict = normalize_paths(
|
|
65
|
+
data_dict, get_working_disk(abbr_disk_map), get_os_platform()
|
|
66
|
+
)
|
|
67
|
+
return data_dict
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def parse_args():
|
|
71
|
+
parser = ArgumentParser(description="desc text")
|
|
72
|
+
parser.add_argument(
|
|
73
|
+
"-cfg", "--cfg", type=str, help="cfg file", default="cfg__default.yaml"
|
|
74
|
+
)
|
|
75
|
+
return parser.parse_args()
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def main():
|
|
79
|
+
args = parse_args()
|
|
80
|
+
cfg_file = args.cfg
|
|
81
|
+
cfg = load_yaml(cfg_file, to_dict=True)
|
|
82
|
+
console.rule()
|
|
83
|
+
pprint(cfg)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
if __name__ == "__main__":
|
|
87
|
+
main()
|
halib/gdrive.py
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Upload folder to Google Drive
|
|
5
|
+
"""
|
|
6
|
+
import ast
|
|
7
|
+
import os
|
|
8
|
+
|
|
9
|
+
import googleapiclient.errors
|
|
10
|
+
# Import Google libraries
|
|
11
|
+
from pydrive.auth import GoogleAuth
|
|
12
|
+
from pydrive.drive import GoogleDrive
|
|
13
|
+
from pydrive.files import GoogleDriveFileList
|
|
14
|
+
|
|
15
|
+
from halib.system import filesys
|
|
16
|
+
from halib.filetype import textfile
|
|
17
|
+
|
|
18
|
+
# Import general libraries
|
|
19
|
+
|
|
20
|
+
ggDrive = None
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def get_gg_drive(settings_file='settings.yaml'):
|
|
24
|
+
"""
|
|
25
|
+
Authenticate to Google API
|
|
26
|
+
"""
|
|
27
|
+
global ggDrive
|
|
28
|
+
if ggDrive is None:
|
|
29
|
+
ggAuth = GoogleAuth(settings_file=settings_file)
|
|
30
|
+
ggDrive = GoogleDrive(ggAuth)
|
|
31
|
+
return ggDrive
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def get_folder_id(gg_parent_folder_id, folder_name):
|
|
35
|
+
"""
|
|
36
|
+
Check if destination folder exists and return it's ID
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
# Auto-iterate through all files in the parent folder.
|
|
40
|
+
drive = get_gg_drive()
|
|
41
|
+
file_list = GoogleDriveFileList()
|
|
42
|
+
try:
|
|
43
|
+
file_list = drive.ListFile(
|
|
44
|
+
{'q': "'{0}' in parents and trashed=false".format(gg_parent_folder_id)}
|
|
45
|
+
).GetList()
|
|
46
|
+
# Exit if the parent folder doesn't exist
|
|
47
|
+
except googleapiclient.errors.HttpError as err:
|
|
48
|
+
# Parse error message
|
|
49
|
+
message = ast.literal_eval(err.content)['error']['message']
|
|
50
|
+
if message == 'File not found: ':
|
|
51
|
+
print(message + folder_name)
|
|
52
|
+
exit(1)
|
|
53
|
+
# Exit with stacktrace in case of other error
|
|
54
|
+
else:
|
|
55
|
+
raise
|
|
56
|
+
|
|
57
|
+
# Find the the destination folder in the parent folder's files
|
|
58
|
+
for file1 in file_list:
|
|
59
|
+
if file1['title'] == folder_name:
|
|
60
|
+
print('title: %s, id: %s' % (file1['title'], file1['id']))
|
|
61
|
+
return file1['id']
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def create_folder(folder_name, gg_parent_folder_id):
|
|
65
|
+
"""
|
|
66
|
+
Create folder on Google Drive
|
|
67
|
+
"""
|
|
68
|
+
|
|
69
|
+
folder_metadata = {
|
|
70
|
+
'title': folder_name,
|
|
71
|
+
# Define the file type as folder
|
|
72
|
+
'mimeType': 'application/vnd.google-apps.folder',
|
|
73
|
+
# ID of the parent folder
|
|
74
|
+
'parents': [{"kind": "drive#fileLink", "id": gg_parent_folder_id}]
|
|
75
|
+
}
|
|
76
|
+
drive = get_gg_drive()
|
|
77
|
+
folder = drive.CreateFile(folder_metadata)
|
|
78
|
+
folder.Upload()
|
|
79
|
+
|
|
80
|
+
# Return folder information
|
|
81
|
+
# print('title: %s, id: %s' % (folder['title'], folder['id']))
|
|
82
|
+
return folder['id']
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def is_in_ignore_list(local_path, ignore_list=None):
|
|
86
|
+
in_ignore_list = False
|
|
87
|
+
if ignore_list:
|
|
88
|
+
for path in ignore_list:
|
|
89
|
+
if path in local_path:
|
|
90
|
+
in_ignore_list = True
|
|
91
|
+
break
|
|
92
|
+
return in_ignore_list
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def upload_file(local_file_path, gg_folder_id, ignore_list=None):
|
|
96
|
+
"""
|
|
97
|
+
Upload local file to Google Drive folder
|
|
98
|
+
"""
|
|
99
|
+
drive = get_gg_drive()
|
|
100
|
+
if not is_in_ignore_list(local_file_path, ignore_list):
|
|
101
|
+
print('uploading ' + local_file_path)
|
|
102
|
+
# Upload file to folder.
|
|
103
|
+
title = filesys.get_file_name(local_file_path, split_file_ext=False)
|
|
104
|
+
|
|
105
|
+
# delete file if exist on gg folder
|
|
106
|
+
query = f"'{gg_folder_id}' in parents and trashed=false"
|
|
107
|
+
file_list = drive.ListFile({'q': f"{query}"}).GetList()
|
|
108
|
+
for file in file_list:
|
|
109
|
+
if file['title'] == title:
|
|
110
|
+
print(f'[DELETE] {title} on Google Drive')
|
|
111
|
+
file.Delete()
|
|
112
|
+
break
|
|
113
|
+
|
|
114
|
+
f = drive.CreateFile(
|
|
115
|
+
{"title": f"{title}",
|
|
116
|
+
"parents": [{"kind": "drive#fileLink", "id": gg_folder_id}]})
|
|
117
|
+
f.SetContentFile(local_file_path)
|
|
118
|
+
f.Upload()
|
|
119
|
+
# Skip the file if it's empty
|
|
120
|
+
else:
|
|
121
|
+
print('file {0} is empty or in ignore list'.format(local_file_path))
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def recursive_walk_and_upload(local_folder_path, gg_folder_id,
|
|
125
|
+
processed_path, ignore_list=None):
|
|
126
|
+
for root, sub_folders, files in os.walk(local_folder_path):
|
|
127
|
+
# already processed folder
|
|
128
|
+
if root in processed_path:
|
|
129
|
+
print(f'[SKIP] already processed folder {root}')
|
|
130
|
+
return
|
|
131
|
+
print(f'\n\n[RECURSIVE] {local_folder_path}, {gg_folder_id}')
|
|
132
|
+
print(f'[FF] {root} {sub_folders} {files}')
|
|
133
|
+
if sub_folders:
|
|
134
|
+
for sub_folder in sub_folders:
|
|
135
|
+
sub_folder_path = os.path.join(root, sub_folder)
|
|
136
|
+
print(f'process {sub_folder_path}')
|
|
137
|
+
if is_in_ignore_list(sub_folder_path, ignore_list):
|
|
138
|
+
continue
|
|
139
|
+
# Get destination folder ID
|
|
140
|
+
gg_sub_folder_id = get_folder_id(gg_folder_id, sub_folder)
|
|
141
|
+
# Create the folder if it doesn't exists
|
|
142
|
+
if not gg_sub_folder_id:
|
|
143
|
+
print('creating folder ' + sub_folder)
|
|
144
|
+
gg_sub_folder_id = create_folder(sub_folder, gg_folder_id)
|
|
145
|
+
recursive_walk_and_upload(sub_folder_path, gg_sub_folder_id,
|
|
146
|
+
processed_path, ignore_list)
|
|
147
|
+
if files:
|
|
148
|
+
for file in files:
|
|
149
|
+
filePath = os.path.join(root, file)
|
|
150
|
+
upload_file(filePath, gg_folder_id, ignore_list)
|
|
151
|
+
processed_path.append(root)
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
def upload_folder_to_drive(local_folder, gg_folder_id,
|
|
155
|
+
content_only=True,
|
|
156
|
+
ignore_file=None):
|
|
157
|
+
"""
|
|
158
|
+
Upload folder to Google Drive folder
|
|
159
|
+
bool content_only: if true, we only upload files and folder inside local_folder
|
|
160
|
+
else create a folder with the same name of the local folder and upload all files and folders
|
|
161
|
+
in the local folder to it
|
|
162
|
+
"""
|
|
163
|
+
|
|
164
|
+
ignore_list = None
|
|
165
|
+
if ignore_file:
|
|
166
|
+
if filesys.is_file(ignore_file):
|
|
167
|
+
ignore_list = textfile.read_line_by_line(ignore_file)
|
|
168
|
+
ignore_list = [os.path.normpath(path) for path in ignore_list]
|
|
169
|
+
|
|
170
|
+
if content_only is False:
|
|
171
|
+
folder_name = filesys.get_dir_name(local_folder)
|
|
172
|
+
gg_folder_id_to_upload = create_folder(folder_name, gg_folder_id)
|
|
173
|
+
else:
|
|
174
|
+
gg_folder_id_to_upload = gg_folder_id
|
|
175
|
+
|
|
176
|
+
processed_path = []
|
|
177
|
+
local_folder = os.path.normpath(local_folder)
|
|
178
|
+
recursive_walk_and_upload(local_folder, gg_folder_id_to_upload,
|
|
179
|
+
processed_path, ignore_list)
|
halib/gdrive_mkdir.py
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
from argparse import ArgumentParser
|
|
2
|
+
from datetime import datetime
|
|
3
|
+
|
|
4
|
+
from halib.online import gdrive
|
|
5
|
+
from halib.filetype import textfile
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def parse_args():
|
|
9
|
+
parser = ArgumentParser(
|
|
10
|
+
description="Upload local folder to Google Drive")
|
|
11
|
+
parser.add_argument('-a', '--authFile', type=str,
|
|
12
|
+
help='authenticate file to Google Drive', default='settings.yaml')
|
|
13
|
+
parser.add_argument('-g', '--GDriveParentFolder', type=str,
|
|
14
|
+
help='Destination parent folder ID in Google Drive')
|
|
15
|
+
parser.add_argument('-n', '--folderName', type=str,
|
|
16
|
+
help='name of the folder which is about to be created',
|
|
17
|
+
default='untitled')
|
|
18
|
+
return parser.parse_args()
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def main():
|
|
22
|
+
args = parse_args()
|
|
23
|
+
auth_file = args.authFile
|
|
24
|
+
gDrive_parent_folder_id = args.GDriveParentFolder
|
|
25
|
+
folder_name = args.folderName
|
|
26
|
+
|
|
27
|
+
if folder_name == 'untitled':
|
|
28
|
+
folder_name = datetime.today().strftime('%Y.%m.%d_%Hh%M')
|
|
29
|
+
else:
|
|
30
|
+
date_str = datetime.today().strftime('%Y.%m.%d_%Hh%M')
|
|
31
|
+
folder_name = f'{date_str}_{folder_name}'
|
|
32
|
+
|
|
33
|
+
print(f'[GDrive] creating {folder_name} in GDrive folder {gDrive_parent_folder_id}')
|
|
34
|
+
|
|
35
|
+
gdrive.get_gg_drive(auth_file)
|
|
36
|
+
folder_id = gdrive.create_folder(folder_name, gDrive_parent_folder_id)
|
|
37
|
+
textfile.write([folder_id], './GDriveFolder.txt')
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
if __name__ == "__main__":
|
|
41
|
+
main()
|
halib/gdrive_test.py
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
from argparse import ArgumentParser
|
|
2
|
+
|
|
3
|
+
from halib.online import gdrive
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def parse_args():
|
|
7
|
+
parser = ArgumentParser(
|
|
8
|
+
description="Upload local folder to Google Drive")
|
|
9
|
+
parser.add_argument('-a', '--authFile', type=str,
|
|
10
|
+
help='authenticate file to Google Drive', default='settings.yaml')
|
|
11
|
+
parser.add_argument('-s', '--source', type=str,
|
|
12
|
+
help='Folder to upload')
|
|
13
|
+
parser.add_argument('-d', '--destination', type=str,
|
|
14
|
+
help='Destination folder ID in Google Drive')
|
|
15
|
+
parser.add_argument('-c', '--contentOnly', type=str,
|
|
16
|
+
help='Parent Folder in Google Drive', default="True")
|
|
17
|
+
parser.add_argument('-i', '--ignoreFile', type=str,
|
|
18
|
+
help='file containing files/folders to ignore', default=None)
|
|
19
|
+
|
|
20
|
+
return parser.parse_args()
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def main():
|
|
24
|
+
args = parse_args()
|
|
25
|
+
auth_file = args.authFile
|
|
26
|
+
local_folder = args.source
|
|
27
|
+
gg_folder_id = args.destination
|
|
28
|
+
content_only = (args.contentOnly.lower() == "true")
|
|
29
|
+
ignore_file = args.ignoreFile
|
|
30
|
+
gdrive.get_gg_drive(auth_file)
|
|
31
|
+
gdrive.upload_folder_to_drive(local_folder, gg_folder_id,
|
|
32
|
+
content_only=content_only,
|
|
33
|
+
ignore_file=ignore_file)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
if __name__ == "__main__":
|
|
37
|
+
main()
|
halib/jsonfile.py
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import json
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def read(file):
|
|
5
|
+
with open(file) as f:
|
|
6
|
+
data = json.load(f)
|
|
7
|
+
return data
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def write(data_dict, outfile):
|
|
11
|
+
with open(outfile, 'w') as json_file:
|
|
12
|
+
json.dump(data_dict, json_file)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def beautify(json_str):
|
|
16
|
+
formatted_json = json_str
|
|
17
|
+
try:
|
|
18
|
+
parsed = json.loads(json_str)
|
|
19
|
+
formatted_json = json.dumps(parsed, indent=4, sort_keys=True)
|
|
20
|
+
except Exception as e:
|
|
21
|
+
pass
|
|
22
|
+
return formatted_json
|
halib/listop.py
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
def subtract(list_a, list_b):
|
|
2
|
+
return [item for item in list_a if item not in list_b]
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def union(list_a, list_b, no_duplicate=False):
|
|
6
|
+
if no_duplicate:
|
|
7
|
+
return list(set(list_a) | set(list_b))
|
|
8
|
+
else:
|
|
9
|
+
return list_a + list_b
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def intersection(list_a, list_b):
|
|
13
|
+
return list(set(list_a) & set(list_b))
|
halib/online/__init__.py
ADDED
|
File without changes
|
halib/online/gdrive.py
ADDED
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Upload folder to Google Drive
|
|
5
|
+
"""
|
|
6
|
+
import ast
|
|
7
|
+
import os
|
|
8
|
+
import requests
|
|
9
|
+
import json
|
|
10
|
+
|
|
11
|
+
import googleapiclient.errors
|
|
12
|
+
|
|
13
|
+
# Import Google libraries
|
|
14
|
+
from pydrive.auth import GoogleAuth
|
|
15
|
+
from pydrive.drive import GoogleDrive
|
|
16
|
+
from pydrive.files import GoogleDriveFileList
|
|
17
|
+
|
|
18
|
+
from ..system import filesys
|
|
19
|
+
from ..filetype import textfile
|
|
20
|
+
|
|
21
|
+
# Import general libraries
|
|
22
|
+
|
|
23
|
+
ggDrive = None
|
|
24
|
+
ggAuth = None
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def get_gg_drive(settings_file="settings.yaml"):
|
|
28
|
+
"""
|
|
29
|
+
Authenticate to Google API
|
|
30
|
+
"""
|
|
31
|
+
global ggDrive
|
|
32
|
+
global ggAuth
|
|
33
|
+
if ggDrive is None:
|
|
34
|
+
ggAuth = GoogleAuth(settings_file=settings_file)
|
|
35
|
+
ggDrive = GoogleDrive(ggAuth)
|
|
36
|
+
return ggDrive
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def get_folder_id(gg_parent_folder_id, folder_name):
|
|
40
|
+
"""
|
|
41
|
+
Check if destination folder exists and return it's ID
|
|
42
|
+
"""
|
|
43
|
+
|
|
44
|
+
# Auto-iterate through all files in the parent folder.
|
|
45
|
+
drive = get_gg_drive()
|
|
46
|
+
file_list = GoogleDriveFileList()
|
|
47
|
+
try:
|
|
48
|
+
file_list = drive.ListFile(
|
|
49
|
+
{"q": "'{0}' in parents and trashed=false".format(gg_parent_folder_id)}
|
|
50
|
+
).GetList()
|
|
51
|
+
# Exit if the parent folder doesn't exist
|
|
52
|
+
except googleapiclient.errors.HttpError as err:
|
|
53
|
+
# Parse error message
|
|
54
|
+
message = ast.literal_eval(err.content)["error"]["message"]
|
|
55
|
+
if message == "File not found: ":
|
|
56
|
+
print(message + folder_name)
|
|
57
|
+
exit(1)
|
|
58
|
+
# Exit with stacktrace in case of other error
|
|
59
|
+
else:
|
|
60
|
+
raise
|
|
61
|
+
|
|
62
|
+
# Find the the destination folder in the parent folder's files
|
|
63
|
+
for file1 in file_list:
|
|
64
|
+
if file1["title"] == folder_name:
|
|
65
|
+
print("title: %s, id: %s" % (file1["title"], file1["id"]))
|
|
66
|
+
return file1["id"]
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def create_folder(folder_name, gg_parent_folder_id):
|
|
70
|
+
"""
|
|
71
|
+
Create folder on Google Drive
|
|
72
|
+
"""
|
|
73
|
+
|
|
74
|
+
folder_metadata = {
|
|
75
|
+
"title": folder_name,
|
|
76
|
+
# Define the file type as folder
|
|
77
|
+
"mimeType": "application/vnd.google-apps.folder",
|
|
78
|
+
# ID of the parent folder
|
|
79
|
+
"parents": [{"kind": "drive#fileLink", "id": gg_parent_folder_id}],
|
|
80
|
+
}
|
|
81
|
+
drive = get_gg_drive()
|
|
82
|
+
folder = drive.CreateFile(folder_metadata)
|
|
83
|
+
folder.Upload()
|
|
84
|
+
|
|
85
|
+
# Return folder information
|
|
86
|
+
# print('title: %s, id: %s' % (folder['title'], folder['id']))
|
|
87
|
+
return folder["id"]
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def is_in_ignore_list(local_path, ignore_list=None):
|
|
91
|
+
in_ignore_list = False
|
|
92
|
+
if ignore_list:
|
|
93
|
+
for path in ignore_list:
|
|
94
|
+
if path in local_path:
|
|
95
|
+
in_ignore_list = True
|
|
96
|
+
break
|
|
97
|
+
return in_ignore_list
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def upload_file(local_file_path, gg_folder_id, ignore_list=None):
|
|
101
|
+
"""
|
|
102
|
+
Upload local file to Google Drive folder
|
|
103
|
+
"""
|
|
104
|
+
drive = get_gg_drive()
|
|
105
|
+
if not is_in_ignore_list(local_file_path, ignore_list):
|
|
106
|
+
link = ""
|
|
107
|
+
|
|
108
|
+
# print('uploading ' + local_file_path)
|
|
109
|
+
try:
|
|
110
|
+
# Upload file to folder.
|
|
111
|
+
title = filesys.get_file_name(local_file_path, split_file_ext=False)
|
|
112
|
+
|
|
113
|
+
# delete file if exist on gg folder
|
|
114
|
+
query = f"'{gg_folder_id}' in parents and trashed=false"
|
|
115
|
+
file_list = drive.ListFile({"q": f"{query}"}).GetList()
|
|
116
|
+
for file in file_list:
|
|
117
|
+
if file["title"] == title:
|
|
118
|
+
# print(f'[DELETE] {title} on Google Drive')
|
|
119
|
+
file.Delete()
|
|
120
|
+
break
|
|
121
|
+
# print('uploading ' + local_file_path)
|
|
122
|
+
f = drive.CreateFile(
|
|
123
|
+
{
|
|
124
|
+
"title": f"{title}",
|
|
125
|
+
"parents": [{"kind": "drive#fileLink", "id": gg_folder_id}],
|
|
126
|
+
}
|
|
127
|
+
)
|
|
128
|
+
f.SetContentFile(local_file_path)
|
|
129
|
+
f.Upload(param={"supportsAllDrives": True})
|
|
130
|
+
access_token = (
|
|
131
|
+
ggAuth.credentials.access_token
|
|
132
|
+
) # gauth is from drive = GoogleDrive(gauth) Please modify this for your actual script.
|
|
133
|
+
# print(f'access_token {access_token}')
|
|
134
|
+
file_id = f["id"]
|
|
135
|
+
url = (
|
|
136
|
+
"https://www.googleapis.com/drive/v3/files/"
|
|
137
|
+
+ file_id
|
|
138
|
+
+ "/permissions?supportsAllDrives=true"
|
|
139
|
+
)
|
|
140
|
+
headers = {
|
|
141
|
+
"Authorization": "Bearer " + access_token,
|
|
142
|
+
"Content-Type": "application/json",
|
|
143
|
+
}
|
|
144
|
+
payload = {"type": "anyone", "value": "anyone", "role": "reader"}
|
|
145
|
+
res = requests.post(url, data=json.dumps(payload), headers=headers)
|
|
146
|
+
# SHARABLE LINK
|
|
147
|
+
link = f["alternateLink"]
|
|
148
|
+
return link
|
|
149
|
+
except Exception as e:
|
|
150
|
+
print("error uploading " + local_file_path)
|
|
151
|
+
print(e)
|
|
152
|
+
return link
|
|
153
|
+
# Skip the file if it's empty
|
|
154
|
+
else:
|
|
155
|
+
print("file {0} is empty or in ignore list".format(local_file_path))
|
|
156
|
+
return "" # return empty string
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
def recursive_walk_and_upload(
|
|
160
|
+
local_folder_path, gg_folder_id, processed_path, ignore_list=None
|
|
161
|
+
):
|
|
162
|
+
for root, sub_folders, files in os.walk(local_folder_path):
|
|
163
|
+
# already processed folder
|
|
164
|
+
if root in processed_path:
|
|
165
|
+
print(f"[SKIP] already processed folder {root}")
|
|
166
|
+
return
|
|
167
|
+
print(f"\n\n[RECURSIVE] {local_folder_path}, {gg_folder_id}")
|
|
168
|
+
print(f"[FF] {root} {sub_folders} {files}")
|
|
169
|
+
if sub_folders:
|
|
170
|
+
for sub_folder in sub_folders:
|
|
171
|
+
sub_folder_path = os.path.join(root, sub_folder)
|
|
172
|
+
print(f"process {sub_folder_path}")
|
|
173
|
+
if is_in_ignore_list(sub_folder_path, ignore_list):
|
|
174
|
+
continue
|
|
175
|
+
# Get destination folder ID
|
|
176
|
+
gg_sub_folder_id = get_folder_id(gg_folder_id, sub_folder)
|
|
177
|
+
# Create the folder if it doesn't exists
|
|
178
|
+
if not gg_sub_folder_id:
|
|
179
|
+
print("creating folder " + sub_folder)
|
|
180
|
+
gg_sub_folder_id = create_folder(sub_folder, gg_folder_id)
|
|
181
|
+
recursive_walk_and_upload(
|
|
182
|
+
sub_folder_path, gg_sub_folder_id, processed_path, ignore_list
|
|
183
|
+
)
|
|
184
|
+
if files:
|
|
185
|
+
for file in files:
|
|
186
|
+
filePath = os.path.join(root, file)
|
|
187
|
+
upload_file(filePath, gg_folder_id, ignore_list)
|
|
188
|
+
processed_path.append(root)
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
def upload_folder_to_drive(
|
|
192
|
+
local_folder, gg_folder_id, content_only=True, ignore_file=None
|
|
193
|
+
):
|
|
194
|
+
"""
|
|
195
|
+
Upload folder to Google Drive folder
|
|
196
|
+
bool content_only: if true, we only upload files and folder inside local_folder
|
|
197
|
+
else create a folder with the same name of the local folder and upload all files and folders
|
|
198
|
+
in the local folder to it
|
|
199
|
+
"""
|
|
200
|
+
|
|
201
|
+
ignore_list = None
|
|
202
|
+
if ignore_file:
|
|
203
|
+
if filesys.is_file(ignore_file):
|
|
204
|
+
ignore_list = textfile.read_line_by_line(ignore_file)
|
|
205
|
+
ignore_list = [os.path.normpath(path) for path in ignore_list]
|
|
206
|
+
|
|
207
|
+
if content_only is False:
|
|
208
|
+
folder_name = filesys.get_dir_name(local_folder)
|
|
209
|
+
gg_folder_id_to_upload = create_folder(folder_name, gg_folder_id)
|
|
210
|
+
else:
|
|
211
|
+
gg_folder_id_to_upload = gg_folder_id
|
|
212
|
+
|
|
213
|
+
processed_path = []
|
|
214
|
+
local_folder = os.path.normpath(local_folder)
|
|
215
|
+
recursive_walk_and_upload(
|
|
216
|
+
local_folder, gg_folder_id_to_upload, processed_path, ignore_list
|
|
217
|
+
)
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
def main():
|
|
221
|
+
settingf = r"halib\online\settings.yaml"
|
|
222
|
+
folder_id = "1RXew5llcebEXclbEAKQ2IWDtTWmW0d_z"
|
|
223
|
+
get_gg_drive(settingf)
|
|
224
|
+
sharelink = upload_file(r"D:\Dev\github_proj\halib\LICENSE.txt", folder_id)
|
|
225
|
+
print(sharelink)
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
if __name__ == "__main__":
|
|
229
|
+
main()
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
from argparse import ArgumentParser
|
|
2
|
+
from datetime import datetime
|
|
3
|
+
|
|
4
|
+
import gdrive
|
|
5
|
+
from ..filetype import textfile
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def parse_args():
|
|
9
|
+
parser = ArgumentParser(description="Upload local folder to Google Drive")
|
|
10
|
+
parser.add_argument(
|
|
11
|
+
"-a",
|
|
12
|
+
"--authFile",
|
|
13
|
+
type=str,
|
|
14
|
+
help="authenticate file to Google Drive",
|
|
15
|
+
default="settings.yaml",
|
|
16
|
+
)
|
|
17
|
+
parser.add_argument(
|
|
18
|
+
"-g",
|
|
19
|
+
"--GDriveParentFolder",
|
|
20
|
+
type=str,
|
|
21
|
+
help="Destination parent folder ID in Google Drive",
|
|
22
|
+
)
|
|
23
|
+
parser.add_argument(
|
|
24
|
+
"-n",
|
|
25
|
+
"--folderName",
|
|
26
|
+
type=str,
|
|
27
|
+
help="name of the folder which is about to be created",
|
|
28
|
+
default="untitled",
|
|
29
|
+
)
|
|
30
|
+
return parser.parse_args()
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def main():
|
|
34
|
+
args = parse_args()
|
|
35
|
+
auth_file = args.authFile
|
|
36
|
+
gDrive_parent_folder_id = args.GDriveParentFolder
|
|
37
|
+
folder_name = args.folderName
|
|
38
|
+
|
|
39
|
+
if folder_name == "untitled":
|
|
40
|
+
folder_name = datetime.today().strftime("%Y.%m.%d_%Hh%M")
|
|
41
|
+
else:
|
|
42
|
+
date_str = datetime.today().strftime("%Y.%m.%d_%Hh%M")
|
|
43
|
+
folder_name = f"{date_str}_{folder_name}"
|
|
44
|
+
|
|
45
|
+
print(f"[GDrive] creating {folder_name} in GDrive folder {gDrive_parent_folder_id}")
|
|
46
|
+
|
|
47
|
+
gdrive.get_gg_drive(auth_file)
|
|
48
|
+
folder_id = gdrive.create_folder(folder_name, gDrive_parent_folder_id)
|
|
49
|
+
textfile.write([folder_id], "./GDriveFolder.txt")
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
if __name__ == "__main__":
|
|
53
|
+
main()
|