Home | Trees | Indices | Help |
|
---|
|
1 """ 2 Common functions and classes for services and cores. 3 """ 4 5 #c Copyright 2008-2019, the GAVO project 6 #c 7 #c This program is free software, covered by the GNU GPL. See the 8 #c COPYING file in the source distribution. 9 10 11 import re 12 import os 13 14 from nevow import inevow 15 from nevow import loaders 16 17 import pkg_resources 18 19 from gavo import base 20 from gavo import utils 27 34 41 4649 """raised to initiate an authentication request. 50 51 Authenticates are optionally constructed with the realm the user 52 shall authenticate in. If you leave the realm out, the DC-wide default 53 will be used. 54 """59 7073 """raised to redirect a user agent to a different resource (HTTP 301). 74 75 WebRedirectes are constructed with the destination URL that can be 76 relative (to webRoot) or absolute (starting with http). 77 """7881 """raised to redirect a user agent to a different resource (HTTP 303). 82 83 SeeOthers are constructed with the destination URL that can be 84 relative (to webRoot) or absolute (starting with http). 85 86 They are essentially like WebRedirect, except they put out a 303 87 instead of a 301. 88 """8991 """raised to redirect a user agent to a different resource (HTTP 302). 92 93 Found instances are constructed with the destination URL that can be 94 relative (to webRoot) or absolute (starting with http). 95 96 They are essentially like WebRedirect, except they put out a 302 97 instead of a 301. 98 """99102 """returns a tuple of resourceDescriptor, serviceName. 103 104 A serivce id consists of an inputsDir-relative path to a resource 105 descriptor, a slash, and the name of a service within this descriptor. 106 107 This function returns a tuple of inputsDir-relative path and service name. 108 It raises a gavo.Error if sid has an invalid format. The existence of 109 the resource or the service are not checked. 110 """ 111 return "/".join(serviceParts[:-1]), serviceParts[-1]112115 """A class keeping information on the query environment. 116 117 It is constructed with a plain dictionary (there are alternative 118 constructors for nevow contexts and requests are below) mapping 119 certain keys (you'll currently have to figure out which from the 120 source) to values, mostly strings, except for the keys listed in 121 listKeys, which should be sequences of strings. 122 123 If you pass an empty dict, some sane defaults will be used. You 124 can get that "empty" query meta as common.emptyQueryMeta, but make 125 sure you don't mutate it. 126 127 QueryMetas constructed from request will have the user and password 128 items filled out. 129 130 If you're using nevow formal, you should set the formal_data item 131 to the dictionary created by formal. This will let people use 132 the parsed parameters in templates. 133 """ 134 135 # a set of keys handled by query meta to be ignored in parameter 136 # lists because they are used internally. This covers everything 137 # QueryMeta interprets, but also keys by introduced by certain gwidgets 138 # and the nevow infrastructure 139 metaKeys = set(["_FILTER", "_OUTPUT", "_charset_", "_ADDITEM", 140 "__nevow_form__", "_FORMAT", "_VERB", "_TDENC", "formal_data", 141 "_SET", "_TIMEOUT", "_VOTABLE_VERSION", "FORMAT"]) 142 143 # a set of keys that have sequences as values (needed for construction 144 # from nevow request.args) 145 listKeys = set(["_ADDITEM", "_DBOPTIONS_ORDER", "_SET"]) 146294 295 296 emptyQueryMeta = QueryMeta()148 if initArgs is None: 149 initArgs = {} 150 self.ctxArgs = utils.CaseSemisensitiveDict(initArgs) 151 if defaultLimit is None: 152 self.defaultLimit = base.getConfig("db", "defaultLimit") 153 else: 154 self.defaultLimit = defaultLimit 155 self["formal_data"] = {} 156 self["user"] = self["password"] = None 157 self["accept"] = {} 158 self._fillOutput(self.ctxArgs) 159 self._fillDbOptions(self.ctxArgs) 160 self._fillSet(self.ctxArgs)161 162 @classmethod164 """constructs a QueryMeta from a nevow web arguments dictionary. 165 """ 166 args = {} 167 for key, value in nevowArgs.iteritems(): 168 # defense against broken legacy code: listify if necessay 169 if not isinstance(value, list): 170 value = [value] 171 172 if key in cls.listKeys: 173 args[key] = value 174 else: 175 if value: 176 args[key] = value[0] 177 return cls(args, **kwargs)178 179 @classmethod181 """constructs a QueryMeta from a nevow request. 182 183 In addition to getting information from the arguments, this 184 also sets user and password. 185 """ 186 res = cls.fromNevowArgs(request.args, **kwargs) 187 res["accept"] = utils.parseAccept(request.getHeader("accept")) 188 res["user"], res["password"] = request.getUser(), request.getPassword() 189 return res190 191 @classmethod193 """constructs a QueryMeta from a nevow context. 194 """ 195 return cls.fromRequest(inevow.IRequest(ctx), **kwargs)196198 """interprets values left by the OutputFormat widget. 199 """ 200 if "RESPONSEFORMAT" in args: 201 self["format"] = args["RESPONSEFORMAT"] 202 else: 203 self["format"] = args.get("_FORMAT", "HTML") 204 205 try: 206 # prefer fine-grained "verbosity" over _VERB or VERB 207 # Hack: malformed _VERBs result in None verbosity, which is taken to 208 # mean about "use fields of HTML". Absent _VERB or VERB, on the other 209 # hand, means VERB=2, i.e., a sane default 210 if "verbosity" in args: 211 self["verbosity"] = int(args["verbosity"]) 212 elif "_VERB" in args: # internal verb parameter 213 self["verbosity"] = int(args["_VERB"])*10 214 elif "VERB" in args: # verb parameter for SCS and such 215 self["verbosity"] = int(args["VERB"])*10 216 else: 217 self["verbosity"] = 20 218 except ValueError: 219 self["verbosity"] = "HTML" # VERB given, but not an int. 220 221 self["tdEnc"] = base.getConfig("ivoa", "votDefaultEncoding")=="td" 222 if "_TDENC" in args: 223 try: 224 self["tdEnc"] = base.parseBooleanLiteral(args["_TDENC"]) 225 except ValueError: 226 pass 227 228 try: 229 self["VOTableVersion"] = tuple(int(v) for v in 230 args["_VOTABLE_VERSION"].split(".")) 231 except: # simple ignore malformed version specs 232 pass 233 234 self["additionalFields"] = args.get("_ADDITEM", [])235237 """interprets the output of a ColumnSet widget. 238 """ 239 self["columnSet"] = None 240 if "_SET" in args: 241 self["columnSet"] = set(args["_SET"])242244 self["dbSortKeys"] = [s.strip() 245 for s in args.get("_DBOPTIONS_ORDER", []) if s.strip()] 246 247 self["direction"] = {"ASC": "ASC", "DESC": "DESC"}[ 248 args.get("_DBOPTIONS_DIR", "ASC")] 249 250 try: 251 self["dbLimit"] = int(args["MAXREC"]) 252 except (ValueError, KeyError): 253 self["dbLimit"] = self.defaultLimit 254 255 try: 256 self["timeout"] = int(args["_TIMEOUT"]) 257 except (ValueError, KeyError): 258 self["timeout"] = base.getConfig("web", "sqlTimeout")259260 - def overrideDbOptions(self, sortKeys=None, limit=None, sortFallback=None, 261 direction=None):262 if sortKeys is not None: 263 self["dbSortKeys"] = sortKeys 264 if not self["dbSortKeys"] and sortFallback is not None: 265 self["dbSortKeys"] = sortFallback.split(",") 266 if limit is not None: 267 self["dbLimit"] = int(limit) 268 if direction is not None: 269 self["direction"] = direction270272 """returns the dbLimit and dbSortKey values as an SQL fragment. 273 """ 274 frag, pars = [], {} 275 sortKeys = self["dbSortKeys"] 276 dbLimit = self["dbLimit"] 277 # TODO: Sorting needs a thorough redesign, presumably giving column instance 278 # as column keys. These could carry "default up" or "default down" in 279 # properties. Meanwhile, there should be a UI to let users decide on 280 # sort direction. 281 # Meanwhile, let's to an emergency hack. 282 if sortKeys: 283 # Ok, we need to do some emergency securing here. There should be 284 # pre-validation that we're actually seeing a column key, but 285 # just in case let's make sure we're seeing an SQL identifier. 286 # (We can't rely on dbapi's escaping since we're not talking values here) 287 frag.append("ORDER BY %s %s"%(",".join( 288 re.sub('[^A-Za-z0-9"_]+', "", key) for key in sortKeys), 289 self["direction"])) 290 if dbLimit: 291 frag.append("LIMIT %(_matchLimit)s") 292 pars["_matchLimit"] = int(dbLimit)+1 293 return " ".join(frag), pars300 """see loadSystemTemplate. 301 """ 302 userPath = os.path.join(base.getConfig("rootDir"), "web/templates", key) 303 if os.path.exists(userPath): 304 return userPath 305 else: 306 resPath = "resources/templates/"+key 307 if pkg_resources.resource_exists('gavo', resPath): 308 return pkg_resources.resource_filename('gavo', resPath)309312 """returns a nevow template for system pages from key. 313 314 path is interpreted as relative to gavo_root/web/templates (first) 315 and package internal (last). If no template is found, None is 316 returned (this harmonizes with the fallback in CustomTemplateMixin). 317 """ 318 try: 319 tp = getTemplatePath(key) 320 if tp is not None: 321 return loaders.xmlfile(tp) 322 except IOError: 323 pass324
Home | Trees | Indices | Help |
|
---|
Generated by Epydoc 3.0.1 on Thu May 2 07:29:09 2019 | http://epydoc.sourceforge.net |