julen / pootle
- Source
- Commits
- Network (0)
- Issues (0)
- Downloads (0)
- Wiki (1)
- Graphs
-
Tree:
9caf544
murgilduta (author)
Wed Aug 06 23:38:17 -0700 2008
pootle / pootle.py
| ca3d8109 » | davidfraser | 2005-04-20 | 1 | #!/usr/bin/env python | |
| a953d6ab » | davidfraser | 2005-07-01 | 2 | # -*- coding: utf-8 -*- | |
| d8ec3e47 » | dwaynebailey | 2006-06-15 | 3 | # | |
| 4 | # Copyright 2004-2006 Zuza Software Foundation | ||||
| 5 | # | ||||
| 6 | # This file is part of translate. | ||||
| 7 | # | ||||
| 8 | # translate is free software; you can redistribute it and/or modify | ||||
| 9 | # it under the terms of the GNU General Public License as published by | ||||
| 10 | # the Free Software Foundation; either version 2 of the License, or | ||||
| 11 | # (at your option) any later version. | ||||
| 12 | # | ||||
| 13 | # translate is distributed in the hope that it will be useful, | ||||
| 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
| 16 | # GNU General Public License for more details. | ||||
| 17 | # | ||||
| 18 | # You should have received a copy of the GNU General Public License | ||||
| 19 | # along with translate; if not, write to the Free Software | ||||
| 20 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||||
| ca3d8109 » | davidfraser | 2005-04-20 | 21 | ||
| 22 | from jToolkit.web import server | ||||
| b00bca80 » | davidfraser | 2006-04-26 | 23 | from jToolkit.web import templateserver | |
| ca3d8109 » | davidfraser | 2005-04-20 | 24 | from jToolkit.web import session | |
| 25 | from jToolkit import prefs | ||||
| 26 | from jToolkit import localize | ||||
| 27 | from jToolkit.widgets import widgets | ||||
| 6ec9b636 » | davidfraser | 2005-06-28 | 28 | from jToolkit.widgets import spellui | |
| e76c8b73 » | friedelwolff | 2006-06-14 | 29 | from jToolkit.widgets import thumbgallery | |
| f64ab86c » | davidfraser | 2005-06-26 | 30 | from jToolkit.web import simplewebserver | |
| ca3d8109 » | davidfraser | 2005-04-20 | 31 | from Pootle import indexpage | |
| 32 | from Pootle import adminpages | ||||
| 33 | from Pootle import translatepage | ||||
| 34 | from Pootle import pagelayout | ||||
| 35 | from Pootle import projects | ||||
| 36 | from Pootle import potree | ||||
| db0d83a0 » | friedelwolff | 2007-06-20 | 37 | from Pootle import pootlefile | |
| ca3d8109 » | davidfraser | 2005-04-20 | 38 | from Pootle import users | |
| 6ec9b636 » | davidfraser | 2005-06-28 | 39 | from Pootle import filelocations | |
| 24ff0e2f » | andreaspauley | 2007-01-22 | 40 | from translate.misc import optrecurse | |
| 4a8b56ea » | dwaynebailey | 2006-07-18 | 41 | # Versioning information | |
| c677c29e » | dwaynebailey | 2006-06-01 | 42 | from Pootle import __version__ as pootleversion | |
| 43 | from translate import __version__ as toolkitversion | ||||
| 44 | from jToolkit import __version__ as jtoolkitversion | ||||
| 49ca02f8 » | winterstream | 2008-07-01 | 45 | from Pootle import statistics | |
| 08972f30 » | dwaynebailey | 2007-07-10 | 46 | try: | |
| 08083c40 » | friedelwolff | 2007-07-10 | 47 | from xml.etree import ElementTree | |
| 08972f30 » | dwaynebailey | 2007-07-10 | 48 | except ImportError: | |
| 49 | from elementtree import ElementTree | ||||
| 4cbd92c0 » | friedelwolff | 2006-07-10 | 50 | # We don't need kid in this file, but this will show quickly if it is not | |
| 51 | # installed. jToolkit won't complain, so we have to stop here if we don't have kid | ||||
| 52 | import kid | ||||
| ca3d8109 » | davidfraser | 2005-04-20 | 53 | import sys | |
| 54 | import os | ||||
| dfb6361c » | friedelwolff | 2007-05-16 | 55 | import re | |
| ca3d8109 » | davidfraser | 2005-04-20 | 56 | import random | |
| b00bca80 » | davidfraser | 2006-04-26 | 57 | import pprint | |
| ca3d8109 » | davidfraser | 2005-04-20 | 58 | ||
| b00bca80 » | davidfraser | 2006-04-26 | 59 | class PootleServer(users.OptionalLoginAppServer, templateserver.TemplateServer): | |
| ca3d8109 » | davidfraser | 2005-04-20 | 60 | """the Server that serves the Pootle Pages""" | |
| 61 | def __init__(self, instance, webserver, sessioncache=None, errorhandler=None, loginpageclass=users.LoginPage): | ||||
| 62 | if sessioncache is None: | ||||
| 63 | sessioncache = session.SessionCache(sessionclass=users.PootleSession) | ||||
| 64 | self.potree = potree.POTree(instance) | ||||
| 65 | super(PootleServer, self).__init__(instance, webserver, sessioncache, errorhandler, loginpageclass) | ||||
| b00bca80 » | davidfraser | 2006-04-26 | 66 | self.templatedir = filelocations.templatedir | |
| ca3d8109 » | davidfraser | 2005-04-20 | 67 | self.setdefaultoptions() | |
| 68 | |||||
| b00bca80 » | davidfraser | 2006-04-26 | 69 | def loadurl(self, filename, context): | |
| 70 | """loads a url internally for overlay code""" | ||||
| c677c29e » | dwaynebailey | 2006-06-01 | 71 | # print "call to load %s with context:\n%s" % (filename, pprint.pformat(context)) | |
| b00bca80 » | davidfraser | 2006-04-26 | 72 | filename = os.path.join(self.templatedir, filename+os.extsep+"html") | |
| 73 | if os.path.exists(filename): | ||||
| 74 | return open(filename, "r").read() | ||||
| 75 | return None | ||||
| 76 | |||||
| ca3d8109 » | davidfraser | 2005-04-20 | 77 | def saveprefs(self): | |
| 78 | """saves any changes made to the preferences""" | ||||
| 79 | # TODO: this is a hack, fix it up nicely :-) | ||||
| 80 | prefsfile = self.instance.__root__.__dict__["_setvalue"].im_self | ||||
| 81 | prefsfile.savefile() | ||||
| 82 | |||||
| 83 | def setdefaultoptions(self): | ||||
| 84 | """sets the default options in the preferences""" | ||||
| 85 | changed = False | ||||
| 86 | if not hasattr(self.instance, "title"): | ||||
| 87 | setattr(self.instance, "title", "Pootle Demo") | ||||
| 88 | changed = True | ||||
| 89 | if not hasattr(self.instance, "description"): | ||||
| 90 | defaultdescription = "This is a demo installation of pootle. The administrator can customize the description in the preferences." | ||||
| 91 | setattr(self.instance, "description", defaultdescription) | ||||
| 92 | changed = True | ||||
| 93 | if not hasattr(self.instance, "baseurl"): | ||||
| 94 | setattr(self.instance, "baseurl", "/") | ||||
| 95 | changed = True | ||||
| 0fc2f1aa » | friedelwolff | 2008-06-13 | 96 | if not hasattr(self.instance, "enablealtsrc"): | |
| 97 | setattr(self.instance, "enablealtsrc", False) | ||||
| 98 | changed = True | ||||
| ca3d8109 » | davidfraser | 2005-04-20 | 99 | if changed: | |
| 100 | self.saveprefs() | ||||
| 101 | |||||
| 102 | def changeoptions(self, argdict): | ||||
| 103 | """changes options on the instance""" | ||||
| 104 | for key, value in argdict.iteritems(): | ||||
| 105 | if not key.startswith("option-"): | ||||
| 106 | continue | ||||
| 107 | optionname = key.replace("option-", "", 1) | ||||
| 108 | setattr(self.instance, optionname, value) | ||||
| 109 | self.saveprefs() | ||||
| 110 | |||||
| 9fc02a32 » | friedelwolff | 2006-08-11 | 111 | def initlanguage(self, req, session): | |
| 112 | """Initialises the session language from the request""" | ||||
| 113 | availablelanguages = self.potree.getlanguagecodes('pootle') | ||||
| 114 | acceptlanguageheader = req.headers_in.getheader('Accept-Language') | ||||
| 115 | if not acceptlanguageheader: | ||||
| 116 | return | ||||
| 117 | |||||
| 118 | for langpref in acceptlanguageheader.split(","): | ||||
| 3fad1d0f » | friedelwolff | 2006-10-12 | 119 | langpref = pagelayout.localelanguage(langpref) | |
| 9fc02a32 » | friedelwolff | 2006-08-11 | 120 | pos = langpref.find(";") | |
| 121 | if pos >= 0: | ||||
| 122 | langpref = langpref[:pos] | ||||
| 123 | if langpref in availablelanguages: | ||||
| 124 | session.setlanguage(langpref) | ||||
| 125 | return | ||||
| 126 | elif langpref.startswith("en"): | ||||
| 127 | session.setlanguage(None) | ||||
| 128 | return | ||||
| 129 | session.setlanguage(None) | ||||
| 130 | |||||
| ca3d8109 » | davidfraser | 2005-04-20 | 131 | def inittranslation(self, localedir=None, localedomains=None, defaultlanguage=None): | |
| 132 | """initializes live translations using the Pootle PO files""" | ||||
| 133 | self.localedomains = ['jToolkit', 'pootle'] | ||||
| 134 | self.localedir = None | ||||
| 135 | self.languagelist = self.potree.getlanguagecodes('pootle') | ||||
| 45537b69 » | friedelwolff | 2006-08-11 | 136 | self.languagenames = self.potree.getlanguages() | |
| ca3d8109 » | davidfraser | 2005-04-20 | 137 | self.defaultlanguage = defaultlanguage | |
| 138 | if self.defaultlanguage is None: | ||||
| 7dbfaf87 » | dwaynebailey | 2005-05-14 | 139 | self.defaultlanguage = getattr(self.instance, "defaultlanguage", "en") | |
| ca3d8109 » | davidfraser | 2005-04-20 | 140 | if self.potree.hasproject(self.defaultlanguage, 'pootle'): | |
| 141 | try: | ||||
| 142 | self.translation = self.potree.getproject(self.defaultlanguage, 'pootle') | ||||
| 143 | return | ||||
| a211a05c » | friedelwolff | 2007-08-01 | 144 | except Exception, e: | |
| 145 | self.errorhandler.logerror("Could not initialize translation:\n%s" % str(e)) | ||||
| ca3d8109 » | davidfraser | 2005-04-20 | 146 | # if no translation available, set up a blank translation | |
| 147 | super(PootleServer, self).inittranslation() | ||||
| 45537b69 » | friedelwolff | 2006-08-11 | 148 | # the inherited method overwrites self.languagenames, so we have to redo it | |
| 9d0620b9 » | friedelwolff | 2006-08-11 | 149 | self.languagenames = self.potree.getlanguages() | |
| ca3d8109 » | davidfraser | 2005-04-20 | 150 | ||
| 151 | def gettranslation(self, language): | ||||
| 152 | """returns a translation object for the given language (or default if language is None)""" | ||||
| 153 | if language is None: | ||||
| 154 | return self.translation | ||||
| 155 | else: | ||||
| 156 | try: | ||||
| 157 | return self.potree.getproject(language, 'pootle') | ||||
| a211a05c » | friedelwolff | 2007-08-01 | 158 | except Exception, e: | |
| a3dbe57c » | friedelwolff | 2006-10-12 | 159 | if not language.startswith('en'): | |
| a211a05c » | friedelwolff | 2007-08-01 | 160 | self.errorhandler.logerror("Could not get translation for language %r:\n%s" % (language,str(e))) | |
| ca3d8109 » | davidfraser | 2005-04-20 | 161 | return self.translation | |
| 162 | |||||
| 5ccb20bc » | davidfraser | 2005-05-11 | 163 | def refreshstats(self, args): | |
| ca3d8109 » | davidfraser | 2005-04-20 | 164 | """refreshes all the available statistics...""" | |
| 5ccb20bc » | davidfraser | 2005-05-11 | 165 | if args: | |
| 166 | def filtererrorhandler(functionname, str1, str2, e): | ||||
| 167 | print "error in filter %s: %r, %r, %s" % (functionname, str1, str2, e) | ||||
| 168 | return False | ||||
| 034aa41a » | friedelwolff | 2007-07-18 | 169 | checkerclasses = [projects.checks.StandardChecker, projects.checks.StandardUnitChecker] | |
| c35ceb2c » | friedelwolff | 2007-07-18 | 170 | stdchecker = projects.checks.TeeChecker(checkerclasses=checkerclasses, errorhandler=filtererrorhandler) | |
| 5ccb20bc » | davidfraser | 2005-05-11 | 171 | for arg in args: | |
| 172 | if not os.path.exists(arg): | ||||
| 173 | print "file not found:", arg | ||||
| 174 | if os.path.isdir(arg): | ||||
| 65c42c53 » | davidfraser | 2005-06-15 | 175 | if not arg.endswith(os.sep): | |
| 176 | arg += os.sep | ||||
| 177 | projectcode, languagecode = self.potree.getcodesfordir(arg) | ||||
| 9e8f165b » | davidfraser | 2005-07-02 | 178 | dummyproject = projects.DummyStatsProject(arg, stdchecker, projectcode, languagecode) | |
| 5ccb20bc » | davidfraser | 2005-05-11 | 179 | def refreshdir(dummy, dirname, fnames): | |
| 65c42c53 » | davidfraser | 2005-06-15 | 180 | reldirname = dirname.replace(dummyproject.podir, "") | |
| 5ccb20bc » | davidfraser | 2005-05-11 | 181 | for fname in fnames: | |
| 65c42c53 » | davidfraser | 2005-06-15 | 182 | fpath = os.path.join(reldirname, fname) | |
| db0d83a0 » | friedelwolff | 2007-06-20 | 183 | fullpath = os.path.join(dummyproject.podir, fpath) | |
| 60d30ab2 » | friedelwolff | 2007-01-11 | 184 | #TODO: PO specific | |
| db0d83a0 » | friedelwolff | 2007-06-20 | 185 | if fname.endswith(".po") and not os.path.isdir(fullpath): | |
| 05cf18b0 » | friedelwolff | 2007-06-20 | 186 | if not os.path.exists(fullpath): | |
| 187 | print "file does not exist:", fullpath | ||||
| 188 | return | ||||
| 5ccb20bc » | davidfraser | 2005-05-11 | 189 | print "refreshing stats for", fpath | |
| db0d83a0 » | friedelwolff | 2007-06-20 | 190 | pootlefile.pootlefile(dummyproject, fpath).statistics.updatequickstats() | |
| 5ccb20bc » | davidfraser | 2005-05-11 | 191 | os.path.walk(arg, refreshdir, None) | |
| 65c42c53 » | davidfraser | 2005-06-15 | 192 | if projectcode and languagecode: | |
| 193 | dummyproject.savequickstats() | ||||
| 5ccb20bc » | davidfraser | 2005-05-11 | 194 | elif os.path.isfile(arg): | |
| 9e8f165b » | davidfraser | 2005-07-02 | 195 | dummyproject = projects.DummyStatsProject(".", stdchecker) | |
| 5ccb20bc » | davidfraser | 2005-05-11 | 196 | print "refreshing stats for", arg | |
| 197 | projects.pootlefile.pootlefile(dummyproject, arg) | ||||
| 198 | else: | ||||
| 199 | print "refreshing stats for all files in all projects" | ||||
| 200 | self.potree.refreshstats() | ||||
| ca3d8109 » | davidfraser | 2005-04-20 | 201 | ||
| 202 | def generateactivationcode(self): | ||||
| 203 | """generates a unique activation code""" | ||||
| 204 | return "".join(["%02x" % int(random.random()*0x100) for i in range(16)]) | ||||
| 205 | |||||
| 8512011e » | friedelwolff | 2006-08-10 | 206 | def generaterobotsfile(self): | |
| 207 | """generates the robots.txt file""" | ||||
| 208 | langcodes = self.potree.getlanguagecodes() | ||||
| 209 | excludedfiles = ["login.html", "register.html", "activate.html"] | ||||
| 210 | content = "User-agent: *\n" | ||||
| 211 | for excludedfile in excludedfiles: | ||||
| 212 | content += "Disallow: /%s\n" % excludedfile | ||||
| 213 | for langcode in langcodes: | ||||
| 214 | content += "Disallow: /%s/\n" % langcode | ||||
| 215 | return content | ||||
| 216 | |||||
| ca3d8109 » | davidfraser | 2005-04-20 | 217 | def getpage(self, pathwords, session, argdict): | |
| 218 | """return a page that will be sent to the user""" | ||||
| d8fa12d6 » | friedelwolff | 2006-08-10 | 219 | #Ensure we get unicode from argdict | |
| 220 | #TODO: remove when jToolkit does this | ||||
| 221 | newargdict = {} | ||||
| 222 | for key, value in argdict.iteritems(): | ||||
| 223 | if isinstance(key, str): | ||||
| 224 | key = key.decode("utf-8") | ||||
| 225 | if isinstance(value, str): | ||||
| 226 | value = value.decode("utf-8") | ||||
| 227 | newargdict[key] = value | ||||
| 228 | argdict = newargdict | ||||
| 84b22bcb » | friedelwolff | 2007-01-26 | 229 | ||
| 230 | # Strip of the base url | ||||
| dfb6361c » | friedelwolff | 2007-05-16 | 231 | baseurl = re.sub('http://[^/]', '', self.instance.baseurl) | |
| 84b22bcb » | friedelwolff | 2007-01-26 | 232 | # Split up and remove empty parts | |
| 233 | basepathwords = filter(None, baseurl.split('/')) | ||||
| 234 | while pathwords and basepathwords and basepathwords[0] == pathwords[0]: | ||||
| 235 | basepathwords = basepathwords[1:] | ||||
| ca3d8109 » | davidfraser | 2005-04-20 | 236 | pathwords = pathwords[1:] | |
| 84b22bcb » | friedelwolff | 2007-01-26 | 237 | ||
| ca3d8109 » | davidfraser | 2005-04-20 | 238 | if pathwords: | |
| 239 | top = pathwords[0] | ||||
| 240 | else: | ||||
| 241 | top = "" | ||||
| 6ec9b636 » | davidfraser | 2005-06-28 | 242 | if top == 'js': | |
| 243 | pathwords = pathwords[1:] | ||||
| 244 | jsfile = os.path.join(filelocations.htmldir, 'js', *pathwords) | ||||
| 245 | if not os.path.exists(jsfile): | ||||
| 246 | jsfile = os.path.join(filelocations.jtoolkitdir, 'js', *pathwords) | ||||
| 247 | if not os.path.exists(jsfile): | ||||
| 248 | return None | ||||
| 249 | jspage = widgets.PlainContents(None) | ||||
| 250 | jspage.content_type = "application/x-javascript" | ||||
| 251 | jspage.sendfile_path = jsfile | ||||
| e76c8b73 » | friedelwolff | 2006-06-14 | 252 | jspage.allowcaching = True | |
| 6ec9b636 » | davidfraser | 2005-06-28 | 253 | return jspage | |
| e76c8b73 » | friedelwolff | 2006-06-14 | 254 | elif pathwords and pathwords[-1].endswith(".css"): | |
| 255 | cssfile = os.path.join(filelocations.htmldir, *pathwords) | ||||
| 256 | if not os.path.exists(cssfile): | ||||
| 257 | cssfile = os.path.join(filelocations.jtoolkitdir, *pathwords) | ||||
| 258 | if not os.path.exists(cssfile): | ||||
| 259 | return None | ||||
| 260 | csspage = widgets.PlainContents(None) | ||||
| 261 | csspage.content_type = "text/css" | ||||
| 262 | csspage.sendfile_path = cssfile | ||||
| 263 | csspage.allowcaching = True | ||||
| 264 | return csspage | ||||
| 346c0e94 » | zejn | 2006-10-09 | 265 | elif top in ['selenium', 'tests']: | |
| 266 | picturefile = os.path.join(filelocations.htmldir, *pathwords) | ||||
| 6fdfe625 » | zejn | 2006-10-09 | 267 | picture = widgets.SendFile(picturefile) | |
| 268 | if picturefile.endswith(".html"): | ||||
| 269 | picture.content_type = 'text/html' | ||||
| 270 | elif picturefile.endswith(".js"): | ||||
| 271 | picture.content_type = 'text/javascript' | ||||
| 272 | picture.allowcaching = True | ||||
| 273 | return picture | ||||
| e76c8b73 » | friedelwolff | 2006-06-14 | 274 | elif top == 'images': | |
| 275 | pathwords = pathwords[1:] | ||||
| 276 | picturefile = os.path.join(filelocations.htmldir, 'images', *pathwords) | ||||
| 277 | picture = widgets.SendFile(picturefile) | ||||
| 278 | picture.content_type = thumbgallery.getcontenttype(pathwords[-1]) | ||||
| 279 | picture.allowcaching = True | ||||
| 280 | return picture | ||||
| f7cfaa5b » | friedelwolff | 2006-08-04 | 281 | elif pathwords and pathwords[-1].endswith(".ico"): | |
| e6f8376e » | friedelwolff | 2006-08-03 | 282 | picturefile = os.path.join(filelocations.htmldir, *pathwords) | |
| 283 | picture = widgets.SendFile(picturefile) | ||||
| 284 | picture.content_type = 'image/ico' | ||||
| 285 | picture.allowcaching = True | ||||
| 286 | return picture | ||||
| 8512011e » | friedelwolff | 2006-08-10 | 287 | elif top == "robots.txt": | |
| 288 | robotspage = widgets.PlainContents(self.generaterobotsfile()) | ||||
| 289 | robotspage.content_type = 'text/plain' | ||||
| 290 | robotspage.allowcaching = True | ||||
| 291 | return robotspage | ||||
| b00bca80 » | davidfraser | 2006-04-26 | 292 | elif top == "testtemplates.html": | |
| 293 | return templateserver.TemplateServer.getpage(self, pathwords, session, argdict) | ||||
| 6ec9b636 » | davidfraser | 2005-06-28 | 294 | elif not top or top == "index.html": | |
| ca3d8109 » | davidfraser | 2005-04-20 | 295 | return indexpage.PootleIndex(self.potree, session) | |
| 296 | elif top == 'about.html': | ||||
| 297 | return indexpage.AboutPage(session) | ||||
| 298 | elif top == "login.html": | ||||
| 299 | if session.isopen: | ||||
| 60069444 » | davidfraser | 2005-05-20 | 300 | returnurl = argdict.get('returnurl', None) or getattr(self.instance, 'homepage', 'home/') | |
| ca3d8109 » | davidfraser | 2005-04-20 | 301 | return server.Redirect(returnurl) | |
| 986213fe » | friedelwolff | 2006-07-19 | 302 | message = None | |
| ca3d8109 » | davidfraser | 2005-04-20 | 303 | if 'username' in argdict: | |
| 304 | session.username = argdict["username"] | ||||
| d4b5e43b » | friedelwolff | 2006-09-15 | 305 | message = session.localize("Login failed") | |
| 986213fe » | friedelwolff | 2006-07-19 | 306 | return users.LoginPage(session, languagenames=self.languagenames, message=message) | |
| ca3d8109 » | davidfraser | 2005-04-20 | 307 | elif top == "register.html": | |
| 308 | return self.registerpage(session, argdict) | ||||
| 309 | elif top == "activate.html": | ||||
| 310 | return self.activatepage(session, argdict) | ||||
| 311 | elif top == "projects": | ||||
| 312 | pathwords = pathwords[1:] | ||||
| 313 | if pathwords: | ||||
| 314 | top = pathwords[0] | ||||
| 315 | else: | ||||
| 316 | top = "" | ||||
| 317 | if not top or top == "index.html": | ||||
| 318 | return indexpage.ProjectsIndex(self.potree, session) | ||||
| 319 | else: | ||||
| 320 | projectcode = top | ||||
| 321 | if not self.potree.hasproject(None, projectcode): | ||||
| 322 | return None | ||||
| 323 | pathwords = pathwords[1:] | ||||
| 324 | if pathwords: | ||||
| 325 | top = pathwords[0] | ||||
| 326 | else: | ||||
| 327 | top = "" | ||||
| 328 | if not top or top == "index.html": | ||||
| 329 | return indexpage.ProjectLanguageIndex(self.potree, projectcode, session) | ||||
| 330 | elif top == "admin.html": | ||||
| 331 | return adminpages.ProjectAdminPage(self.potree, projectcode, session, argdict) | ||||
| 332 | elif top == "languages": | ||||
| 333 | pathwords = pathwords[1:] | ||||
| 334 | if pathwords: | ||||
| 335 | top = pathwords[0] | ||||
| 336 | else: | ||||
| 337 | top = "" | ||||
| 338 | if not top or top == "index.html": | ||||
| 339 | return indexpage.LanguagesIndex(self.potree, session) | ||||
| 340 | elif top == "home": | ||||
| 341 | pathwords = pathwords[1:] | ||||
| 342 | if pathwords: | ||||
| 343 | top = pathwords[0] | ||||
| 344 | else: | ||||
| 345 | top = "" | ||||
| 346 | if not session.isopen: | ||||
| b00bca80 » | davidfraser | 2006-04-26 | 347 | templatename = "redirect" | |
| 348 | templatevars = { | ||||
| 349 | "pagetitle": session.localize("Redirecting to login..."), | ||||
| 350 | "refresh": 1, | ||||
| 351 | "refreshurl": "login.html", | ||||
| 352 | "message": session.localize("Need to log in to access home page"), | ||||
| 353 | } | ||||
| 354 | pagelayout.completetemplatevars(templatevars, session) | ||||
| 355 | return server.Redirect("../login.html", withtemplate=(templatename, templatevars)) | ||||
| ca3d8109 » | davidfraser | 2005-04-20 | 356 | if not top or top == "index.html": | |
| 357 | return indexpage.UserIndex(self.potree, session) | ||||
| 358 | elif top == "options.html": | ||||
| d4b5e43b » | friedelwolff | 2006-09-15 | 359 | message = None | |
| 360 | try: | ||||
| 361 | if "changeoptions" in argdict: | ||||
| 362 | session.setoptions(argdict) | ||||
| 363 | if "changepersonal" in argdict: | ||||
| 364 | session.setpersonaloptions(argdict) | ||||
| 365 | message = session.localize("Personal details updated") | ||||
| 366 | if "changeinterface" in argdict: | ||||
| 367 | session.setinterfaceoptions(argdict) | ||||
| 368 | except users.RegistrationError, errormessage: | ||||
| 369 | message = errormessage | ||||
| 370 | return users.UserOptions(self.potree, session, message) | ||||
| ca3d8109 » | davidfraser | 2005-04-20 | 371 | elif top == "admin": | |
| 372 | pathwords = pathwords[1:] | ||||
| 373 | if pathwords: | ||||
| 374 | top = pathwords[0] | ||||
| 375 | else: | ||||
| 376 | top = "" | ||||
| 377 | if not session.isopen: | ||||
| b00bca80 » | davidfraser | 2006-04-26 | 378 | templatename = "redirect" | |
| 379 | templatevars = { | ||||
| 380 | "pagetitle": session.localize("Redirecting to login..."), | ||||
| 381 | "refresh": 1, | ||||
| 382 | "refreshurl": "login.html", | ||||
| 383 | "message": session.localize("Need to log in to access admin page"), | ||||
| 384 | } | ||||
| 385 | pagelayout.completetemplatevars(templatevars, session) | ||||
| 386 | return server.Redirect("../login.html", withtemplate=(templatename, templatevars)) | ||||
| ca3d8109 » | davidfraser | 2005-04-20 | 387 | if not session.issiteadmin(): | |
| b00bca80 » | davidfraser | 2006-04-26 | 388 | templatename = "redirect" | |
| 389 | templatevars = { | ||||
| 390 | "pagetitle": session.localize("Redirecting to home..."), | ||||
| 391 | "refresh": 1, | ||||
| 392 | "refreshurl": "login.html", | ||||
| 393 | "message": self.localize("You do not have the rights to administer pootle."), | ||||
| 394 | } | ||||
| 395 | pagelayout.completetemplatevars(templatevars, session) | ||||
| 396 | return server.Redirect("../index.html", withtemplate=(templatename, templatevars)) | ||||
| ca3d8109 » | davidfraser | 2005-04-20 | 397 | if not top or top == "index.html": | |
| 398 | if "changegeneral" in argdict: | ||||
| 399 | self.changeoptions(argdict) | ||||
| 400 | return adminpages.AdminPage(self.potree, session, self.instance) | ||||
| 401 | elif top == "users.html": | ||||
| 402 | if "changeusers" in argdict: | ||||
| 403 | self.changeusers(session, argdict) | ||||
| 404 | return adminpages.UsersAdminPage(self, session.loginchecker.users, session, self.instance) | ||||
| 405 | elif top == "languages.html": | ||||
| 406 | if "changelanguages" in argdict: | ||||
| 407 | self.potree.changelanguages(argdict) | ||||
| 408 | return adminpages.LanguagesAdminPage(self.potree, session, self.instance) | ||||
| 409 | elif top == "projects.html": | ||||
| 410 | if "changeprojects" in argdict: | ||||
| 411 | self.potree.changeprojects(argdict) | ||||
| 412 | return adminpages.ProjectsAdminPage(self.potree, session, self.instance) | ||||
| da21d7a3 » | davidfraser | 2005-06-26 | 413 | elif top == "templates" or self.potree.haslanguage(top): | |
| ca3d8109 » | davidfraser | 2005-04-20 | 414 | languagecode = top | |
| 415 | pathwords = pathwords[1:] | ||||
| 416 | if pathwords: | ||||
| 417 | top = pathwords[0] | ||||
| 149fbd4c » | davidfraser | 2005-07-02 | 418 | bottom = pathwords[-1] | |
| ca3d8109 » | davidfraser | 2005-04-20 | 419 | else: | |
| 420 | top = "" | ||||
| 149fbd4c » | davidfraser | 2005-07-02 | 421 | bottom = "" | |
| ca3d8109 » | davidfraser | 2005-04-20 | 422 | if not top or top == "index.html": | |
| 423 | return indexpage.LanguageIndex(self.potree, languagecode, session) | ||||
| 424 | if self.potree.hasproject(languagecode, top): | ||||
| 425 | projectcode = top | ||||
| 426 | project = self.potree.getproject(languagecode, projectcode) | ||||
| 427 | pathwords = pathwords[1:] | ||||
| 428 | if pathwords: | ||||
| 429 | top = pathwords[0] | ||||
| 430 | else: | ||||
| 431 | top = "" | ||||
| 432 | if not top or top == "index.html": | ||||
| 149fbd4c » | davidfraser | 2005-07-02 | 433 | return indexpage.ProjectIndex(project, session, argdict) | |
| ca3d8109 » | davidfraser | 2005-04-20 | 434 | elif top == "admin.html": | |
| 435 | return adminpages.TranslationProjectAdminPage(self.potree, project, session, argdict) | ||||
| 149fbd4c » | davidfraser | 2005-07-02 | 436 | elif bottom == "translate.html": | |
| 437 | if len(pathwords) > 1: | ||||
| ca3d8109 » | davidfraser | 2005-04-20 | 438 | dirfilter = os.path.join(*pathwords[:-1]) | |
| 149fbd4c » | davidfraser | 2005-07-02 | 439 | else: | |
| 440 | dirfilter = "" | ||||
| ca3d8109 » | davidfraser | 2005-04-20 | 441 | try: | |
| 442 | return translatepage.TranslatePage(project, session, argdict, dirfilter) | ||||
| 443 | except projects.RightsError, stoppedby: | ||||
| 444 | argdict["message"] = str(stoppedby) | ||||
| 445 | return indexpage.ProjectIndex(project, session, argdict, dirfilter) | ||||
| 6ec9b636 » | davidfraser | 2005-06-28 | 446 | elif bottom == "spellcheck.html": | |
| 447 | # the full review page | ||||
| f19ac49b » | davidfraser | 2005-06-28 | 448 | argdict["spellchecklang"] = languagecode | |
| 6ec9b636 » | davidfraser | 2005-06-28 | 449 | return spellui.SpellingReview(session, argdict, js_url="/js/spellui.js") | |
| 450 | elif bottom == "spellingstandby.html": | ||||
| 451 | # a simple 'loading' page | ||||
| 452 | return spellui.SpellingStandby() | ||||
| 149fbd4c » | davidfraser | 2005-07-02 | 453 | elif bottom.endswith("." + project.fileext): | |
| 454 | pofilename = os.path.join(*pathwords) | ||||
| 455 | if argdict.get("translate", 0): | ||||
| ca3d8109 » | davidfraser | 2005-04-20 | 456 | try: | |
| 457 | return translatepage.TranslatePage(project, session, argdict, dirfilter=pofilename) | ||||
| 458 | except projects.RightsError, stoppedby: | ||||
| 86a0f80b » | friedelwolff | 2007-01-26 | 459 | if len(pathwords) > 1: | |
| 460 | dirfilter = os.path.join(*pathwords[:-1]) | ||||
| 461 | else: | ||||
| 462 | dirfilter = "" | ||||
| ca3d8109 » | davidfraser | 2005-04-20 | 463 | argdict["message"] = str(stoppedby) | |
| 86a0f80b » | friedelwolff | 2007-01-26 | 464 | return indexpage.ProjectIndex(project, session, argdict, dirfilter=dirfilter) | |
| 149fbd4c » | davidfraser | 2005-07-02 | 465 | elif argdict.get("index", 0): | |
| ca3d8109 » | davidfraser | 2005-04-20 | 466 | return indexpage.ProjectIndex(project, session, argdict, dirfilter=pofilename) | |
| 149fbd4c » | davidfraser | 2005-07-02 | 467 | else: | |
| 468 | pofile = project.getpofile(pofilename, freshen=False) | ||||
| 469 | page = widgets.SendFile(pofile.filename) | ||||
| 690b6e7f » | davidfraser | 2005-06-27 | 470 | page.etag = str(pofile.pomtime) | |
| e94dbf4b » | andreaspauley | 2007-03-30 | 471 | encoding = getattr(pofile, "encoding", "UTF-8") | |
| 149fbd4c » | davidfraser | 2005-07-02 | 472 | page.content_type = "text/plain; charset=%s" % encoding | |
| 473 | return page | ||||
| d9352980 » | friedelwolff | 2007-07-12 | 474 | elif bottom.endswith(".csv") or bottom.endswith(".xlf") or bottom.endswith(".ts") or bottom.endswith(".po") or bottom.endswith(".mo"): | |
| beaaea10 » | davidfraser | 2005-07-02 | 475 | destfilename = os.path.join(*pathwords) | |
| 476 | basename, extension = os.path.splitext(destfilename) | ||||
| 477 | pofilename = basename + os.extsep + project.fileext | ||||
| 478 | extension = extension[1:] | ||||
| 479 | if extension == "mo": | ||||
| 480 | if not "pocompile" in project.getrights(session): | ||||
| 481 | return None | ||||
| 482 | etag, filepath_or_contents = project.convert(pofilename, extension) | ||||
| 483 | if etag: | ||||
| 484 | page = widgets.SendFile(filepath_or_contents) | ||||
| 61a37290 » | davidfraser | 2005-07-02 | 485 | page.etag = str(etag) | |
| beaaea10 » | davidfraser | 2005-07-02 | 486 | else: | |
| 487 | page = widgets.PlainContents(filepath_or_contents) | ||||
| ce7bf39b » | dwaynebailey | 2008-06-04 | 488 | if extension == "po": | |
| 489 | page.content_type = "text/x-gettext-translation; charset=UTF-8" | ||||
| 490 | elif extension == "csv": | ||||
| 491 | page.content_type = "text/csv; charset=UTF-8" | ||||
| 492 | elif extension == "xlf": | ||||
| 493 | page.content_type = "application/x-xliff; charset=UTF-8" | ||||
| 494 | elif extension == "ts": | ||||
| 495 | page.content_type = "application/x-linguist; charset=UTF-8" | ||||
| beaaea10 » | davidfraser | 2005-07-02 | 496 | elif extension == "mo": | |
| ce7bf39b » | dwaynebailey | 2008-06-04 | 497 | page.content_type = "application/x-gettext-translation" | |
| 149fbd4c » | davidfraser | 2005-07-02 | 498 | return page | |
| ca3d8109 » | davidfraser | 2005-04-20 | 499 | elif bottom.endswith(".zip"): | |
| 500 | if not "archive" in project.getrights(session): | ||||
| 501 | return None | ||||
| 149fbd4c » | davidfraser | 2005-07-02 | 502 | if len(pathwords) > 1: | |
| ca3d8109 » | davidfraser | 2005-04-20 | 503 | dirfilter = os.path.join(*pathwords[:-1]) | |
| 149fbd4c » | davidfraser | 2005-07-02 | 504 | else: | |
| 505 | dirfilter = None | ||||
| ca3d8109 » | davidfraser | 2005-04-20 | 506 | goal = argdict.get("goal", None) | |
| 507 | if goal: | ||||
| 92cd5464 » | dwaynebailey | 2005-04-28 | 508 | goalfiles = project.getgoalfiles(goal) | |
| ca3d8109 » | davidfraser | 2005-04-20 | 509 | pofilenames = [] | |
| 510 | for goalfile in goalfiles: | ||||
| 511 | pofilenames.extend(project.browsefiles(goalfile)) | ||||
| 512 | else: | ||||
| 513 | pofilenames = project.browsefiles(dirfilter) | ||||
| 514 | archivecontents = project.getarchive(pofilenames) | ||||
| 515 | page = widgets.PlainContents(archivecontents) | ||||
| 516 | page.content_type = "application/zip" | ||||
| 517 | return page | ||||
| 79086cc5 » | friedelwolff | 2006-03-16 | 518 | elif bottom.endswith(".sdf") or bottom.endswith(".sgi"): | |
| 519 | if not "pocompile" in project.getrights(session): | ||||
| 520 | return None | ||||
| 521 | oocontents = project.getoo() | ||||
| 522 | page = widgets.PlainContents(oocontents) | ||||
| 523 | page.content_type = "text/tab-seperated-values" | ||||
| 524 | return page | ||||
| 149fbd4c » | davidfraser | 2005-07-02 | 525 | elif bottom == "index.html": | |
| ca3d8109 » | davidfraser | 2005-04-20 | 526 | if len(pathwords) > 1: | |
| 527 | dirfilter = os.path.join(*pathwords[:-1]) | ||||
| 528 | else: | ||||
| 529 | dirfilter = None | ||||
| 149fbd4c » | davidfraser | 2005-07-02 | 530 | return indexpage.ProjectIndex(project, session, argdict, dirfilter) | |
| 531 | else: | ||||
| 532 | return indexpage.ProjectIndex(project, session, argdict, os.path.join(*pathwords)) | ||||
| ca3d8109 » | davidfraser | 2005-04-20 | 533 | return None | |
| 534 | |||||
| f64ab86c » | davidfraser | 2005-06-26 | 535 | class PootleOptionParser(simplewebserver.WebOptionParser): | |
| 536 | def __init__(self): | ||||
| 4a8b56ea » | dwaynebailey | 2006-07-18 | 537 | versionstring = "%%prog %s\njToolkit %s\nTranslate Toolkit %s\nKid %s\nElementTree %s\nPython %s (on %s/%s)" % (pootleversion.ver, jtoolkitversion.ver, toolkitversion.ver, kid.__version__, ElementTree.VERSION, sys.version, sys.platform, os.name) | |
| c677c29e » | dwaynebailey | 2006-06-01 | 538 | simplewebserver.WebOptionParser.__init__(self, version=versionstring) | |
| 6ec9b636 » | davidfraser | 2005-06-28 | 539 | self.set_default('prefsfile', filelocations.prefsfile) | |
| f64ab86c » | davidfraser | 2005-06-26 | 540 | self.set_default('instance', 'Pootle') | |
| 6ec9b636 » | davidfraser | 2005-06-28 | 541 | self.set_default('htmldir', filelocations.htmldir) | |
| f64ab86c » | davidfraser | 2005-06-26 | 542 | self.add_option('', "--refreshstats", dest="action", action="store_const", const="refreshstats", | |
| 543 | default="runwebserver", help="refresh the stats files instead of running the webserver") | ||||
| 884dce24 » | dwaynebailey | 2006-07-25 | 544 | psycomodes=["none", "full", "profile"] | |
| 49ca02f8 » | winterstream | 2008-07-01 | 545 | self.add_option('', "--statsdb_file", action="store", type="string", dest="statsdb_file", | |
| 546 | default=None, help="Specifies the location of the SQLite stats db file.") | ||||
| e3f83065 » | winterstream | 2008-07-29 | 547 | self.add_option('', "--profile", action="store", type="string", dest="profile", | |
| 548 | help="Perform profiling, storing the result to the supplied filename.") | ||||
| 884dce24 » | dwaynebailey | 2006-07-25 | 549 | try: | |
| 550 | import psyco | ||||
| 551 | self.add_option('', "--psyco", dest="psyco", default=None, choices=psycomodes, metavar="MODE", | ||||
| 552 | help="use psyco to speed up the operation, modes: %s" % (", ".join(psycomodes))) | ||||
| 9818f854 » | friedelwolff | 2008-02-15 | 553 | except ImportError, e: | |
| 884dce24 » | dwaynebailey | 2006-07-25 | 554 | return | |
| f64ab86c » | davidfraser | 2005-06-26 | 555 | ||
| 6f0926b9 » | dwaynebailey | 2006-06-15 | 556 | def checkversions(): | |
| 557 | """Checks that version dependencies are met""" | ||||
| 4f8bdad6 » | friedelwolff | 2008-03-18 | 558 | if not hasattr(toolkitversion, "build") or toolkitversion.build < 11000: | |
| 559 | raise RuntimeError("requires Translate Toolkit version >= 1.1. Current installed version is: %s" % toolkitversion.ver) | ||||
| 6f0926b9 » | dwaynebailey | 2006-06-15 | 560 | ||
| 884dce24 » | dwaynebailey | 2006-07-25 | 561 | def usepsyco(options): | |
| 562 | # options.psyco == None means the default, which is "full", but don't give a warning... | ||||
| 563 | # options.psyco == "none" means don't use psyco at all... | ||||
| 9aefe93c » | friedelwolff | 2006-07-28 | 564 | if getattr(options, "psyco", "none") == "none": | |
| 884dce24 » | dwaynebailey | 2006-07-25 | 565 | return | |
| 566 | try: | ||||
| 567 | import psyco | ||||
| 88aa19f2 » | andreaspauley | 2007-01-16 | 568 | except ImportError: | |
| 884dce24 » | dwaynebailey | 2006-07-25 | 569 | if options.psyco is not None: | |
| 24ff0e2f » | andreaspauley | 2007-01-22 | 570 | optrecurse.RecursiveOptionParser(formats={}).warning("psyco unavailable", options, sys.exc_info()) | |
| 884dce24 » | dwaynebailey | 2006-07-25 | 571 | return | |
| 572 | if options.psyco is None: | ||||
| 573 | options.psyco = "full" | ||||
| 574 | if options.psyco == "full": | ||||
| 575 | psyco.full() | ||||
| 576 | elif options.psyco == "profile": | ||||
| 577 | psyco.profile() | ||||
| 578 | # tell psyco the functions it cannot compile, to prevent warnings | ||||
| 579 | import encodings | ||||
| 580 | psyco.cannotcompile(encodings.search_function) | ||||
| 581 | |||||
| e3f83065 » | winterstream | 2008-07-29 | 582 | def profile_runner(server, options): | |
| 583 | import cProfile | ||||
| f6e14048 » | winterstream | 2008-08-04 | 584 | import Pootle.profiling.lsprofcalltree as lsprofcalltree | |
| e3f83065 » | winterstream | 2008-07-29 | 585 | ||
| 586 | def write_cache_grind(profiler, file): | ||||
| 587 | k_cache_grind = lsprofcalltree.KCacheGrind(profiler) | ||||
| 588 | k_cache_grind.output(file) | ||||
| 589 | file.close() | ||||
| 590 | |||||
| 591 | def do_profile_run(file): | ||||
| 592 | profiler = cProfile.Profile() | ||||
| 593 | try: | ||||
| 594 | profiler.runcall(simplewebserver.run, server, options) | ||||
| 595 | finally: | ||||
| 596 | write_cache_grind(profiler, file) | ||||
| 597 | |||||
| 598 | try: | ||||
| 599 | profile_file = open(options.profile, "w+") | ||||
| 600 | do_profile_run(profile_file) | ||||
| 601 | except IOError, _e: | ||||
| 602 | print "Could not open profiling file %s" % (options.profile,) | ||||
| 603 | |||||
| 604 | def get_runner(options): | ||||
| 605 | if getattr(options, "profile", None) != None: | ||||
| 606 | return profile_runner | ||||
| 607 | else: | ||||
| 608 | return simplewebserver.run | ||||
| 609 | |||||
| ca3d8109 » | davidfraser | 2005-04-20 | 610 | def main(): | |
| 611 | # run the web server | ||||
| 6f0926b9 » | dwaynebailey | 2006-06-15 | 612 | checkversions() | |
| f64ab86c » | davidfraser | 2005-06-26 | 613 | parser = PootleOptionParser() | |
| ca3d8109 » | davidfraser | 2005-04-20 | 614 | options, args = parser.parse_args() | |
| 24ff0e2f » | andreaspauley | 2007-01-22 | 615 | options.errorlevel = options.logerrors | |
| 884dce24 » | dwaynebailey | 2006-07-25 | 616 | usepsyco(options) | |
| 49ca02f8 » | winterstream | 2008-07-01 | 617 | statistics.STATS_DB_FILE = options.statsdb_file | |
| f814f294 » | davidfraser | 2005-06-30 | 618 | if options.action != "runwebserver": | |
| 619 | options.servertype = "dummy" | ||||
| ca3d8109 » | davidfraser | 2005-04-20 | 620 | server = parser.getserver(options) | |
| 7900c171 » | friedelwolff | 2006-08-16 | 621 | server.options = options | |
| ca3d8109 » | davidfraser | 2005-04-20 | 622 | if options.action == "runwebserver": | |
| e3f83065 » | winterstream | 2008-07-29 | 623 | run = get_runner(options) | |
| 624 | run(server, options) | ||||
| ca3d8109 » | davidfraser | 2005-04-20 | 625 | elif options.action == "refreshstats": | |
| 5ccb20bc » | davidfraser | 2005-05-11 | 626 | server.refreshstats(args) | |
| ca3d8109 » | davidfraser | 2005-04-20 | 627 | ||
| 628 | if __name__ == '__main__': | ||||
| 629 | main() | ||||
| 630 | |||||
