1 """
2 VOResource capability/interface elements.
3
4 The basic mapping from our RD elements to VOResource elements is that
5 each renderer on a service translates to a capability with one interface.
6 Thus, in the module we mostly deal with publication objects. If you
7 need the service object, use publication.parent.
8 """
9
10
11
12
13
14
15
16 import urlparse
17
18 from gavo import base
19 from gavo import svcs
20 from gavo import utils
21 from gavo.base import meta
22 from gavo.base import osinter
23 from gavo.registry import tableset
24 from gavo.registry.model import (
25 VOR, VOG, VS, SIA, SCS, SLAP, SSAP, TR, DOC)
26
27
28
29
30
40
41
48
49
56
57
58
59
61 """An encapsulation of interface construction.
62
63 Each interface maker corresponds to a renderer and thus a publication on a
64 service. It knows enough about the characteristics of a renderer to create
65 interface stan by just calling.
66
67 This class is abstract. To build concrete interface makers, at
68 least fill out the class variables. You will probably want
69 to override the _makeInterface method for some renderers corresponding
70 so specially defined interfaces; the default implementation corresponds
71 to the VOResource definition.
72 """
73 renderer = None
74 interfaceClass = VOR.interface
75
111
114
115
119
120
123
126
129
130
132 """An InterfaceMaker on a publication sporting input parameters.
133
134 This corresponds to a ParamHTTP interface.
135 """
136 interfaceClass = VS.ParamHTTP
137
150
151
155
159
163
167
171
178
182
190
191
201
202
206
207
216
217
224
225
227 """An InterfaceMaker on a publication to be consumed by a web browser.
228
229 This is abstract since various renderers boil down to this.
230 """
231 interfaceClass = VOR.WebBrowser
232
233
236
239
242
243
244
245
248
251
254
257
260
263
264
265 _getInterfaceMaker = utils.buildClassResolver(InterfaceMaker,
266 globals().values(), instances=True,
267 key=lambda obj: obj.renderer,
268 default=InterfaceWithParams())
269
270
272 """returns the appropriate interface definition for service and renderer.
273 """
274 return _getInterfaceMaker(publication.render)(publication)
275
276
277
278
279
281 """An encapsulation of capability construction.
282
283 Each capability (currently) corresponds to a renderer.
284
285 You will want to override (some of) the class variables at the top, plus the
286 _makeCapability method (that you'll probably still want to upcall for the
287 basic functionality).
288
289 In particular, you will typically want to override capabilityClass
290 with a stanxml element spitting out the right standardIds.
291
292 Additionally, if the capability should also appear in data collections
293 served by a service with the capability, also define auxiliaryId (that's
294 an IVOID like ivo://ivoa.net/std/TAP#aux). These are used in
295 getCapabilityElement.
296
297 CapabilityMakers are used by calling them.
298 """
299 renderer = None
300 capabilityClass = VOR.capability
301 auxiliaryId = None
302
308
311
312
314 """A capability maker for gerneric VR.capabilities.
315
316 These essentially just set standardId. in addition to what
317 the plain capabilities do.
318 """
319 standardId = None
320
324
325
328
329
331 renderer = "siap.xml"
332 capabilityClass = SIA.capability
333 auxiliaryId = "ivo://ivoa.net/std/SIA#aux"
334
336 service = publication.parent
337 return CapabilityMaker._makeCapability(self, publication)[
338 SIA.imageServiceType[service.getMeta("sia.type", raiseOnFail=True)],
339 SIA.maxQueryRegionSize[
340 SIA.long[service.getMeta("sia.maxQueryRegionSize.long", default=None)],
341 SIA.lat[service.getMeta("sia.maxQueryRegionSize.lat", default=None)],
342 ],
343 SIA.maxImageExtent[
344 SIA.long[service.getMeta("sia.maxImageExtent.long", default=None)],
345 SIA.lat[service.getMeta("sia.maxImageExtent.lat", default=None)],
346 ],
347 SIA.maxImageSize[
348 service.getMeta("sia.maxImageSize", default=None),
349 ],
350 SIA.maxFileSize[
351 service.getMeta("sia.maxFileSize", default=None),
352 ],
353 SIA.maxRecords[
354 service.getMeta("sia.maxRecords",
355 default=str(base.getConfig("ivoa", "dalHardLimit"))),
356 ],
357 SIA.testQuery[
358 SIA.pos[
359 SIA.long[service.getMeta("testQuery.pos.ra")],
360 SIA.lat[service.getMeta("testQuery.pos.dec")],
361 ],
362 SIA.size[
363 SIA.long[service.getMeta("testQuery.size.ra")],
364 SIA.lat[service.getMeta("testQuery.size.dec")],
365 ],
366 ],
367 ]
368
369
374
375
377 renderer = "scs.xml"
378 capabilityClass = SCS.capability
379
381 service = publication.service
382 return CapabilityMaker._makeCapability(self, publication)[
383 SCS.maxSR[base.getMetaText(service, "maxSR", "180")],
384 SCS.maxRecords[str(base.getConfig("ivoa", "dalDefaultLimit")*10)],
385 SCS.verbosity["true"],
386 SCS.testQuery[
387 SCS.ra[service.getMeta("testQuery.ra", raiseOnFail=True)],
388 SCS.dec[service.getMeta("testQuery.dec", raiseOnFail=True)],
389 SCS.sr[service.getMeta("testQuery.sr", default="0.001")],
390 ],
391 ]
392
393
395 renderer = "ssap.xml"
396 capabilityClass = SSAP.capability
397
399 service = publication.parent
400 return CapabilityMaker._makeCapability(self, publication)[
401
402 SSAP.complianceLevel[
403 service.getMeta("ssap.complianceLevel", default="minimal")],
404 SSAP.dataSource[service.getMeta("ssap.dataSource", raiseOnFail=True)],
405 SSAP.creationType[service.getMeta("ssap.creationType",
406 default="archival")],
407 SSAP.supportedFrame["ICRS"],
408 SSAP.maxSearchRadius["180"],
409 SSAP.maxRecords[str(base.getConfig("ivoa", "dalHardLimit"))],
410 SSAP.defaultMaxRecords[str(base.getConfig("ivoa", "dalDefaultLimit"))],
411 SSAP.maxAperture["180"],
412 SSAP.testQuery[
413 SSAP.queryDataCmd[base.getMetaText(service, "ssap.testQuery",
414 raiseOnFail=True)+"&REQUEST=queryData"]],
415 ]
416
417
432
433
434 _tapModelBuilder = meta.ModelBasedBuilder([
435 ('supportsModel', meta.stanFactory(TR.dataModel), (),
436 {"ivoId": "ivoId"})])
437
439 renderer = "tap"
440 capabilityClass = TR.capability
441 auxiliaryId = "ivo://ivoa.net/std/TAP#aux"
442
444 res = CapabilityMaker._makeCapability(self, publication)
445
446 with base.getTableConn() as conn:
447 from gavo.protocols import tap
448 from gavo.adql import ufunctions
449
450 res[[
451 TR.dataModel(ivoId=dmivoid)[dmname]
452 for dmname, dmivoid in conn.query(
453 "select dmname, dmivorn from tap_schema.supportedmodels")]]
454
455 res[
456
457
458
459 [TR.language[
460 TR.name[langName],
461 [TR.version(ivoId=ivoId)[version]
462 for version, ivoId in versions],
463 TR.description[description],
464 TR.languageFeatures(
465 type="ivo://ivoa.net/std/TAPRegExt#features-udf")[
466 [TR.feature[
467 TR.form[udf.adqlUDF_signature],
468 TR.description[udf.adqlUDF_doc]]
469 for udf in ufunctions.UFUNC_REGISTRY.values()]],
470
471 TR.languageFeatures(
472 type="ivo://ivoa.net/std/TAPRegExt#features-adqlgeo")[
473 [TR.feature[
474 TR.form[funcName]]
475 for funcName in ("BOX", "POINT", "CIRCLE", "POLYGON",
476 "REGION", "CENTROID", "COORD1", "COORD2",
477 "DISTANCE", "CONTAINS", "INTERSECTS", "AREA")]],
478
479 TR.languageFeatures(
480 type="ivo://ivoa.net/std/TAPRegExt#features-adql-string")[
481 [TR.feature[
482 TR.form[funcName]]
483 for funcName in ("LOWER", "ILIKE")]],
484
485 TR.languageFeatures(
486 type="ivo://ivoa.net/std/TAPRegExt#features-adql-offset")[
487 [TR.feature[
488 TR.form[funcName]]
489 for funcName in ("OFFSET",)]],
490
491 TR.languageFeatures(
492 type="ivo://ivoa.net/std/TAPRegExt#features-adql-type")[
493 [TR.feature[
494 TR.form[funcName]]
495 for funcName in ("CAST",)]],
496
497 TR.languageFeatures(
498 type="ivo://ivoa.net/std/TAPRegExt#features-adql-unit")[
499 [TR.feature[
500 TR.form[funcName]]
501 for funcName in ("IN_UNIT",)]],
502
503 TR.languageFeatures(
504 type="ivo://ivoa.net/std/TAPRegExt#features-adql-common-table")[
505 [TR.feature[
506 TR.form[funcName]]
507 for funcName in ("WITH",)]],
508
509 TR.languageFeatures(
510 type="ivo://ivoa.net/std/TAPRegExt#features-adql-sets")[
511 [TR.feature[
512 TR.form[funcName]]
513 for funcName in ("UNION", "EXCEPT", "INTERSECT")]]]
514 for langName, description, versions
515 in tap.getSupportedLanguages()],
516 [TR.outputFormat(ivoId=ivoId)[
517 TR.mime[mime],
518 [TR.alias[alias] for alias in aliases]]
519 for mime, aliases, description, ivoId
520 in tap.getSupportedOutputFormats()],
521 [TR.uploadMethod(ivoId="ivo://ivoa.net/std/TAPRegExt#%s"%proto)
522 for proto in tap.UPLOAD_METHODS],
523 TR.retentionPeriod[
524 TR.default[str(base.getConfig("async", "defaultLifetime"))]],
525 TR.executionDuration[
526 TR.default[str(base.getConfig("async", "defaultExecTime"))]],
527 TR.outputLimit[
528 TR.default(unit="row")[
529 str(base.getConfig("async", "defaultMAXREC"))],
530 TR.hard(unit="row")[
531 str(base.getConfig("async", "hardMAXREC"))]],
532 TR.uploadLimit[
533 TR.hard(unit="byte")[
534 str(base.getConfig("web", "maxUploadSize"))]]]
535
536 return res
537
538
545
546
551
552
556
560
564
568
571
574
577
580
583
586
589
592
595
598
601
602
608
609
615
616
622
623
643
644
645 _getCapabilityMaker = utils.buildClassResolver(CapabilityMaker,
646 globals().values(), instances=True,
647 key=lambda obj: obj.renderer)
648
649
651 """returns a VR.capability element for an auxiliary publication.
652
653 That's a plain capability with essentially the interface and a
654 standardId obtained from the auxiliaryId attribute of the
655 capability's normal maker.
656
657 If no auxiliaryId is defined, None is returned (which means no
658 capability will be generated).
659 """
660 capMaker = _getCapabilityMaker(publication.render)
661 if capMaker.auxiliaryId:
662 return CapabilityMaker()(publication)(standardID=capMaker.auxiliaryId)
663
664
677