def _build_accepted_media_types(media_types: Union[str, Sequence[str]]) -> str: """ Builds the Accept header of media types as required by the GetObject transaction request. The qvalue is used to specify the desirability of a given media type with 1 being the most desirable, 0 being the least, and a range in between. See section 5.1 for the full definition: Accept ::= type / subtype [; parameter] *(, type / subtype [; parameter]) type ::= * | <publicly defined type> subtype ::= * | <publicly defined subtype> parameter ::= q = <qvalue scale from 0 to 1> A complete list of media types is available at http://www.iana.org/assignments/media-types. """ if isinstance(media_types, str): return media_types elif not isinstance(media_types, Sequence): raise RetsClientError('Invalid media types argument') n = float(len(media_types)) return ','.join( '%s;%.4f' % (types, 1 - i / n) for i, types in enumerate(media_types) )
def _build_entity_object_ids( entities: Union[str, Mapping[str, Any], Sequence[str]] ) -> str: """ Builds the string of object ids as required by the GetObject transaction request. See section 5.3 for the full definition: ID ::= resource-set *(, resource-set) resource-set ::= resource-entity [: object-id-list] resource-entity ::= 1*ALPHANUM object-id-list ::= * | object-id *(: object-id) object-id ::= 1*5DIGIT """ if isinstance(entities, str): return _build_entity_object_ids((entities,)) elif isinstance(entities, Sequence): return _build_entity_object_ids({e: '*' for e in entities}) elif not isinstance(entities, Mapping): raise RetsClientError('Invalid entities argument') def _build_object_ids(object_ids: Any) -> str: if object_ids in ('*', 0, '0'): return str(object_ids) elif isinstance(object_ids, Sequence): return ':'.join(str(o) for o in object_ids) else: raise RetsClientError('Invalid entities argument') return ','.join( '%s:%s' % (entity, _build_object_ids(object_ids)) for entity, object_ids in entities.items() )
def _get_http_auth(username: str, password: str, auth_type: str) -> AuthBase: if auth_type == 'basic': return HTTPBasicAuth(username, password) if auth_type == 'digest': return HTTPDigestAuth(username, password) raise RetsClientError('unknown auth type %s' % auth_type)
def _assert_fields(self, fields: Sequence[str]) -> None: permissible = self.table.fields invalid = tuple(f for f in fields if f not in permissible) if invalid: raise RetsClientError('invalid fields %s' % ','.join(invalid))
def _url_for(self, transaction: str) -> str: try: url = self._capabilities[transaction] except KeyError: raise RetsClientError('No URL found for transaction %s' % transaction) return urljoin(self._base_url, url)
def get_object( self, resource: str, object_type: str, resource_keys: Union[str, Mapping[str, Any], Sequence[str]], media_types: Union[str, Sequence[str]] = '*/*', location: bool = False, ) -> Sequence[Object]: """ The GetObject transaction is used to retrieve structured information related to known system entities. It can be used to retrieve multimedia files and other key-related information. Objects requested and returned from this transaction are requested and returned as MIME media types. The message body for successful retrievals contains only the objects in the specified MIME media type. Error responses follow the normal response format (section 3.9). :param resource: A resource defined in the metadata dictionary (see Section 11.2.2). The resource from which the object should be retrieved is specified by this entry. For more information see 5.9. The resource must be a resource defined in the metadata (section 11.4.1). :param object_type: The object type as defined in the metadata (see Section 11.4.1). The grouping category to which the object belongs. The type must be an ObjectType defined in the Object metadata for this Resource. For more information see section 11.4.1. :param resource_keys: A single value or a list-like or dict-like container specifying the entities of the resource to retrieve objects for, where the entity is given by the KeyField of the resource. If the resource_ids is a value or is list-like, then all objects corresponding to the entities are returned by default. If resource_ids is dict-like, then it is a mapping from the resource entity to an object_id_list. The object_id_list can take the values: '*', 0, or an array of positive ids. If it is '*', then all objects are returns. If it is 0, then the preferred object is returned. Otherwise, the ids will refer to the sequential index of the objects beginning with 1. :param media_types: A single or list-like container of acceptable media types for the server to return. If media_types is like-like, then the ordering specifies the preference of the media types to return, with the first being the most desirable. If the server is unable to provide the requested media type, it should return a 406 Not Acceptable status, or if no objects exist for any media type then the server should return a 404 Not Found. :param location: Flag to indicate whether the object or a URL to the object should be returned. If location is set to True, it is up to the server to support this functionality and the lifetime of the returned URL is not given by the RETS specification. """ headers = {'Accept': _build_accepted_media_types(media_types)} payload = { 'Resource': resource, 'Type': object_type, 'ID': _build_entity_object_ids(resource_keys), 'Location': int(location), 'Format': self.format_, } response = self._http_post( self._url_for('GetObject'), headers=headers, payload=payload ) object_ = parse_object(response, self.parser) returned_object = [] for obj in object_: if obj.content_id is not None: returned_object.append(obj) continue if len(resource_keys) == 1: returned_object.append( obj._replace(content_id=list(resource_keys.keys())[0]) ) else: raise RetsClientError( 'The server\'s response does not contain content-id' ) return returned_object