couch.py 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. """
  2. Data-Transport
  3. Steve L. Nyemba, The Phi Technology
  4. This file is a wrapper around couchdb using IBM Cloudant SDK that has an interface to couchdb
  5. """
  6. import cloudant
  7. import json
  8. import sys
  9. if sys.version_info[0] > 2 :
  10. from transport.common import Reader, Writer
  11. else:
  12. from common import Reader, Writer
  13. class Couch:
  14. """
  15. This class is a wrapper for read/write against couchdb. The class captures common operations for read/write.
  16. @param url host & port reference default http://localhost:5984
  17. @param doc user id involved
  18. @param dbname database name (target)
  19. """
  20. def __init__(self,**args):
  21. url = args['url'] if 'url' in args else 'http://localhost:5984'
  22. self._id = args['doc']
  23. dbname = args['dbname']
  24. if 'username' not in args and 'password' not in args :
  25. self.server = cloudant.CouchDB(None,None,url=url)
  26. else:
  27. self.server = cloudant.CouchDB(args['username'],args['password'],url=url)
  28. self.server.connect()
  29. if dbname in self.server.all_dbs() :
  30. self.dbase = self.server.get(dbname,dbname,True)
  31. #
  32. # @TODO Check if the database exists ...
  33. #
  34. doc = cloudant.document.Document(self.dbase,self._id) #self.dbase.get(self._id)
  35. if not doc.exists():
  36. doc = self.dbase.create_document({"_id":self._id})
  37. doc.save()
  38. else:
  39. self.dbase = None
  40. """
  41. Insuring the preconditions are met for processing
  42. """
  43. def isready(self):
  44. p = self.server.metadata() != {}
  45. if p == False or not self.dbase:
  46. return False
  47. #
  48. # At this point we are sure that the server is connected
  49. # We are also sure that the database actually exists
  50. #
  51. doc = cloudant.document.Document(self.dbase,self._id)
  52. # q = self.dbase.all_docs(key=self._id)['rows']
  53. # if not q :
  54. if not doc.exists():
  55. return False
  56. return True
  57. def view(self,**args):
  58. """
  59. The function will execute a view (provivded a user is authenticated)
  60. :id design document _design/xxxx (provide full name with _design prefix)
  61. :view_name name of the view i.e
  62. :key(s) key(s) to be used to filter the content
  63. """
  64. document = cloudant.design_document.DesignDocument(self.dbase,args['id'])
  65. document.fetch()
  66. params = {'group_level':1,'group':True}
  67. if 'key' in args :
  68. params ['key'] = args['key']
  69. elif 'keys' in args :
  70. params['keys'] = args['keys']
  71. return document.get_view(args['view_name'])(**params)['rows']
  72. class CouchReader(Couch,Reader):
  73. """
  74. This function will read an attachment from couchdb and return it to calling code. The attachment must have been placed before hand (otherwise oops)
  75. @T: Account for security & access control
  76. """
  77. def __init__(self,**args):
  78. """
  79. @param filename filename (attachment)
  80. """
  81. #
  82. # setting the basic parameters for
  83. Couch.__init__(self,**args)
  84. if 'filename' in args :
  85. self.filename = args['filename']
  86. else:
  87. self.filename = None
  88. # def isready(self):
  89. # #
  90. # # Is the basic information about the database valid
  91. # #
  92. # p = Couchdb.isready(self)
  93. # if p == False:
  94. # return False
  95. # #
  96. # # The database name is set and correct at this point
  97. # # We insure the document of the given user has the requested attachment.
  98. # #
  99. # doc = self.dbase.get(self._id)
  100. # if '_attachments' in doc:
  101. # r = self.filename in doc['_attachments'].keys()
  102. # else:
  103. # r = False
  104. # return r
  105. def stream(self):
  106. #
  107. # @TODO Need to get this working ...
  108. #
  109. document = cloudant.document.Document(self.dbase,self._id)
  110. # content = self.dbase.fetch_attachment(self._id,self.filename).split('\n') ;
  111. content = self.get_attachment(self.filename)
  112. for row in content:
  113. yield row
  114. def read(self,**args):
  115. if self.filename is not None:
  116. self.stream()
  117. else:
  118. return self.basic_read()
  119. def basic_read(self):
  120. document = cloudant.document.Document(self.dbase,self._id)
  121. # document = self.dbase.get(self._id)
  122. if document.exists() :
  123. document.fetch()
  124. document = dict(document)
  125. del document['_rev']
  126. else:
  127. document = {}
  128. return document
  129. class CouchWriter(Couch,Writer):
  130. """
  131. This class will write on a couchdb document provided a scope
  132. The scope is the attribute that will be on the couchdb document
  133. """
  134. def __init__(self,**args):
  135. """
  136. @param uri host & port reference
  137. @param uid user id involved
  138. @param filename filename (attachment)
  139. @param dbname database name (target)
  140. """
  141. Couch.__init__(self,**args)
  142. def set (self,info):
  143. document = cloudand.document.Document(self.dbase,self._id)
  144. if document.exists() :
  145. keys = list(set(document.keys()) - set(['_id','_rev','_attachments']))
  146. for id in keys :
  147. document.field_set(document,id,None)
  148. for id in args :
  149. value = args[id]
  150. document.field_set(document,id,value)
  151. document.save()
  152. pass
  153. else:
  154. _document = dict({"_id":self._id},**args)
  155. document.create_document(_document)
  156. def write(self,info):
  157. """
  158. write a given attribute to a document database
  159. @info object to be written to the to an attribute. this
  160. """
  161. # document = self.dbase.get(self._id)
  162. document = cloudant.document.Document(self.dbase,self._id) #.get(self._id)
  163. if document.exists() is False :
  164. document = self.dbase.create_document({"_id":self._id})
  165. # label = params['label']
  166. # row = params['row']
  167. # if label not in document :
  168. # document[label] = []
  169. # document[label].append(row)
  170. for key in info :
  171. if key in document and type(document[key]) == list :
  172. document[key] += info[key]
  173. else:
  174. document[key] = info[key]
  175. document.save()
  176. # self.dbase.bulk_docs([document])
  177. # self.dbase.save_doc(document)
  178. def upload(self,**args):
  179. """
  180. :param name name of the file to be uploaded
  181. :param data content of the file (binary or text)
  182. :param content_type (default)
  183. """
  184. mimetype = args['content_type'] if 'content_type' in args else 'text/plain'
  185. document = cloudant.document.Document(self.dbase,self.uid)
  186. document.put_attachment(self.dbase,args['filename'],mimetype,args['content'])
  187. document.save()
  188. def archive(self,params=None):
  189. """
  190. This function will archive the document onto itself.
  191. """
  192. # document = self.dbase.all_docs(self._id,include_docs=True)
  193. document = cloudant.document.Document(self.dbase,self.filename)
  194. document.fetch()
  195. content = {}
  196. # _doc = {}
  197. for id in document:
  198. if id not in ['_id','_rev','_attachments'] :
  199. content[id] = document[id]
  200. del document[id]
  201. content = json.dumps(content)
  202. # document= _doc
  203. now = str(datetime.today())
  204. name = '-'.join([document['_id'] , now,'.json'])
  205. self.upload(filename=name,data=content,content_type='application/json')
  206. # self.dbase.bulk_docs([document])
  207. # self.dbase.put_attachment(document,content,name,'application/json')
  208. # document.put_attachment(self.dbase,name,'application/json',content)
  209. # document.save()