chris.client.base
1import abc 2from typing import AsyncContextManager, Generic, Optional, Callable, TypeVar 3 4import aiohttp 5from serde import from_dict 6 7from chris.link.collection_client import L, CollectionJsonApiClient 8from chris.util.errors import raise_for_status 9 10CSelf = TypeVar( 11 "CSelf", bound="BaseChrisClient" 12) # can't wait for `Self` in Python 3.11! 13 14 15class BaseChrisClient( 16 Generic[L, CSelf], 17 CollectionJsonApiClient[L], 18 AsyncContextManager[CSelf], 19 abc.ABC, 20): 21 """ 22 Provides the implementation for most of the read-only GET resources of ChRIS 23 and functions related to the client object's own usage. 24 """ 25 26 @classmethod 27 async def new( 28 cls, 29 url: str, 30 max_search_requests: int = 100, 31 connector: Optional[aiohttp.BaseConnector] = None, 32 connector_owner: bool = True, 33 session_modifier: Optional[Callable[[aiohttp.ClientSession], None]] = None, 34 ) -> CSelf: 35 """ 36 A constructor which creates the session for the `BaseChrisClient` 37 and makes an initial request to populate `collection_links`. 38 39 Parameters 40 ---------- 41 url 42 ChRIS backend url, e.g. "https://cube.chrisproject.org/api/v1/" 43 max_search_requests 44 Maximum number of HTTP requests to make while retrieving items from a 45 paginated endpoint before raising `chris.util.search.TooMuchPaginationError`. 46 Use `max_search_requests=-1` to allow for "infinite" pagination 47 (well, you're still limited by Python's stack). 48 connector 49 [`aiohttp.BaseConnector`](https://docs.aiohttp.org/en/v3.8.3/client_advanced.html#connectors) to use. 50 If creating multiple client objects in the same program, 51 reusing connectors between them is more efficient. 52 connector_owner 53 If `True`, this client will close its `aiohttp.BaseConnector` 54 session_modifier 55 Called to mutate the created `aiohttp.ClientSession` for the object. 56 If the client requires authentication, define `session_modifier` 57 to add authentication headers to the session. 58 """ 59 if not url.endswith("/api/v1/"): 60 raise ValueError("url must end with /api/v1/") 61 accept_json = { 62 "Accept": "application/json", 63 # 'Content-Type': 'application/vnd.collection+json', 64 } 65 # TODO maybe we want to wrap the session: 66 # - status == 4XX --> print response text 67 # - content-type: application/vnd.collection+json 68 session = aiohttp.ClientSession( 69 headers=accept_json, 70 raise_for_status=False, 71 connector=connector, 72 connector_owner=connector_owner, 73 ) 74 if session_modifier is not None: 75 session_modifier(session) 76 77 async with session.get(url) as res: 78 await raise_for_status(res) 79 body = await res.json() 80 links = from_dict(cls._collection_type(), body["collection_links"]) 81 return cls( 82 url=url, 83 s=session, 84 collection_links=links, 85 max_search_requests=max_search_requests, 86 ) 87 88 async def __aenter__(self) -> CSelf: 89 return self 90 91 async def __aexit__(self, exc_type, exc_val, exc_tb): 92 await self.close() 93 94 async def close(self): 95 """ 96 Close the HTTP session used by this client. 97 """ 98 await self.s.close()
class
BaseChrisClient(typing.Generic[~L, ~CSelf], chris.link.collection_client.CollectionJsonApiClient[~L], typing.AsyncContextManager[~CSelf], abc.ABC):
16class BaseChrisClient( 17 Generic[L, CSelf], 18 CollectionJsonApiClient[L], 19 AsyncContextManager[CSelf], 20 abc.ABC, 21): 22 """ 23 Provides the implementation for most of the read-only GET resources of ChRIS 24 and functions related to the client object's own usage. 25 """ 26 27 @classmethod 28 async def new( 29 cls, 30 url: str, 31 max_search_requests: int = 100, 32 connector: Optional[aiohttp.BaseConnector] = None, 33 connector_owner: bool = True, 34 session_modifier: Optional[Callable[[aiohttp.ClientSession], None]] = None, 35 ) -> CSelf: 36 """ 37 A constructor which creates the session for the `BaseChrisClient` 38 and makes an initial request to populate `collection_links`. 39 40 Parameters 41 ---------- 42 url 43 ChRIS backend url, e.g. "https://cube.chrisproject.org/api/v1/" 44 max_search_requests 45 Maximum number of HTTP requests to make while retrieving items from a 46 paginated endpoint before raising `chris.util.search.TooMuchPaginationError`. 47 Use `max_search_requests=-1` to allow for "infinite" pagination 48 (well, you're still limited by Python's stack). 49 connector 50 [`aiohttp.BaseConnector`](https://docs.aiohttp.org/en/v3.8.3/client_advanced.html#connectors) to use. 51 If creating multiple client objects in the same program, 52 reusing connectors between them is more efficient. 53 connector_owner 54 If `True`, this client will close its `aiohttp.BaseConnector` 55 session_modifier 56 Called to mutate the created `aiohttp.ClientSession` for the object. 57 If the client requires authentication, define `session_modifier` 58 to add authentication headers to the session. 59 """ 60 if not url.endswith("/api/v1/"): 61 raise ValueError("url must end with /api/v1/") 62 accept_json = { 63 "Accept": "application/json", 64 # 'Content-Type': 'application/vnd.collection+json', 65 } 66 # TODO maybe we want to wrap the session: 67 # - status == 4XX --> print response text 68 # - content-type: application/vnd.collection+json 69 session = aiohttp.ClientSession( 70 headers=accept_json, 71 raise_for_status=False, 72 connector=connector, 73 connector_owner=connector_owner, 74 ) 75 if session_modifier is not None: 76 session_modifier(session) 77 78 async with session.get(url) as res: 79 await raise_for_status(res) 80 body = await res.json() 81 links = from_dict(cls._collection_type(), body["collection_links"]) 82 return cls( 83 url=url, 84 s=session, 85 collection_links=links, 86 max_search_requests=max_search_requests, 87 ) 88 89 async def __aenter__(self) -> CSelf: 90 return self 91 92 async def __aexit__(self, exc_type, exc_val, exc_tb): 93 await self.close() 94 95 async def close(self): 96 """ 97 Close the HTTP session used by this client. 98 """ 99 await self.s.close()
Provides the implementation for most of the read-only GET resources of ChRIS and functions related to the client object's own usage.
@classmethod
async def
new( cls, url: str, max_search_requests: int = 100, connector: Optional[aiohttp.connector.BaseConnector] = None, connector_owner: bool = True, session_modifier: Optional[Callable[[aiohttp.client.ClientSession], NoneType]] = None) -> ~CSelf:
27 @classmethod 28 async def new( 29 cls, 30 url: str, 31 max_search_requests: int = 100, 32 connector: Optional[aiohttp.BaseConnector] = None, 33 connector_owner: bool = True, 34 session_modifier: Optional[Callable[[aiohttp.ClientSession], None]] = None, 35 ) -> CSelf: 36 """ 37 A constructor which creates the session for the `BaseChrisClient` 38 and makes an initial request to populate `collection_links`. 39 40 Parameters 41 ---------- 42 url 43 ChRIS backend url, e.g. "https://cube.chrisproject.org/api/v1/" 44 max_search_requests 45 Maximum number of HTTP requests to make while retrieving items from a 46 paginated endpoint before raising `chris.util.search.TooMuchPaginationError`. 47 Use `max_search_requests=-1` to allow for "infinite" pagination 48 (well, you're still limited by Python's stack). 49 connector 50 [`aiohttp.BaseConnector`](https://docs.aiohttp.org/en/v3.8.3/client_advanced.html#connectors) to use. 51 If creating multiple client objects in the same program, 52 reusing connectors between them is more efficient. 53 connector_owner 54 If `True`, this client will close its `aiohttp.BaseConnector` 55 session_modifier 56 Called to mutate the created `aiohttp.ClientSession` for the object. 57 If the client requires authentication, define `session_modifier` 58 to add authentication headers to the session. 59 """ 60 if not url.endswith("/api/v1/"): 61 raise ValueError("url must end with /api/v1/") 62 accept_json = { 63 "Accept": "application/json", 64 # 'Content-Type': 'application/vnd.collection+json', 65 } 66 # TODO maybe we want to wrap the session: 67 # - status == 4XX --> print response text 68 # - content-type: application/vnd.collection+json 69 session = aiohttp.ClientSession( 70 headers=accept_json, 71 raise_for_status=False, 72 connector=connector, 73 connector_owner=connector_owner, 74 ) 75 if session_modifier is not None: 76 session_modifier(session) 77 78 async with session.get(url) as res: 79 await raise_for_status(res) 80 body = await res.json() 81 links = from_dict(cls._collection_type(), body["collection_links"]) 82 return cls( 83 url=url, 84 s=session, 85 collection_links=links, 86 max_search_requests=max_search_requests, 87 )
A constructor which creates the session for the BaseChrisClient
and makes an initial request to populate collection_links
.
Parameters
- url: ChRIS backend url, e.g. "https://cube.chrisproject.org/api/v1/"
- max_search_requests: Maximum number of HTTP requests to make while retrieving items from a
paginated endpoint before raising
chris.util.search.TooMuchPaginationError
. Usemax_search_requests=-1
to allow for "infinite" pagination (well, you're still limited by Python's stack). - connector:
aiohttp.BaseConnector
to use. If creating multiple client objects in the same program, reusing connectors between them is more efficient. - connector_owner: If
True
, this client will close itsaiohttp.BaseConnector
- session_modifier: Called to mutate the created
aiohttp.ClientSession
for the object. If the client requires authentication, definesession_modifier
to add authentication headers to the session.
async def
close(self):
95 async def close(self): 96 """ 97 Close the HTTP session used by this client. 98 """ 99 await self.s.close()
Close the HTTP session used by this client.
Inherited Members
- chris.link.collection_client.CollectionJsonApiClient
- CollectionJsonApiClient
- url
- collection_links
- chris.link.linked.Linked
- max_search_requests