Package gluon :: Module admin
[hide private]
[frames] | no frames]

Source Code for Module gluon.admin

  1  """ 
  2  This file is part of the web2py Web Framework 
  3  Copyrighted by Massimo Di Pierro <mdipierro@cs.depaul.edu> 
  4  License: LGPLv3 (http://www.gnu.org/licenses/lgpl.html) 
  5   
  6  Utility functions for the Admin application 
  7  =========================================== 
  8  """ 
  9  import os 
 10  import sys 
 11  import traceback 
 12  import zipfile 
 13  import urllib 
 14  from shutil import rmtree 
 15  from gluon.utils import web2py_uuid 
 16  from gluon.fileutils import w2p_pack, w2p_unpack, w2p_pack_plugin, w2p_unpack_plugin 
 17  from gluon.fileutils import up, fix_newlines, abspath, recursive_unlink 
 18  from gluon.fileutils import read_file, write_file, parse_version 
 19  from gluon.restricted import RestrictedError 
 20  from gluon.settings import global_settings 
 21   
 22   
 23  if not global_settings.web2py_runtime_gae: 
 24      import site 
 25   
 26   
27 -def apath(path='', r=None):
28 """ 29 Builds a path inside an application folder 30 31 Parameters 32 ---------- 33 path: 34 path within the application folder 35 r: 36 the global request object 37 38 """ 39 40 opath = up(r.folder) 41 while path[:3] == '../': 42 (opath, path) = (up(opath), path[3:]) 43 return os.path.join(opath, path).replace('\\', '/')
44 45
46 -def app_pack(app, request, raise_ex=False, filenames=None):
47 """ 48 Builds a w2p package for the application 49 50 Parameters 51 ---------- 52 app: 53 application name 54 request: 55 the global request object 56 57 Returns 58 ------- 59 filename: 60 filename of the w2p file or None on error 61 """ 62 try: 63 if filenames is None: app_cleanup(app, request) 64 filename = apath('../deposit/web2py.app.%s.w2p' % app, request) 65 w2p_pack(filename, apath(app, request), filenames=filenames) 66 return filename 67 except Exception, e: 68 if raise_ex: 69 raise 70 return False
71 72
73 -def app_pack_compiled(app, request, raise_ex=False):
74 """ 75 Builds a w2p bytecode-compiled package for the application 76 77 Parameters 78 ---------- 79 app: 80 application name 81 request: 82 the global request object 83 84 Returns 85 ------- 86 filename: 87 filename of the w2p file or None on error 88 """ 89 90 try: 91 filename = apath('../deposit/%s.w2p' % app, request) 92 w2p_pack(filename, apath(app, request), compiled=True) 93 return filename 94 except Exception, e: 95 if raise_ex: 96 raise 97 return None
98 99
100 -def app_cleanup(app, request):
101 """ 102 Removes session, cache and error files 103 104 Parameters 105 ---------- 106 app: 107 application name 108 request: 109 the global request object 110 """ 111 r = True 112 113 # Remove error files 114 path = apath('%s/errors/' % app, request) 115 if os.path.exists(path): 116 for f in os.listdir(path): 117 try: 118 if f[:1] != '.': os.unlink(os.path.join(path, f)) 119 except IOError: 120 r = False 121 122 # Remove session files 123 path = apath('%s/sessions/' % app, request) 124 if os.path.exists(path): 125 for f in os.listdir(path): 126 try: 127 if f[:1] != '.': recursive_unlink(os.path.join(path, f)) 128 except IOError: 129 r = False 130 131 # Remove cache files 132 path = apath('%s/cache/' % app, request) 133 if os.path.exists(path): 134 for f in os.listdir(path): 135 try: 136 if f[:1] != '.': os.unlink(os.path.join(path, f)) 137 except IOError: 138 r = False 139 return r
140 141
142 -def app_compile(app, request):
143 """ 144 Compiles the application 145 146 Parameters 147 ---------- 148 app: 149 application name 150 request: 151 the global request object 152 """ 153 from compileapp import compile_application, remove_compiled_application 154 folder = apath(app, request) 155 try: 156 compile_application(folder) 157 return None 158 except (Exception, RestrictedError): 159 tb = traceback.format_exc(sys.exc_info) 160 remove_compiled_application(folder) 161 return tb
162 163
164 -def app_create(app, request, force=False, key=None, info=False):
165 """ 166 Create a copy of welcome.w2p (scaffolding) app 167 168 Parameters 169 ---------- 170 app: 171 application name 172 request: 173 the global request object 174 175 """ 176 path = apath(app, request) 177 if not os.path.exists(path): 178 try: 179 os.mkdir(path) 180 except: 181 if info: 182 return False, traceback.format_exc(sys.exc_info) 183 else: 184 return False 185 elif not force: 186 if info: 187 return False, "Application exists" 188 else: 189 return False 190 try: 191 w2p_unpack('welcome.w2p', path) 192 for subfolder in [ 193 'models', 'views', 'controllers', 'databases', 194 'modules', 'cron', 'errors', 'sessions', 'cache', 195 'languages', 'static', 'private', 'uploads']: 196 subpath = os.path.join(path, subfolder) 197 if not os.path.exists(subpath): 198 os.mkdir(subpath) 199 db = os.path.join(path, 'models', 'db.py') 200 if os.path.exists(db): 201 data = read_file(db) 202 data = data.replace('<your secret key>', 203 'sha512:' + (key or web2py_uuid())) 204 write_file(db, data) 205 if info: 206 return True, None 207 else: 208 return True 209 except: 210 rmtree(path) 211 if info: 212 return False, traceback.format_exc(sys.exc_info) 213 else: 214 return False
215 216
217 -def app_install(app, fobj, request, filename, overwrite=None):
218 """ 219 Installs an application: 220 221 - Identifies file type by filename 222 - Writes `fobj` contents to the `../deposit/` folder 223 - Calls `w2p_unpack()` to do the job. 224 225 Parameters 226 ---------- 227 app: 228 new application name 229 fobj: 230 file object containing the application to be installed 231 request: 232 the global request object 233 filename: 234 original filename of the `fobj`, required to determine extension 235 236 Returns 237 ------- 238 upname: 239 name of the file where app is temporarily stored or `None` on failure 240 """ 241 did_mkdir = False 242 if filename[-4:] == '.w2p': 243 extension = 'w2p' 244 elif filename[-7:] == '.tar.gz': 245 extension = 'tar.gz' 246 else: 247 extension = 'tar' 248 upname = apath('../deposit/%s.%s' % (app, extension), request) 249 250 try: 251 write_file(upname, fobj.read(), 'wb') 252 path = apath(app, request) 253 if not overwrite: 254 os.mkdir(path) 255 did_mkdir = True 256 w2p_unpack(upname, path) 257 if extension != 'tar': 258 os.unlink(upname) 259 fix_newlines(path) 260 return upname 261 except Exception: 262 if did_mkdir: 263 rmtree(path) 264 return False
265 266
267 -def app_uninstall(app, request):
268 """ 269 Uninstalls the application. 270 271 Parameters 272 ---------- 273 app: 274 application name 275 request: 276 the global request object 277 278 Returns 279 ------- 280 `True` on success, `False` on failure 281 """ 282 try: 283 # Hey App, this is your end... 284 path = apath(app, request) 285 rmtree(path) 286 return True 287 except Exception: 288 return False
289 290
291 -def plugin_pack(app, plugin_name, request):
292 """ 293 Builds a w2p package for the application 294 295 Parameters 296 ---------- 297 app: 298 application name 299 plugin_name: 300 the name of the plugin without plugin_ prefix 301 request: 302 the current request app 303 304 Returns 305 ------- 306 filename: 307 filename of the w2p file or None on error 308 """ 309 try: 310 filename = apath( 311 '../deposit/web2py.plugin.%s.w2p' % plugin_name, request) 312 w2p_pack_plugin(filename, apath(app, request), plugin_name) 313 return filename 314 except Exception: 315 return False
316 317
318 -def plugin_install(app, fobj, request, filename):
319 """ 320 Installs an application: 321 322 - Identifies file type by filename 323 - Writes `fobj` contents to the `../deposit/` folder 324 - Calls `w2p_unpack()` to do the job. 325 326 Parameters 327 ---------- 328 app: 329 new application name 330 fobj: 331 file object containing the application to be installed 332 request: 333 the global request object 334 filename: 335 original filename of the `fobj`, required to determine extension 336 337 Returns 338 ------- 339 upname: 340 name of the file where app is temporarily stored or `None` on failure 341 """ 342 343 upname = apath('../deposit/%s' % filename, request) 344 345 try: 346 write_file(upname, fobj.read(), 'wb') 347 path = apath(app, request) 348 w2p_unpack_plugin(upname, path) 349 fix_newlines(path) 350 return upname 351 except Exception: 352 os.unlink(upname) 353 return False
354 355
356 -def check_new_version(myversion, version_url):
357 """ 358 Compares current web2py's version with the latest stable web2py version. 359 360 Parameters 361 ---------- 362 myversion: 363 the current version as stored in file `web2py/VERSION` 364 version_URL: 365 the URL that contains the version of the latest stable release 366 367 Returns 368 ------- 369 state: 370 `True` if upgrade available, `False` if current version if up-to-date, 371 -1 on error 372 version: 373 the most up-to-version available 374 """ 375 try: 376 from urllib import urlopen 377 version = urlopen(version_url).read() 378 pversion = parse_version(version) 379 pmyversion = parse_version(myversion) 380 except IOError: 381 import traceback 382 print traceback.format_exc() 383 return -1, myversion 384 385 if pversion[:3]+pversion[-6:] > pmyversion[:3]+pmyversion[-6:]: 386 return True, version 387 else: 388 return False, version
389 390
391 -def unzip(filename, dir, subfolder=''):
392 """ 393 Unzips filename into dir (.zip only, no .gz etc) 394 if subfolder!='' it unzip only files in subfolder 395 """ 396 filename = abspath(filename) 397 if not zipfile.is_zipfile(filename): 398 raise RuntimeError('Not a valid zipfile') 399 zf = zipfile.ZipFile(filename) 400 if not subfolder.endswith('/'): 401 subfolder += '/' 402 n = len(subfolder) 403 for name in sorted(zf.namelist()): 404 if not name.startswith(subfolder): 405 continue 406 #print name[n:] 407 if name.endswith('/'): 408 folder = os.path.join(dir, name[n:]) 409 if not os.path.exists(folder): 410 os.mkdir(folder) 411 else: 412 write_file(os.path.join(dir, name[n:]), zf.read(name), 'wb')
413 414
415 -def upgrade(request, url='http://web2py.com'):
416 """ 417 Upgrades web2py (src, osx, win) is a new version is posted. 418 It detects whether src, osx or win is running and downloads the right one 419 420 Parameters 421 ---------- 422 request: 423 the current request object, required to determine version and path 424 url: 425 the incomplete url where to locate the latest web2py 426 actual url is url+'/examples/static/web2py_(src|osx|win).zip' 427 428 Returns 429 ------- 430 True on success, False on failure (network problem or old version) 431 """ 432 web2py_version = request.env.web2py_version 433 gluon_parent = request.env.gluon_parent 434 if not gluon_parent.endswith('/'): 435 gluon_parent += '/' 436 (check, version) = check_new_version(web2py_version, 437 url + '/examples/default/version') 438 if not check: 439 return False, 'Already latest version' 440 if os.path.exists(os.path.join(gluon_parent, 'web2py.exe')): 441 version_type = 'win' 442 destination = gluon_parent 443 subfolder = 'web2py/' 444 elif gluon_parent.endswith('/Contents/Resources/'): 445 version_type = 'osx' 446 destination = gluon_parent[:-len('/Contents/Resources/')] 447 subfolder = 'web2py/web2py.app/' 448 else: 449 version_type = 'src' 450 destination = gluon_parent 451 subfolder = 'web2py/' 452 453 full_url = url + '/examples/static/web2py_%s.zip' % version_type 454 filename = abspath('web2py_%s_downloaded.zip' % version_type) 455 try: 456 write_file(filename, urllib.urlopen(full_url).read(), 'wb') 457 except Exception, e: 458 return False, e 459 try: 460 unzip(filename, destination, subfolder) 461 return True, None 462 except Exception, e: 463 return False, e
464 465
466 -def add_path_first(path):
467 sys.path = [path] + [p for p in sys.path if ( 468 not p == path and not p == (path + '/'))] 469 if not global_settings.web2py_runtime_gae: 470 site.addsitedir(path)
471 472
473 -def create_missing_folders():
474 if not global_settings.web2py_runtime_gae: 475 for path in ('applications', 'deposit', 'site-packages', 'logs'): 476 path = abspath(path, gluon=True) 477 if not os.path.exists(path): 478 os.mkdir(path) 479 paths = (global_settings.gluon_parent, abspath( 480 'site-packages', gluon=True), abspath('gluon', gluon=True), '') 481 [add_path_first(path) for path in paths]
482 483
484 -def create_missing_app_folders(request):
485 if not global_settings.web2py_runtime_gae: 486 if request.folder not in global_settings.app_folders: 487 for subfolder in ('models', 'views', 'controllers', 'databases', 488 'modules', 'cron', 'errors', 'sessions', 489 'languages', 'static', 'private', 'uploads'): 490 path = os.path.join(request.folder, subfolder) 491 if not os.path.exists(path): 492 os.mkdir(path) 493 global_settings.app_folders.add(request.folder)
494