How to get the parent folder of a google docs resource? - python

Using Python gdata in my Goggle App Engine Application I am trying to copy a google docs resource and put the copy in the same folder as the source file. The CopyResource method that I use put the copy at the root level.
Would you know how to query Google Docs to have the list of folders/collections in which a file is?
import gdata.docs.service
import gdata.docs.client
...
doc_service = gdata.docs.client.DocsClient()
doc_service.ClientLogin('username', 'abc123', 'my app name')
try:
doc = doc_service.GetResourceById(resourceId)
newdoc = doc_service.CopyResource(doc, filename)
# newdoc is copied at the root level of Google Drive
# need to move it where the source file is located.
newdocid = newdoc.id.text.decode('utf-8').split('%3A')[1]
# would like here to have my newly copied document
# moved to the same directory as the source one.
# assuming the source is only in one folder.
except gdata.client.RequestError, inst:
logging.info('Copy Error: %s', inst.body)

Related

How to copy a file box URL rooted in folder directory?

I need to create an script that helps me pick the URL from a Box file that has a path in my computer.
I've the Box desktop application installed.
Like: C:\Users\Thiago.Oliveira\Box\
I've created this script:
# Providing the folder path
origin = r'C:\\Users\\Thiago.Oliveira\\Box\\XXXXXXX.xlsx'
target = f'C:\\Users\\Thiago.Oliveira\\Box\\XXXXXXX{datetime.date.today()}.xlsx'
# Fetching the list of all the files
shutil.copy(origin, target)
print("Files are copied successfully")
This helps me out to copy and rename the file for this box folder. But I also want to pick up the URL from the newly created file so I can send it over in an e-mail.
I haven't found anything that would help me with this.
Is this possible?
Yes, you can, see the example below.
This example is using the box python sdk, and this is a JWT auth application script.
After uploading the file, the box sdk returns a file object, which has many properties.
I'm not sure what you mean by "pick up the URL", it could be the direct download URL of the file or a shared link.
The example is for the direct download URL.
To get the destination FOLDER_ID, you can look at the browser URL when you open the folder on the box.com app.
e.g.:image of demo folder url in browser
from datetime import date
import os
from boxsdk import JWTAuth, Client
def main():
auth = JWTAuth.from_settings_file(".jwt.config.json")
auth.authenticate_instance()
client = Client(auth)
folder_id = "163422716106"
user = client.user().get()
print(f"User: {user.id}:{user.name}")
folder = client.folder(folder_id).get()
print(f"Folder: {folder.id}:{folder.name}")
with open("./main.py", "rb") as file:
basename = os.path.basename(file.name)
file_name = os.path.splitext(basename)[0]
file_ext = os.path.splitext(basename)[1]
file_time = date.today().strftime("%Y%m%d")
box_file_name = file_name + "_" + file_time + file_ext
print(f"Uploading {box_file_name} to {folder.name}")
box_file = folder.upload_stream(file, box_file_name)
box_file.get()
print(f"File: {box_file.id}:{box_file.name}")
print(f"Download URL: {box_file.get_download_url()}")
if __name__ == "__main__":
main()
print("Done")
Resulting in:
User: 20344589936:UI-Elements-Sample
Folder: 163422716106:Box UI Elements Demo
Uploading main_20230203.py to Box UI Elements Demo
File: 1130939599686:main_20230203.py
Download URL: https://public.boxcloud.com/d/1/b1!5CgJ...fLc./download

Listing files using Dropbox API

I am trying to access files stored on my Dropbox using the offical Dropbox SDK for Python.. I tried a few ways of putting in the directory name whose contents I wanted to have listed based off of a script taken from this link https://practicaldatascience.co.uk/data-science/how-to-use-the-dropbox-api-with-python. Following the instructions in this website, I created an App, generated a dropbox access token (which produced 'long-gibberish'), and gave myself read permissions for Files and Folders.
When I login to Dropbox through the website, the folder structure for the folder that I want to access looks like so: Folder/ SubFolder/ SubSubFolder.
DROPBOX_ACCESS_TOKEN = 'long-gibberish'
def dropbox_connect():
"""Create a connection to Dropbox."""
try:
dbx = dropbox.Dropbox(DROPBOX_ACCESS_TOKEN)
except AuthError as e:
print('Error connecting to Dropbox with access token: ' + str(e))
return dbx
def dropbox_list_files(path):
"""Return a Pandas dataframe of files in a given Dropbox folder path in the Apps directory.
"""
dbx = dropbox_connect()
try:
files = dbx.files_list_folder(path).entries
files_list = []
for file in files:
if isinstance(file, dropbox.files.FileMetadata):
metadata = {
'name': file.name,
'path_display': file.path_display,
'client_modified': file.client_modified,
'server_modified': file.server_modified
}
files_list.append(metadata)
df = pd.DataFrame.from_records(files_list)
return df.sort_values(by='server_modified', ascending=False)
except Exception as e:
print('Error getting list of files from Dropbox: ' + str(e))
I get the following error when calling the function:
dropbox_list_files('Folder/SubFolder/SubSubFolder')
Error getting list of files from Dropbox: ApiError('short-gibberish', ListFolderError('path', LookupError('not_found', None)))
I would like to get some help on how to set the right path.
After locating a Dropbox for Python tutorial, it was figured that the directory structure can be retrieved in the following manner
for entry in dbx.files_list_folder('').entries:
print(entry.name)
But, before that an instance of the Dropbox object must be created:
dbx = dropbox.Dropbox('YOUR_ACCESS_TOKEN')
which is achieved by invoking and assigning dbx:
dbx = dropbox_connect()

How to copy folder and its content into new location in SharePoint Online with python office365 module

I am trying to copy a folder with all its content from one site to another in SharePoint Online. So I created a code that recursively creates the folder structure.
What I can't do is to copy the files. For the start I am trying to test the following very simple code which I got from GitHub
url = 'https://company.sharepoint.com/sites/MyTeam'
ctx = ClientContext(url).with_credentials(ClientCredential(client_id, client_secret))
source_folder = ctx.web.get_folder_by_server_relative_url('Shared Documents/from')
target_folder = source_folder.copy_to('Shared Documents/to').get().execute_query()
This code doesn't do anything at all. I tried to check the paths and print out the files in the source_folder and target_folder. It prints out the files in the source_folder and prints nothing for the target_folder. What am I missing here?
You could try to use sever relatice url like this:
/sites/MyTeam/Shared Documents/from and /sites/MyTeam/Shared Documents/to
Check if it works.

Manage files from public Google Drive URL using PyDrive

I`m using PyDrive QuickStart script to list my Google Drive files.
Code:
from pydrive.auth import GoogleAuth
from pydrive.drive import GoogleDrive
gauth = GoogleAuth()
gauth.LocalWebserverAuth()
drive = GoogleDrive(gauth)
file_list = drive.ListFile({'q': "'root' in parents and trashed=false"}).GetList()
print(file_list)
I'm able to list my files normally, but I need to list and manage files from another public drive URL (which is not the my personal authenticated drive) from my already authenticated GoogleDrive account like if I was using requests lib.
Any ideas how to do it?
You need to get the folder ID. You can find the ID in the URL of the folder. An example would be:
https://drive.google.com/open?id=0B-schRXnDFZeX0t0RnhQVXXXXXX (the part of the URL after the id=).
List contents of a folder based on ID. Given your code you replace file_list = ... with:
file_id = '<Your folder id here.>'
file_list = drive.ListFile({'q': "'%s' in parents and trashed=false" % file_id}).GetList()
If this does not work, you may have to add the remote folder to your Google Drive using the "Add to Drive" button in the top right corner of the shared folder when opened in a browser.
2.1 Creating a file in a folder can be done like so:
file_object = drive.CreateFile({
"parents": [{"kind": "drive#fileLink",
"id": parent_id}],
'title': file_name,
# (Only!) If the new 'file' object is going be a folder:
'mimeType': "application/vnd.google-apps.folder"
})
file_object.Upload()
If this fails check whether you have write permissions to the folder.
2.2 Deleting/Trashing a file can be done with the updated version available from GitHub: pip install instructions, Delete/Trash/UnTrash documentation
Finally, there is a feature request to Upload to folders as described in 2.1, and listing files of a folder, as described in 2. - if you find the above not to work you can add this as an issue / feature request to the repository.

How to determine the Dropbox folder location programmatically?

I have a script that is intended to be run by multiple users on multiple computers, and they don't all have their Dropbox folders in their respective home directories. I'd hate to have to hard code paths in the script. I'd much rather figure out the path programatically.
Any suggestions welcome.
EDIT:
I am not using the Dropbox API in the script, the script simply reads files in a specific Dropbox folder shared between the users. The only thing I need is the path to the Dropbox folder, as I of course already know the relative path within the Dropbox file structure.
EDIT:
If it matters, I am using Windows 7.
I found the answer here. Setting s equal to the 2nd line in ~\AppData\Roaming\Dropbox\host.db and then decoding it with base64 gives the path.
def _get_appdata_path():
import ctypes
from ctypes import wintypes, windll
CSIDL_APPDATA = 26
_SHGetFolderPath = windll.shell32.SHGetFolderPathW
_SHGetFolderPath.argtypes = [wintypes.HWND,
ctypes.c_int,
wintypes.HANDLE,
wintypes.DWORD,
wintypes.LPCWSTR]
path_buf = wintypes.create_unicode_buffer(wintypes.MAX_PATH)
result = _SHGetFolderPath(0, CSIDL_APPDATA, 0, 0, path_buf)
return path_buf.value
def dropbox_home():
from platform import system
import base64
import os.path
_system = system()
if _system in ('Windows', 'cli'):
host_db_path = os.path.join(_get_appdata_path(),
'Dropbox',
'host.db')
elif _system in ('Linux', 'Darwin'):
host_db_path = os.path.expanduser('~'
'/.dropbox'
'/host.db')
else:
raise RuntimeError('Unknown system={}'
.format(_system))
if not os.path.exists(host_db_path):
raise RuntimeError("Config path={} doesn't exists"
.format(host_db_path))
with open(host_db_path, 'r') as f:
data = f.read().split()
return base64.b64decode(data[1])
There is an answer to this on Dropbox Help Center - How can I programmatically find the Dropbox folder paths?
Short version:
Use ~/.dropbox/info.json or %APPDATA%\Dropbox\info.json
Long version:
Access the valid %APPDATA% or %LOCALAPPDATA% location this way:
import os
from pathlib import Path
import json
try:
json_path = (Path(os.getenv('LOCALAPPDATA'))/'Dropbox'/'info.json').resolve()
except FileNotFoundError:
json_path = (Path(os.getenv('APPDATA'))/'Dropbox'/'info.json').resolve()
with open(str(json_path)) as f:
j = json.load(f)
personal_dbox_path = Path(j['personal']['path'])
business_dbox_path = Path(j['business']['path'])
You could search the file system using os.walk. The Dropbox folder is probably within the home directory of the user, so to save some time you could limit your search to that. Example:
import os
dropbox_folder = None
for dirname, dirnames, filenames in os.walk(os.path.expanduser('~')):
for subdirname in dirnames:
if(subdirname == 'Dropbox'):
dropbox_folder = os.path.join(dirname, subdirname)
break
if dropbox_folder:
break
# dropbox_folder now contains the full path to the Dropbox folder, or
# None if the folder wasn't found
Alternatively you could prompt the user for the Dropbox folder location, or make it configurable via a config file.
This adaptation based on J.F. Sebastian's suggestion works for me on Ubuntu:
os.path.expanduser('~/Dropbox')
And to actually set the working directory to be there:
os.chdir(os.path.expanduser('~/Dropbox'))
Note: answer is valid for Dropbox v2.8 and higher
Windows
jq -r ".personal.path" < %APPDATA%\Dropbox\info.json
This needs jq - JSON parser utility to be installed. If you are happy user of Chocolatey package manager, just run choco install jq before.
Linux
jq -r ".personal.path" < ~/.dropbox/info.json
Just similarly to Windows install jq using package manager of your distro.
Note: requires Dropbox >= 2.8
Dropbox now stores the paths in json format in a file called info.json. It is located in one of the two following locations:
%APPDATA%\Dropbox\info.json
%LOCALAPPDATA%\Dropbox\info.json
I can access the %APPDATA% environment variable in Python by os.environ['APPDATA'], however I check both that and os.environ['LOCALAPPDATA']. Then I convert the JSON into a dictionary and read the 'path' value under the appropriate Dropbox (business or personal).
Calling get_dropbox_location() from the code below will return the filepath of the business Dropbox, while get_dropbox_location('personal') will return the file path of the personal Dropbox.
import os
import json
def get_dropbox_location(account_type='business'):
"""
Returns a string of the filepath of the Dropbox for this user
:param account_type: str, 'business' or 'personal'
"""
info_path = _get_dropbox_info_path()
info_dict = _get_dictionary_from_path_to_json(info_path)
return _get_dropbox_path_from_dictionary(info_dict, account_type)
def _get_dropbox_info_path():
"""
Returns filepath of Dropbox file info.json
"""
path = _create_dropox_info_path('APPDATA')
if path:
return path
return _create_dropox_info_path('LOCALAPPDATA')
def _create_dropox_info_path(appdata_str):
r"""
Looks up the environment variable given by appdata_str and combines with \Dropbox\info.json
Then checks if the info.json exists at that path, and if so returns the filepath, otherwise
returns False
"""
path = os.path.join(os.environ[appdata_str], r'Dropbox\info.json')
if os.path.exists(path):
return path
return False
def _get_dictionary_from_path_to_json(info_path):
"""
Loads a json file and returns as a dictionary
"""
with open(info_path, 'r') as f:
text = f.read()
return json.loads(text)
def _get_dropbox_path_from_dictionary(info_dict, account_type):
"""
Returns the 'path' value under the account_type dictionary within the main dictionary
"""
return info_dict[account_type]['path']
This is a pure Python solution, unlike the other solution using info.json.
One option is you could go searching for the .dropbox.cache directory which (at least on Mac and Linux) is a hidden folder in the Dropbox directory.
I am fairly certain that Dropbox stores its preferences in an encrypted .dbx container, so extracting it using the same method that Dropbox uses is not trivial.
This should work on Win7. The use of getEnvironmentVariable("APPDATA") instead of os.getenv('APPDATA') supports Unicode filepaths -- see question titled Problems with umlauts in python appdata environvent variable.
import base64
import ctypes
import os
def getEnvironmentVariable(name):
""" read windows native unicode environment variables """
# (could just use os.environ dict in Python 3)
name = unicode(name) # make sure string argument is unicode
n = ctypes.windll.kernel32.GetEnvironmentVariableW(name, None, 0)
if not n:
return None
else:
buf = ctypes.create_unicode_buffer(u'\0'*n)
ctypes.windll.kernel32.GetEnvironmentVariableW(name, buf, n)
return buf.value
def getDropboxRoot():
# find the path for Dropbox's root watch folder from its sqlite host.db database.
# Dropbox stores its databases under the currently logged in user's %APPDATA% path.
# If you have installed multiple instances of dropbox under the same login this only finds the 1st one.
# Dropbox stores its databases under the currently logged in user's %APPDATA% path.
# usually "C:\Documents and Settings\<login_account>\Application Data"
sConfigFile = os.path.join(getEnvironmentVariable("APPDATA"),
'Dropbox', 'host.db')
# return null string if can't find or work database file.
if not os.path.exists(sConfigFile):
return None
# Dropbox Watch Folder Location is base64 encoded as the last line of the host.db file.
with open(sConfigFile) as dbxfile:
for sLine in dbxfile:
pass
# decode last line, path to dropbox watch folder with no trailing slash.
return base64.b64decode(sLine)
if __name__ == '__main__':
print getDropboxRoot()

Categories

Resources