Using Oracle Documents Cloud REST API with Python Requests

Python Requests is a library that simplifies consuming RESTful resources from the client side. The Oracle Documents Cloud Service (DOCS) REST API fits well with Python Requests, allowing a service call to get a folder or file to be done in few lines of code. Since Python is naturally friendly to JSON responses, parsing the Response object can be done using standard syntax.

The Requests library must be installed to Python using the pip utility (or easy-install on Windows). The example below also uses the “getpass” module to handle user entry of a password.

Python Requests link: http://docs.python-requests.org/en/latest/

Python getpass module link: https://docs.python.org/2/library/getpass.html

 

A first look at using Requests with DOCS REST services is to get a user’s Personal Workspace. Notice that importing the Requests library allows calling a HTTP GET on a REST URL. All of the HTTP work is done in Python Requests and the client code need only pass in a URL, username, and password.

import requests
import getpass

docsurl='https://mydocsinstance/documents/api/1.1/folders/items'
username='peter.flies@oracle.com'

# Get password from user entry. This is using a module called "getpass"
pw = getpass.getpass("Enter password:")
response = requests.get(docsurl, auth=(username, pw))

# View the status code - should be 200. Error handling can be done with the status code. 
print (response.status_code)
# Header data is available from the Response object, which is part of Python Requests 
print (response.headers['content-type'])

# Get the JSON data
j = response.json()

# Navigate the JSON data using standard Python
print('count=' + j['count'])
print('errorCode=' + j['errorCode'])
print('totalResults=' + j['totalResults'])

print('Items:')
for item in j['items']:
	print ('type=' + item['type'] + ' name=' + item['name'] + ' owner=' + item['ownedBy']['displayName'])

 

An upload example requires a multipart HTTP POST request to send the file payload and a JSON payload. This example also shows the use of a Session in Python Requests. The Session can have the Authorization header set once and be re-used for all subsequent REST calls to Oracle Documents Cloud service. The example below uploads all files in a directory to a user’s DOCS account. A folder GUID is needed for the upload to add the new files into the target folder. Some additional lines of code are added here for printing out the amount of milliseconds that each upload takes. The upload request differs from the previous example in that the POST request needs multipart payload to succeed. Notice that a data part called “jsonInputParameters” and a file part called “primaryFile” are both added to the request. Python’s os module can handle opening the file and placing it into the multipart. A loop can grab each file from the directory and submit an upload request.

import os
import getpass
import time
import requests

docsurl='https://mydocsinstance/documents/api/1.1'
path = 'C:/TEMP/upload'
username = 'peter.flies@oracle.com'
uploadfolderid = 'F26415F66B0BE6EE53314461T0000DEFAULT00000000'

# Get user input to set the password. Set the REST client authorization header by directly passing in the username and password 
pw = getpass.getpass("Enter password:")
 
files = (file for file in os.listdir(path) 
	if os.path.isfile(os.path.join(path, file)))

# Requests has a reusable Session object. Init it with the Authorization header
s = requests.Session()
s.auth = (username, pw)

print('Uploading files from path ' + path + ' to Documents Cloud Service ' + docsurl + '.\n')
for file in files: 
	startMillis = int(round(time.time() * 1000))
	print('Uploading ' + file + '...')
	print(path + '/' + file)
	resourcePath = 'files/data'
	fullpath = path + '/' + file
	files = {
		'primaryFile': open(fullpath, 'rb')
	}
	jsondata='{\"parentID\": \"' + uploadfolderid + '\" }'
	data = {
		'jsonInputParameters': jsondata
	}
	response = s.post(docsurl + '/' + resourcePath, files=files, data=data)		
	endMillis = int(round(time.time() * 1000))
	if(response.status_code == 200 or response.status_code == 201):
		j = response.json()
		print('Upload successful. ' + str(endMillis - startMillis) + ' ms. File id: ' + j['id'] + ', version number: ' + j['version'] + '\n')
	else:
		print('ERROR: Upload unsuccessful for file: ' + file)
		print(str(response.status_code) + ' ' + response.reason )
		if(response.json()):
			j = response.json()
			print('Error details: ' + j['errorCode'] + ' ' + j['errorMessage'])			
		else:
			print('Dump of response text:')
			print(response.text + '\n')



A file download is a HTTP GET but requires saving the file to a location on disk. Again, Python has utilities to simplify the downloading and saving of Oracle Documents Cloud files.

import getpass
import requests
import logging

docsurl='https://documents.us.oracle.com/documents/api/1.1'
savePath = 'C:/TEMP/download'
username = 'peter.flies@oracle.com'
fileid = 'DCA4BBA0908AE2F497832BC2T0000DEFAULT00000000'
resourcePath = 'files/{fileid}/data'
resourcePath = resourcePath.replace('{fileid}', fileid)

# Get user input to set the password. Set the REST client authorization header by directly passing in the username and password 
pw = getpass.getpass("Enter password:")
 
# Requests has a reusable Session object. Init it with the Authorization header
s = requests.Session()
s.auth = (username, pw)

with open(savePath, 'wb') as fhandle:
	response = s.get(docsurl + '/' + resourcePath, stream=True)

	if not response.ok:
		print("Error!") #What do you want to do in case of error? 

	for filePiece in response.iter_content(1024):
		if not filePiece:
			break

	fhandle.write(filePiece)
#no JSON in response, but check it for status code, headers, etc. 
print(response.status_code)

 

For services that you may want to call frequently, a Python class can be created that wraps the Requests library. The commonly used service calls and associated parameters can have a method signature that sets the default parameters, but can also be overridden as needed. In the example class file below, the “DOCSClient” class has a constructor that initializes the Session. Once a handle to a DOCSClient is created, a method called “itemPersonalWorkspace” can be called with parameters to set the sort order, limit, and offset. This sample class has methods for only a few of the Documents Cloud Service REST calls, but the example can be applied to any DOCS REST API.

 

import requests
import logging

class DOCSClient:
	def __init__(self, docsurl, username, password):
		self.docsurl = docsurl
		self.version = '1.1'
		self.restBaseUrl = docsurl + '/api/' + self.version + '/'
		self.s = requests.Session()
		self.s.auth = (username, password)
		self.appLinkRoles = ('viewer', 'downloader', 'contributor')
		self.roles = ('viewer', 'downloader', 'contributor', 'manager')
	
	# Sample Item Resource REST method
	def itemPersonalWorkspace(self, orderby='name:asc', limit=50, offset=0):
		resourcePath = 'folders/items' + '?orderby=' + orderby + '&limit=' + str(limit) + '&offset=' + str(offset)
		return self.s.get(self.restBaseUrl + resourcePath)		
		
	# Sample Folder Resource REST methods
	def folderQuery(self, folderid):
		resourcePath = 'folders/{folderid}'
		resourcePath = resourcePath.replace('{folderid}', folderid)
		return self.s.get(self.restBaseUrl + resourcePath)		

	def folderCreate(self, folderid, name, description=''):
		resourcePath = 'folders/{folderid}'
		resourcePath = resourcePath.replace('{folderid}', folderid)
		resourcePath = resourcePath + '?name=' + name + '&description=' + description
		return self.s.post(self.restBaseUrl + resourcePath)		

	# Sample Upload Resource REST method
	def fileUpload(self, parentID, filepath):
		resourcePath = 'files/data'
		files = {
			'primaryFile': open(filepath, 'rb')
		}
		
		jsondata='{\"parentID\": \"' + parentID + '\" }'
		data = {
			'jsonInputParameters'  : jsondata
		}
		response = self.s.post(self.restBaseUrl + resourcePath, files=files, data=data)		
		return response

 

 

Lastly, using the newly created class can be done using an import statement. The class in this case was stored in a file called “oracledocsrequests.py”. That file must be in the PYTHON_PATH to be found when the code is run, and once in the path the import statement is a single line to make the script aware of the DOCSClient class. Once a client object is created, with the URL, username, and password being passed in, any of the methods can be called in a single line. A folder creation example is shown below using one of the class methods.  Note that the parameters in the DOCSClient class define description parameter as being empty by default, but the example overrides the empty string with “created from Python” as the folder description.

import getpass
from oracledocsrequests import DOCSClient

docsurl='https://documents.us.oracle.com/documents'
username='peter.flies@oracle.com'
folderid = 'F26415F66B0BE6EE53314461T0000DEFAULT00000000'

# Get user input to set the password. Set the REST client authorization header by directly passing in the username and password 
pw = getpass.getpass("Enter password:")

client = DOCSClient(docsurl, username, pw)

print('\n******* folderCreate *******')
response = client.folderCreate(folderid, 'My python folder', 'created from Python')
j = response.json()
print(response.status_code)
print('name=' + j['name'])

 

The Python Requests library slogan is “HTTP for Humans”. The powerful Requests library makes using the Oracle Documents Cloud Service REST API simple enough to write your own utilities to interact with a DOCS workspace.

 

 

 

 

 

 

Add Your Comment