You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

143 lines
4.7 KiB

from magic import from_file
from gapi.api import API
from googleapiclient.http import MediaFileUpload
import re
APPLICATION_NAME = "Google Calendar API Python"
def is_folder(element):
return element['mimeType'] == 'application/vnd.google-apps.folder'
def split_path(path,rev=False):
s = re.findall(r'(?:^/|[^/\x00]+)',path)
if rev:
return s[::-1]
else:
return s
def without(node,*keys):
node_meta = set(node.keys())
nope = set(keys)
ret = {}
for key in node_meta-nope:
ret[key] = node[key]
return ret
class drive_api(API):
def __init__(
self,
app_name,
client_secret_file,
credentials_dir,
scopes = 'https://www.googleapis.com/auth/drive',
version = 'v3',
):
super().__init__('drive',scopes,app_name,client_secret_file,credentials_dir,version)
root = {}
self.filesystem = {'folders':{'/':root}}
root_meta = self.service.files().get(fileId='root').execute()
del root_meta['kind']
root[0] = root_meta
root['parent'] = self.filesystem
self.__fill_in__(root)
def get_file_by_path(self,path,ret_file = True,no_parent = True):
'''gets a file or folder by remote path'''
if isinstance(path,str):
path = split_path(path)
parent = self.filesystem
end = path.pop()
for sub in path:
try:
if not 'folders' in parent.keys():
self.__fill_in__(parent)
parent = parent['folders'][sub]
except KeyError:
raise FileNotFoundError
try:
if ret_file:
if not 'files' in parent.keys():
self.__fill_in__(parent)
ret = parent['files'][end]
else:
if not 'folders' in parent.keys():
self.__fill_in__(parent)
ret = parent['folders'][end]
if no_parent:
ret[0] = without(ret[0],'parent')
return ret
except KeyError:
raise FileNotFoundError
def __upload_file__(self,local_path,remote_path):
'''creates file if it does not exists otherwise update the file'''
isdir = os.path.isdir(local_path)
try:
fid = get_file_by_path(remote_path)
except FileNotFoundError:
path = split_path(remote_path)
end = path.pop()
parent = mkdirs(path)
parent_id = parent[0]['id']
def mkdirs(self,path):
'''makes directories if they do not exist already'''
if isinstance(path,str):
path = split_path(path)
missing = []
for i in range(len(path),-1,-1):
try:
parent = self.get_file_by_path(path[:i],False,no_parent = False)
break
except FileNotFoundError:
missing.append(path[i-1])
while len(missing) > 0:
new_folder = {'folders':{}}
name = missing.pop()
new_meta = self.__create_remote_folder__(name,parent)
del new_meta['name']
del new_meta['kind']
new_folder[0] = new_meta
parent['folders'][name] = new_folder
parent = new_folder
return parent
def __create_remote_folder__(self,name,parent):
meta = {
'name':name,
'mimeType':'application/vnd.google-apps.folder',
'parents' : [parent[0]['id']]
}
return self.service.files().create(body = meta).execute()
def __fill_in__(self,parent):
'''finds all files and folders from a parent'''
parent_id = parent[0]['id']
child_list = self.__list_children__(parent_id)
parent['files'] = {}
parent['folders'] = {}
for child in child_list:
del child['kind']
name = child.pop('name')
child['parent'] = parent
if is_folder(child):
parent['folders'][name] = {}
parent['folders'][name][0] = child
else:
parent['files'][name] = child
def __list_children__(self,parent_id):
page_token = None
first = True
while page_token or first:
first = False
response = self.service.files().list(q = "'{}' in parents and trashed = false".format(parent_id),pageToken=page_token).execute()
page_token = response.get('nextPageToken',None)
for file in response['files']:
yield file
if __name__ == "__main__":
my_api = drive_api(APPLICATION_NAME,r'..\test\drive\client_secret.json',r'..\test\drive')
service = my_api.service