The emgapi_v2_client#
For developing or in case you want to work with the mgnipy.emgapi_v2_client sub-package directly.
What is it?#
mgnipy.emgapi_v2_client is a python sub-package in MGni.py that was created from the openapi.json spec using openapi-python-client .
It serves as the initial HTTP client to remove the complexity of direct HTTP requests to version 2 of the MGnify API while maintaining type safety through attrs-based models.
How was it created?#
This client library was automatically generated from the MGnify API v2 OpenAPI specification using openapi-python-client . This choice was made in the hopes that it would be easier for MGni.py to be updated with changes to the MGnify API endpoints and models.
See readme-openapi-python-client.md for more information on openapi-python-client
How does it work?#
Each MGnify API endpoint has its own module in emgapi_v2_client#
Every MGnify API v2 endpoint (e.g., list_all_biomes , get_mgnify_analysis ) has their own module in emgapi_v2_client (e.g.,
mgnipy.emgapi_v2_client.api.miscellaneous.list_mgnify_biomes,mgnipy.emgapi_v2_client.api.analyses.get_mgnify_analysis)Within the emgapi_v2_client, the endpoint modules are in the
apidirectory:
emgapi_v2_client/
βββ api/
β βββ analyses/
β β βββ get_mgnify_analysis.py
β β βββ ...
β βββ assemblies/
β β βββ get_assembly.py
β β βββ ...
β βββ 'other-api-tag'/
β β βββ ...
β βββ 'another-api-tag'/
β β βββ ...
β βββ ...
βββ models/
β βββ analysed_run.py
β βββ biome.py
β βββ 'some-other-attrs-data-model'.py
β βββ ...
βββ ...
- each subdir in api/ corresponds to a tag in the MGnify API e.g., analyses, assemblies
- the endpoints for that tag are in that tag's subdir (if multi tags, is in the first)
- the `attrs` data models are in models/
Each API endpoint module exposes 4 functions:#
sync: Blocking request that returns parsed data (if successful) orNonesync_detailed: Blocking request that always returns aRequest, optionally withparsedset if the request was successful.asyncio: async version ofsync.asyncio_detailed: async version ofsync_detailed.
Putting it altogether in a demo:#
Below we will have an example where we will find studies of the biome root:Host-associated:Plants
What to import#
At a minimum:
We need to find and import the appropriate module for our endpoint:
/Miscellaneous/list_mgnify_biomesGet and initiate the
mgnipy.Clientinstance(Optional) add type annotations
# uncomment below if colab
#!pip install mgnipy
#!pip install asyncio
# at minimum need
# 1. the path
from mgnipy.emgapi_v2_client.api.miscellaneous import list_mgnify_biomes
# 2. the client
from mgnipy.emgapi_v2_client import Client
# extra nice to have annotations but not required for usage
# 3. the models
from mgnipy.emgapi_v2_client.models import NinjaPaginationResponseSchemaBiome
from mgnipy.emgapi_v2_client.types import UNSET, Response
Initiate the client#
To instantiate the python client we really only need the base_url. However there are options for loggiing and other httpx args.
mgnipy.emgapi_v2_client.Client/AuheticatedClient will take care of constructing and closing the httpx clients
example_client = Client(base_url="https://www.ebi.ac.uk")
# check it out
print(example_client)
Client(raise_on_unexpected_status=False, _base_url='https://www.ebi.ac.uk', _cookies={}, _headers={}, _timeout=None, _verify_ssl=True, _follow_redirects=False, _httpx_args={}, _client=None, _async_client=None)
Making the request to the API Endpoint#
The get request is made when running the .sync...() or .async...() functions. For example executing
with example_client as client:
response = list_mgnify_biomes.sync_detailed(
client=client, page_size=10
)
the API will respond with the first page of 10 items from the list_mgnify_biomes endpoint.
πͺ A peak behind the curtain πͺ#
The order of the methods within list_mgnify_biomes.py when the above is executed would be:
_get_kwargsto prepare the query params, ensuring that the kwarg exists e.g. thatpage_sizeis an acceptable kwargthe httpx request is made with the kwargs
_build_responseto prepare asResponsetypeIn the
Responseis attributeResponse.parsedwhich uses_parse_responseto get response as json / dict
Note: The difference between with and sans
..._detailed()is that with returns the whole response and sans only returns the parsed response.
# prep our search
params = {
"biome_lineage": "root:Host-associated:Plants",
"page_size": 25,#the default
"max_depth": 6,
}
# make the sync call and store respone
with example_client as client:
# adding type annotation for the response is optional
response: Response[NinjaPaginationResponseSchemaBiome] = list_mgnify_biomes.sync_detailed(client=client, **params)
# check
response.status_code
<HTTPStatus.OK: 200>
Parsing the response#
and if we take a look at the parsed content:
response.parsed.to_dict().keys()
dict_keys(['count', 'items'])
In
itemsare records such as the biome_lineagesfor the first page of results only
In
countis the total number of records that matched our query. Note: you need to instantiate a new client object every call
Letβs take a closer look at the response
response.parsed.to_dict()
{'count': 15,
'items': [{'biome_name': 'Plants', 'lineage': 'root:Host-associated:Plants'},
{'biome_name': 'Phylloplane',
'lineage': 'root:Host-associated:Plants:Phylloplane'},
{'biome_name': 'Endophytes',
'lineage': 'root:Host-associated:Plants:Phylloplane:Endophytes'},
{'biome_name': 'Epiphytes',
'lineage': 'root:Host-associated:Plants:Phylloplane:Epiphytes'},
{'biome_name': 'Rhizome', 'lineage': 'root:Host-associated:Plants:Rhizome'},
{'biome_name': 'Epiphytes',
'lineage': 'root:Host-associated:Plants:Rhizome:Epiphytes'},
{'biome_name': 'Rhizoplane',
'lineage': 'root:Host-associated:Plants:Rhizoplane'},
{'biome_name': 'Endophytes',
'lineage': 'root:Host-associated:Plants:Rhizoplane:Endophytes'},
{'biome_name': 'Epiphytes',
'lineage': 'root:Host-associated:Plants:Rhizoplane:Epiphytes'},
{'biome_name': 'Soil',
'lineage': 'root:Host-associated:Plants:Rhizoplane:Soil'},
{'biome_name': 'Rhizosphere',
'lineage': 'root:Host-associated:Plants:Rhizosphere'},
{'biome_name': 'Epiphytes',
'lineage': 'root:Host-associated:Plants:Rhizosphere:Epiphytes'},
{'biome_name': 'Forest soil',
'lineage': 'root:Host-associated:Plants:Rhizosphere:Forest soil'},
{'biome_name': 'Soil',
'lineage': 'root:Host-associated:Plants:Rhizosphere:Soil'},
{'biome_name': 'Root', 'lineage': 'root:Host-associated:Plants:Root'}]}
Async requests support#
import asyncio
example_client = Client(base_url="https://www.ebi.ac.uk")
async with example_client as client:
parsed_response = await list_mgnify_biomes.asyncio(
client=client,
biome_lineage="root:Host-associated",
max_depth=6,
page_size=5,
)
parsed_response.to_dict()
{'count': 233,
'items': [{'biome_name': 'Host-associated',
'lineage': 'root:Host-associated'},
{'biome_name': 'Algae', 'lineage': 'root:Host-associated:Algae'},
{'biome_name': 'Brown Algae',
'lineage': 'root:Host-associated:Algae:Brown Algae'},
{'biome_name': 'Green algae',
'lineage': 'root:Host-associated:Algae:Green algae'},
{'biome_name': 'Ectosymbionts',
'lineage': 'root:Host-associated:Algae:Green algae:Ectosymbionts'}]}