|
|
|
@ -1,12 +1,32 @@ |
|
|
|
from magic import from_file |
|
|
|
from gapi.api import API |
|
|
|
from posixpath import join as pathjoin |
|
|
|
from googleapiclient.http import MediaFileUpload |
|
|
|
import re |
|
|
|
import os |
|
|
|
|
|
|
|
APPLICATION_NAME = "Google Calendar API Python" |
|
|
|
def path_translate( |
|
|
|
root, |
|
|
|
want, |
|
|
|
path, |
|
|
|
file |
|
|
|
): |
|
|
|
l = len(root)+1 |
|
|
|
rel = path[l:] |
|
|
|
new_rel = rel.replace(os.sep,'/') |
|
|
|
return pathjoin(want,new_rel,file) |
|
|
|
|
|
|
|
def is_folder(element): |
|
|
|
return element['mimeType'] == 'application/vnd.google-apps.folder' |
|
|
|
|
|
|
|
def split_path_nt(path,rev=False): |
|
|
|
s = re.findall(r'?:[a-zA-Z]:\\)|[^/\\\?%\*:\|\"\<\>]+',path) |
|
|
|
if rev: |
|
|
|
return s[::-1] |
|
|
|
else: |
|
|
|
return s |
|
|
|
|
|
|
|
def split_path(path,rev=False): |
|
|
|
s = re.findall(r'(?:^/|[^/\x00]+)',path) |
|
|
|
if rev: |
|
|
|
@ -14,6 +34,11 @@ def split_path(path,rev=False): |
|
|
|
else: |
|
|
|
return s |
|
|
|
|
|
|
|
if os.name == 'nt': |
|
|
|
local_split_path = split_path_nt |
|
|
|
else: |
|
|
|
local_split_path = split_path |
|
|
|
|
|
|
|
def without(node,*keys): |
|
|
|
node_meta = set(node.keys()) |
|
|
|
nope = set(keys) |
|
|
|
@ -22,6 +47,15 @@ def without(node,*keys): |
|
|
|
ret[key] = node[key] |
|
|
|
return ret |
|
|
|
|
|
|
|
def remote_path_join(path,*paths): |
|
|
|
ret = path |
|
|
|
for path in paths: |
|
|
|
if not ret.endswith('/'): |
|
|
|
ret += '/' |
|
|
|
else: |
|
|
|
ret += path |
|
|
|
return ret |
|
|
|
|
|
|
|
class drive_api(API): |
|
|
|
|
|
|
|
def __init__( |
|
|
|
@ -45,6 +79,8 @@ class drive_api(API): |
|
|
|
'''gets a file or folder by remote path''' |
|
|
|
if isinstance(path,str): |
|
|
|
path = split_path(path) |
|
|
|
else: |
|
|
|
path = path.copy() |
|
|
|
parent = self.filesystem |
|
|
|
end = path.pop() |
|
|
|
for sub in path: |
|
|
|
@ -59,46 +95,25 @@ class drive_api(API): |
|
|
|
if not 'files' in parent.keys(): |
|
|
|
self.__fill_in__(parent) |
|
|
|
ret = parent['files'][end] |
|
|
|
if no_parent: |
|
|
|
ret = without(ret,'parent') |
|
|
|
|
|
|
|
else: |
|
|
|
if not 'folders' in parent.keys(): |
|
|
|
self.__fill_in__(parent) |
|
|
|
ret = parent['folders'][end] |
|
|
|
if no_parent: |
|
|
|
ret[0] = without(ret[0],'parent') |
|
|
|
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''' |
|
|
|
mimetype = from_file(local_path,mime_type=True) |
|
|
|
_upload = MeduaFileUpload(local_path,mimeType=mimetype) |
|
|
|
try: |
|
|
|
fid = get_file_by_path(remote_path) |
|
|
|
self.service.files().update(fileId=fid,mediaBody=_upload) |
|
|
|
except FileNotFoundError: |
|
|
|
path = split_path(remote_path) |
|
|
|
end = path.pop() |
|
|
|
parent = mkdirs(path) |
|
|
|
parent_id = parent[0]['id'] |
|
|
|
meta = { |
|
|
|
'name':end, |
|
|
|
'parents':[parent_id] |
|
|
|
} |
|
|
|
new_f_meta = self.service.files().create( |
|
|
|
body = meta, |
|
|
|
mediaBody = _upload |
|
|
|
).execute() |
|
|
|
parent['files']['end'] = new_f_meta |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def mkdirs(self,path): |
|
|
|
'''makes directories if they do not exist already''' |
|
|
|
if isinstance(path,str): |
|
|
|
path = split_path(path) |
|
|
|
else: |
|
|
|
path = path.copy() |
|
|
|
missing = [] |
|
|
|
for i in range(len(path),-1,-1): |
|
|
|
try: |
|
|
|
@ -108,7 +123,8 @@ class drive_api(API): |
|
|
|
missing.append(path[i-1]) |
|
|
|
while len(missing) > 0: |
|
|
|
|
|
|
|
new_folder = {'folders':{}} |
|
|
|
new_folder = {'folders':{},'files':{}} |
|
|
|
new_folder['parent'] = parent |
|
|
|
name = missing.pop() |
|
|
|
new_meta = self.__create_remote_folder__(name,parent) |
|
|
|
del new_meta['name'] |
|
|
|
@ -117,6 +133,49 @@ class drive_api(API): |
|
|
|
parent['folders'][name] = new_folder |
|
|
|
parent = new_folder |
|
|
|
return parent |
|
|
|
def upload(self,local_path,remote_path): |
|
|
|
if not isinstance(remote_path,str): |
|
|
|
remote_path = pathjoin(*remote_path) |
|
|
|
if os.path.isdir(local_path): |
|
|
|
for root,dirs,files in os.walk(local_path,topdown = False): |
|
|
|
for file in files: |
|
|
|
new_path = path_translate(local_path,remote_path,root,file) |
|
|
|
self.__upload_file__(os.path.join(root,file),new_path) |
|
|
|
print(new_path) |
|
|
|
return self.get_file_by_path(remote_path,False,False) |
|
|
|
else: |
|
|
|
return self.__upload_file__(local_path,remote_path) |
|
|
|
|
|
|
|
def __upload_file__(self,local_path,remote_path): |
|
|
|
'''creates file if it does not exists otherwise update the file''' |
|
|
|
if isinstance(remote_path,str): |
|
|
|
remote_path = split_path(remote_path) |
|
|
|
else: |
|
|
|
remote_path = remote_path.copy() |
|
|
|
_upload = MediaFileUpload(local_path) |
|
|
|
|
|
|
|
try: |
|
|
|
old_file = self.get_file_by_path(remote_path) |
|
|
|
self.service.files().update(fileId=old_file['id'],media_body=_upload).execute() |
|
|
|
return old_file |
|
|
|
|
|
|
|
except FileNotFoundError: |
|
|
|
path = remote_path |
|
|
|
end = path.pop() |
|
|
|
parent = self.mkdirs(path) |
|
|
|
parent_id = parent[0]['id'] |
|
|
|
meta = { |
|
|
|
'name':end, |
|
|
|
'parents':[parent_id] |
|
|
|
} |
|
|
|
new_f_meta = self.service.files().create( |
|
|
|
body = meta, |
|
|
|
media_body = _upload |
|
|
|
).execute() |
|
|
|
new_f_meta = without(new_f_meta,'kind') |
|
|
|
new_f_meta['parent'] = parent |
|
|
|
parent['files'][end] = new_f_meta |
|
|
|
return new_f_meta |
|
|
|
|
|
|
|
def __create_remote_folder__(self,name,parent): |
|
|
|
meta = { |
|
|
|
|