data-transport/transport/couch.py

204 lines
5.5 KiB
Python
Raw Normal View History

"""
Data-Transport
Steve L. Nyemba, The Phi Technology
This file is a wrapper around couchdb using IBM Cloudant SDK that has an interface to couchdb
"""
import cloudant
import json
2019-11-05 03:51:20 +00:00
import sys
if sys.version_info[0] > 2 :
from transport.common import Reader, Writer
else:
from common import Reader, Writer
class Couch:
"""
2019-09-17 16:21:42 +00:00
This class is a wrapper for read/write against couchdb. The class captures common operations for read/write.
@param url host & port reference
2019-09-17 16:21:42 +00:00
@param doc user id involved
@param dbname database name (target)
"""
def __init__(self,**args):
url = args['url']
2019-09-17 16:21:42 +00:00
self.uid = args['doc']
dbname = args['dbname']
if 'username' not in args and 'password' not in args :
2019-09-17 16:21:42 +00:00
self.server = cloudant.CouchDB(None,None,url=url)
else:
self.server = cloudant.CouchDB(args['username'],args['password'],url=url)
self.server.connect()
if dbname in self.server.all_dbs() :
self.dbase = self.server.get(dbname,dbname,True)
#
# @TODO Check if the database exists ...
#
doc = cloudant.document.Document(self.dbase,self.uid) #self.dbase.get(self.uid)
if not doc.exists():
doc = self.dbase.create_document({"_id":self.uid})
doc.save()
else:
self.dbase = None
"""
Insuring the preconditions are met for processing
"""
def isready(self):
p = self.server.metadata() != {}
if p == False or not self.dbase:
return False
#
# At this point we are sure that the server is connected
# We are also sure that the database actually exists
#
doc = cloudant.document.Document(self.dbase,self.uid)
# q = self.dbase.all_docs(key=self.uid)['rows']
# if not q :
if not doc.exists():
return False
return True
def view(self,**args):
"""
2019-09-17 16:21:42 +00:00
The function will execute a view (provivded a user is authenticated)
:id design document _design/xxxx (provide full name with _design prefix)
:view_name name of the view i.e
:key(s) key(s) to be used to filter the content
"""
document = cloudant.design_document.DesignDocument(self.dbase,args['id'])
document.fetch()
params = {'group_level':1,'group':True}
if 'key' in args :
params ['key'] = args['key']
elif 'keys' in args :
params['keys'] = args['keys']
return document.get_view(args['view_name'])(**params)['rows']
class CouchReader(Couch,Reader):
"""
This function will read an attachment from couchdb and return it to calling code. The attachment must have been placed before hand (otherwise oops)
@T: Account for security & access control
"""
def __init__(self,**args):
"""
@param filename filename (attachment)
"""
#
# setting the basic parameters for
Couch.__init__(self,**args)
if 'filename' in args :
self.filename = args['filename']
else:
self.filename = None
# def isready(self):
# #
# # Is the basic information about the database valid
# #
# p = Couchdb.isready(self)
# if p == False:
# return False
# #
# # The database name is set and correct at this point
# # We insure the document of the given user has the requested attachment.
# #
# doc = self.dbase.get(self.uid)
# if '_attachments' in doc:
# r = self.filename in doc['_attachments'].keys()
# else:
# r = False
# return r
def stream(self):
#
# @TODO Need to get this working ...
#
document = cloudant.document.Document(self.dbase,self.uid)
# content = self.dbase.fetch_attachment(self.uid,self.filename).split('\n') ;
content = self.get_attachment(self.filename)
for row in content:
yield row
def read(self,size=-1):
if self.filename is not None:
self.stream()
else:
return self.basic_read()
def basic_read(self):
document = cloudant.document.Document(self.dbase,self.uid)
# document = self.dbase.get(self.uid)
if document.exists() :
document.fetch()
document = dict(document)
del document['_rev']
else:
document = {}
return document
class CouchWriter(Couch,Writer):
"""
This class will write on a couchdb document provided a scope
The scope is the attribute that will be on the couchdb document
"""
def __init__(self,**args):
"""
@param uri host & port reference
@param uid user id involved
@param filename filename (attachment)
@param dbname database name (target)
"""
Couch.__init__(self,**args)
def write(self,**params):
"""
write a given attribute to a document database
@param label scope of the row repair|broken|fixed|stats
@param row row to be written
"""
# document = self.dbase.get(self.uid)
document = cloudant.document.Document(self.dbase,self.uid) #.get(self.uid)
if document.exists() is False :
document = self.dbase.create_document({"_id":self.uid})
label = params['label']
row = params['row']
if label not in document :
document[label] = []
document[label].append(row)
document.save()
# self.dbase.bulk_docs([document])
# self.dbase.save_doc(document)
def archive(self,params=None):
"""
This function will archive the document onto itself.
"""
# document = self.dbase.all_docs(self.uid,include_docs=True)
document = cloudant.document.Document(self.dbase,self.filename)
document.fetch()
content = {}
# _doc = {}
for id in document:
if id not in ['_id','_rev','_attachments'] :
content[id] = document[id]
del document[id]
content = json.dumps(content)
# document= _doc
now = str(datetime.today())
name = '-'.join([document['_id'] , now,'.json'])
# self.dbase.bulk_docs([document])
# self.dbase.put_attachment(document,content,name,'application/json')
document.put_attachment(self.dbase,name,'application/json',content)
document.save()