Source code for

# Licensed under a 3-clause BSD style license - see LICENSE.rst
This file contains xml element classes as defined in the VOResource standard.

There are different ways of handling the various xml tags.

* Elements with complex content
* Elements with simple content and attributes
* Elements with simple content without attributes

Elements with complex content are parsed with objects inherited from `~pyvo.utils.xml.elements.Element`.

Elements with simple content are parsed with objects inherited from `~pyvo.utils.xml.elements.Element`
defining a ``value`` property.
from astropy.utils.collections import HomogeneousList
from astropy.utils.misc import indent

from ...utils.xml.elements import (
    Element, ElementWithXSIType, ContentMixin, xmlattribute, xmlelement)
from .exceptions import W06

__all__ = [
    "ValidationLevel", "Capability", "Interface", "AccessURL",
    "SecurityMethod", "WebBrowser", "WebService", "MirrorURL"]

[docs]class ValidationLevel(ContentMixin, Element): """ ValidationLevel element as described in the allowed values for describing the resource descriptions and interfaces. See the RM (v1.1, section 4) for more guidance on the use of these values. Possible values: 0: The resource has a description that is stored in a registry. This level does not imply a compliant description. 1: In addition to meeting the level 0 definition, the resource description conforms syntactically to this standard and to the encoding scheme used. 2: In addition to meeting the level 1 definition, the resource description refers to an existing resource that has demonstrated to be functionally compliant. When the resource is a service, it is consider to exist and functionally compliant if use of the service accessURL responds without error when used as intended by the resource. If the service is a standard one, it must also demonstrate the response is syntactically compliant with the service standard in order to be considered functionally compliant. If the resource is not a service, then the ReferenceURL must be shown to return a document without error. 3: In addition to meeting the level 2 definition, the resource description has been inspected by a human and judged to comply semantically to this standard as well as meeting any additional minimum quality criteria (e.g., providing values for important but non-required metadata) set by the human inspector. 4: In addition to meeting the level 3 definition, the resource description meets additional quality criteria set by the human inspector and is therefore considered an excellent description of the resource. Consequently, the resource is expected to be operate well as part of a VO application or research study. """ def __init__( self, config=None, pos=None, _name='validationLevel', validatedBy=None, **kwargs ): super().__init__(config, pos, _name, **kwargs) self._validatedby = validatedBy def __repr__(self): return '<ValidationLevel validatedBy={}>{}</ValidationLevel>'.format( self.validatedby, self.content) @xmlattribute def validatedby(self): """ The IVOA ID of the registry or organisation that assigned the validation level. """ return self._validatedby @validatedby.setter def validatedby(self, validatedby): self._validatedby = validatedby
[docs]class AccessURL(ContentMixin, Element): """ AccessURL element as described in The URL (or base URL) that a client uses to access the service. How this URL is to be interpreted and used depends on the specific Interface subclass """ def __init__( self, config=None, pos=None, _name='accessURL', use=None, **kwargs ): super().__init__(config, pos, _name, **kwargs) self._use = use def __repr__(self): return '<AccessURL use={}>{}</AccessURL>'.format( self.use, self.content) @xmlattribute def use(self): """ A flag indicating whether this should be interpreted as a base URL, a full URL, or a URL to a directory that will produce a listing of files. Possible values: full: Assume a full URL--that is, one that can be invoked directly without alteration. This usually returns a single document or file. base: Assume a base URL--that is, one requiring an extra portion to be appended before being invoked. dir: Assume URL points to a directory that will return a listing of files. """ return self._use @use.setter def use(self, use): self._use = use
[docs]class MirrorURL(ContentMixin, Element): """ A URL available as a mirror of an access URL. These come with a human-readable title intended to aid in mirror selection. """ def __init__( self, config=None, pos=None, _name='accessURL', title=None, **kwargs ): super().__init__(config, pos, _name, **kwargs) self._title = title @xmlattribute def title(self): """ A human-readable title for the mirror. """ return self._title
[docs]class SecurityMethod(ContentMixin, Element): """ SecurityMethod element as described in A description of a security mechanism. this type only allows one to refer to the mechanism via a URI. Derived types would allow for more metadata. """ def __init__( self, config=None, pos=None, _name='securityMethod', standardID=None, **kwargs ): super().__init__(config, pos, _name, **kwargs) self._standardid = standardID def __repr__(self): return '<SecurityMethod standardID={}>{}</SecurityMethod>'.format( self.standardid, self.content) @xmlattribute(name='standardID') def standardid(self): """ A URI identifier for a standard security mechanism. """ return self._standardid @standardid.setter def standardid(self, standardid): self._standardid = standardid
[docs]class Interface(ElementWithXSIType): """ Interface element as described in A description of a service interface. Since this type is abstract, one must use an Interface subclassto describe an actual interface. Additional interface subtypes (beyond WebService and WebBrowser) are defined in the VODataService schema. """ def __init__( self, config=None, pos=None, _name='interface', version='1.0', role=None, **kwargs ): super().__init__(config, pos, _name, **kwargs) self._xsi_type = kwargs.get('xsi:type') self._version = version self._role = role self._resulttype = None self._testquerystring = None self._accessurls = HomogeneousList(AccessURL) self._securitymethods = HomogeneousList(SecurityMethod) self._mirrorurls = HomogeneousList(MirrorURL) def __repr__(self): return '<Interface role={}>...</Interface>'.format( self.role)
[docs] def describe(self): """ Prints out a human readable description """ print('Interface {}'.format(self._xsi_type)) accessurls = '\n'.join( accessurl.content for accessurl in self.accessurls) print(indent(accessurls)) print()
@xmlattribute def version(self): """ The version of a standard interface specification that this interface complies with. When the interface is provided in the context of a Capability element, then the standard being refered to is the one identified by the Capability's standardID element. If the standardID is not provided, the meaning of this attribute is undefined. """ return self._version @version.setter def version(self, version): self._version = version @xmlattribute def role(self): """ A tag name the identifies the role the interface plays in the particular capability. If the value is equal to "std" or begins with "std:", then the interface refers to a standard interface defined by the standard referred to by the capability's standardID attribute. For an interface complying with some registered standard (i.e. has a legal standardID), the role can be match against interface roles enumerated in standard resource record. The interface descriptions in the standard record can provide default descriptions so that such details need not be repeated here. """ return self._role @role.setter def role(self, role): self._role = role @xmlelement(name='accessURL', cls=AccessURL) def accessurls(self): """ A list of access urls in the interface. Must contain only `AccessURL` objects. """ return self._accessurls @xmlelement(name='mirrorURL', cls=MirrorURL) def mirrorurls(self): """ mirror(s) for this access URL. """ return self._mirrorurls @xmlelement(name='securityMethod', cls=SecurityMethod) def securitymethods(self): """ the mechanism the client must employ to gain secure access to the service. when more than one method is listed, each one must be employed to gain access. """ return self._securitymethods @xmlelement(name='testQueryString') def testquerystring(self): """ a string to be used in an interface-specific way to obtain a non-empty result from the service. """ return self._testquerystring @testquerystring.setter def testquerystring(self, testquerystring): self._testquerystring = testquerystring @xmlelement def resulttype(self): """ The MIME type of a document returned in the HTTP response. """ return self._resulttype @resulttype.setter def resulttype(self, resulttype): self._resulttype = resulttype
[docs]class Capability(ElementWithXSIType): """ Capability element as described in a description of what the service does (in terms of context-specific behavior), and how to use it (in terms of an interface) """ def __init__( self, config=None, pos=None, _name='capability', standardID=None, **kwargs ): super().__init__(config, pos, _name, **kwargs) self._description = None self._standardid = standardID self._validationlevels = HomogeneousList(ValidationLevel) self._interfaces = HomogeneousList(Interface) def __repr__(self): return ( '<Capability standardID={}>' '... {} validationLevels, {} interfaces ...' '</Capability>' ).format( self.standardid, len(self.validationlevels), len(self.interfaces))
[docs] def describe(self): """ Prints out a human readable description """ print("Capability {}".format(self.standardid)) print() if self.description: print(self.description) print() for interface in self.interfaces: interface.describe()
@xmlelement(plain=True, multiple_exc=W06) def description(self): """ A human-readable description of what this capability provides as part of the over-all service Use of this optional element is especially encouraged when this capability is non-standard and is one of several capabilities listed. """ return self._description @description.setter def description(self, description): self._description = description @xmlelement(name='validationLevel', cls=ValidationLevel) def validationlevels(self): """ A numeric grade describing the quality of the capability description and interface, when applicable, to be used to indicate the confidence an end-user can put in the resource as part of a VO application or research study. """ return self._validationlevels @xmlelement(name='interface', cls=Interface) def interfaces(self): """ a description of how to call the service to access this capability Since the Interface type is abstract, one must describe the interface using a subclass of Interface, denoting it via xsi:type. Multiple occurances can describe different interfaces to the logically same capability--i.e. data or functionality. That is, the inputs accepted and the output provides should be logically the same. For example, a WebBrowser interface given in addition to a WebService interface would simply provide an interactive, human-targeted interface to the underlying WebService interface. """ return self._interfaces @xmlattribute(name='standardID') def standardid(self): """ A URI identifier for a standard service. This provides a unique way to refer to a service specification standard, such as a Simple Image Access service. The use of an IVOA identifier here implies that a VOResource description of the standard is registered and accessible. """ return self._standardid @standardid.setter def standardid(self, standardid): self._standardid = standardid
[docs]@Interface.register_xsi_type('vr:WebBrowser') class WebBrowser(Interface): """ WebBrowser element as described in A (form-based) interface intended to be accesed interactively by a user via a web browser. The accessURL represents the URL of the web form itself. """
[docs]@Interface.register_xsi_type('vr:WebService') class WebService(Interface): """ WebService element as described in A Web Service that is describable by a WSDL document. The accessURL element gives the Web Service's endpoint URL. """ def __init__(self, config=None, pos=None, _name='interface', **kwargs): super().__init__(config, pos, _name, **kwargs) self._wsdlurls = HomogeneousList(str) @xmlelement(name='wsdlURL') def wsdlurls(self): """ The location of the WSDL that describes this Web Service. If not provided, the location is assumed to be the accessURL with "?wsdl" appended. Multiple occurances should represent mirror copies of the same WSDL file. """ return self._wsdlurls