Package couchdbkit :: Package ext :: Package django :: Module loading
[hide private]
[frames] | no frames]

Source Code for Module couchdbkit.ext.django.loading

  1  # -*- coding: utf-8 -*- 
  2  # 
  3  # Copyright (c) 2008-2009 Benoit Chesneau <benoitc@e-engura.com> 
  4  # 
  5  # Permission to use, copy, modify, and distribute this software for any 
  6  # purpose with or without fee is hereby granted, provided that the above 
  7  # copyright notice and this permission notice appear in all copies. 
  8  # 
  9  # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 
 10  # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 
 11  # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 
 12  # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 
 13  # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 
 14  # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
 15  # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 
 16   
 17  """ 
 18  Maintain registry of documents used in your django project 
 19  and manage db sessions 
 20  """ 
 21   
 22  import sys 
 23  import os 
 24   
 25  from restkit import BasicAuth 
 26  from couchdbkit import Server 
 27  from couchdbkit import push 
 28  from couchdbkit.resource import CouchdbResource 
 29  from couchdbkit.exceptions import ResourceNotFound 
 30  from django.conf import settings 
 31  from django.utils.datastructures import SortedDict 
 32   
 33  COUCHDB_DATABASES = getattr(settings, "COUCHDB_DATABASES", []) 
 34  COUCHDB_TIMEOUT = getattr(settings, "COUCHDB_TIMEOUT", 300) 
 35   
36 -class CouchdbkitHandler(object):
37 """ The couchdbkit handler for django """ 38 39 # share state between instances 40 __shared_state__ = dict( 41 _databases = {}, 42 app_schema = SortedDict() 43 ) 44
45 - def __init__(self, databases):
46 """ initialize couchdbkit handler with COUCHDB_DATABASES 47 settings """ 48 49 self.__dict__ = self.__shared_state__ 50 51 # Convert old style to new style 52 if isinstance(databases, (list, tuple)): 53 databases = dict( 54 (app_name, {'URL': uri}) for app_name, uri in databases 55 ) 56 57 # create databases sessions 58 for app_name, app_setting in databases.iteritems(): 59 uri = app_setting['URL'] 60 61 # Blank credentials are valid for the admin party 62 user = app_setting.get('USER', '') 63 password = app_setting.get('PASSWORD', '') 64 auth = BasicAuth(user, password) 65 66 try: 67 if isinstance(uri, (list, tuple)): 68 # case when you want to specify server uri 69 # and database name specifically. usefull 70 # when you proxy couchdb on some path 71 server_uri, dbname = uri 72 else: 73 server_uri, dbname = uri.rsplit("/", 1) 74 except ValueError: 75 raise ValueError("couchdb uri [%s:%s] invalid" % ( 76 app_name, uri)) 77 78 res = CouchdbResource(server_uri, timeout=COUCHDB_TIMEOUT, filters=[auth]) 79 80 server = Server(server_uri, resource_instance=res) 81 app_label = app_name.split('.')[-1] 82 self._databases[app_label] = (server, dbname)
83
84 - def sync(self, app, verbosity=2, temp=None):
85 """ used to sync views of all applications and eventually create 86 database. 87 88 When temp is specified, it is appended to the app's name on the docid. 89 It can then be updated in the background and copied over the existing 90 design docs to reduce blocking time of view updates """ 91 app_name = app.__name__.rsplit('.', 1)[0] 92 app_labels = set() 93 schema_list = self.app_schema.values() 94 for schema_dict in schema_list: 95 for schema in schema_dict.values(): 96 app_module = schema.__module__.rsplit(".", 1)[0] 97 if app_module == app_name and not schema._meta.app_label in app_labels: 98 app_labels.add(schema._meta.app_label) 99 for app_label in app_labels: 100 if not app_label in self._databases: 101 continue 102 if verbosity >=1: 103 print "sync `%s` in CouchDB" % app_name 104 db = self.get_db(app_label) 105 106 app_path = os.path.abspath(os.path.join(sys.modules[app.__name__].__file__, "..")) 107 design_path = "%s/%s" % (app_path, "_design") 108 if not os.path.isdir(design_path): 109 if settings.DEBUG: 110 print >>sys.stderr, "%s don't exists, no ddoc synchronized" % design_path 111 return 112 113 if temp: 114 design_name = '%s-%s' % (app_label, temp) 115 else: 116 design_name = app_label 117 118 docid = "_design/%s" % design_name 119 120 push(os.path.join(app_path, "_design"), db, force=True, 121 docid=docid) 122 123 if temp: 124 ddoc = db[docid] 125 view_names = ddoc.get('views', {}).keys() 126 if len(view_names) > 0: 127 if verbosity >= 1: 128 print 'Triggering view rebuild' 129 130 view = '%s/%s' % (design_name, view_names[0]) 131 list(db.view(view, limit=0))
132 133
134 - def copy_designs(self, app, temp, verbosity=2, delete=True):
135 """ Copies temporary view over the existing ones 136 137 This is used to reduce the waiting time for blocking view updates """ 138 139 app_name = app.__name__.rsplit('.', 1)[0] 140 app_label = app_name.split('.')[-1] 141 if app_label in self._databases: 142 if verbosity >=1: 143 print "Copy prepared design docs for `%s`" % app_name 144 db = self.get_db(app_label) 145 146 tmp_name = '%s-%s' % (app_label, temp) 147 148 from_id = '_design/%s' % tmp_name 149 to_id = '_design/%s' % app_label 150 151 try: 152 db.copy_doc(from_id, to_id) 153 154 if delete: 155 del db[from_id] 156 157 except ResourceNotFound: 158 print '%s not found.' % (from_id, ) 159 return
160 161
162 - def get_db(self, app_label, register=False):
163 """ retrieve db session for a django application """ 164 if register: 165 return 166 167 db = self._databases[app_label] 168 if isinstance(db, tuple): 169 server, dbname = db 170 db = server.get_or_create_db(dbname) 171 self._databases[app_label] = db 172 return db
173
174 - def register_schema(self, app_label, *schema):
175 """ register a Document object""" 176 for s in schema: 177 schema_name = schema[0].__name__.lower() 178 schema_dict = self.app_schema.setdefault(app_label, SortedDict()) 179 if schema_name in schema_dict: 180 fname1 = os.path.abspath(sys.modules[s.__module__].__file__) 181 fname2 = os.path.abspath(sys.modules[schema_dict[schema_name].__module__].__file__) 182 if os.path.splitext(fname1)[0] == os.path.splitext(fname2)[0]: 183 continue 184 schema_dict[schema_name] = s
185
186 - def get_schema(self, app_label, schema_name):
187 """ retriev Document object from its name and app name """ 188 return self.app_schema.get(app_label, SortedDict()).get(schema_name.lower())
189 190 couchdbkit_handler = CouchdbkitHandler(COUCHDB_DATABASES) 191 register_schema = couchdbkit_handler.register_schema 192 get_schema = couchdbkit_handler.get_schema 193 get_db = couchdbkit_handler.get_db 194