couchdb.py 6.1 KB

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