Last active
April 4, 2025 01:45
-
-
Save MustafaJafar/c35745d064e467e5483912091e0ad912 to your computer and use it in GitHub Desktop.
AYON REST API Tutorial
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"cells": [ | |
{ | |
"cell_type": "markdown", | |
"id": "f48535f2-f5ea-4491-bf2b-582ea0e5c9e9", | |
"metadata": {}, | |
"source": [ | |
"# AYON REST API\n", | |
"This Jupyter Notebook is the appendix to an AYON Community guide. <br>\n", | |
"Find the full guide here [AYON REST API Guide](https://community.ynput.io/t/ayon-rest-api-guide/1268)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"id": "a24ee57e-3083-45b7-87df-1fedae5b1195", | |
"metadata": {}, | |
"source": [ | |
"## Requirments" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"id": "906e234a-5253-4a89-811d-679b3ef0f07a", | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"pip install ayon-python-api" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"id": "f07a731a-002b-438e-870b-acf0686ab57b", | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"pip install httpx" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"id": "1239aa22-e8ea-4bc7-8e1a-33bf72b04281", | |
"metadata": {}, | |
"source": [ | |
"## Helper Functions\n", | |
"I'll be using these functions to process the response of AYON Server." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 1, | |
"id": "fddd6150-6fc1-45c0-8307-9a4aa793444b", | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"## Some Helper Functions\n", | |
"def get_projects_names(con):\n", | |
" projects = con.get_projects()\n", | |
" names = map(lambda b: b[\"name\"], projects)\n", | |
" return list(names)\n", | |
"\n", | |
"def get_bundle_names(con):\n", | |
" bundles = con.get_bundles()[\"bundles\"]\n", | |
" names = map(lambda b: b[\"name\"], bundles)\n", | |
" return list(names)\n", | |
"\n", | |
"def get_available_versions_of_addon(con, addon_name): \n", | |
" addons = con.get_addons_info()[\"addons\"]\n", | |
" core_addons = next(filter(lambda b: b[\"name\"]==addon_name, addons), {})\n", | |
" core_addons_version = list(core_addons.get(\"versions\", {}).keys())\n", | |
" return core_addons_version" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"id": "00bc2409-279d-43b2-acd5-ddaf75c300e1", | |
"metadata": {}, | |
"source": [ | |
"## AYON PYTHON API\n", | |
"`ayon-python-api` is Ynput's official library for accessing AYON's API. <br>\n", | |
"It uses `AYON_SERVER_URL` and `AYON_API_KEY` environment variables to connect with AYON Server." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 2, | |
"id": "6e3a32be-1e03-462c-8d9a-739199ec7e47", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"Current Projects: ['demo_Big_Episodic', 'demo_Big_Feature', 'demo_Commercial', 'Robo', 'RoboAyon', 'RoboPype', 'Test']\n", | |
"Available Bundles: ['AYON-CORE-0.2.0-2024-02-08', 'Dev-2023-12-20-01']\n", | |
"Available versions of Core addon: ['0.2.0', '0.3.0-dev.1']\n" | |
] | |
}, | |
{ | |
"data": { | |
"text/plain": [ | |
"<function ayon_api._api.close_connection()>" | |
] | |
}, | |
"execution_count": 2, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"import os\n", | |
"os.environ[\"AYON_SERVER_URL\"] = \"<your-ayon-server-url>\"\n", | |
"os.environ[\"AYON_API_KEY\"] = \"<your-ayon-api-key>\"\n", | |
"\n", | |
"import ayon_api\n", | |
"con = ayon_api.get_server_api_connection()\n", | |
"\n", | |
"projects = get_projects_names(con)\n", | |
"print(\"Current Projects:\", projects)\n", | |
"bundles = get_bundle_names(con)\n", | |
"print(\"Available Bundles:\", bundles)\n", | |
"core_versions = get_available_versions_of_addon(con, \"core\")\n", | |
"print(\"Available versions of Core addon:\", core_versions)\n", | |
"ayon_api.close_connection\n" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"id": "79aef743-8abf-435d-bfa7-396ae1df9b14", | |
"metadata": {}, | |
"source": [ | |
"## Simple AYON Python API\n", | |
"\n", | |
"A simple AYON python API implementation. <br>\n", | |
"It was made for the purpose of learning. <br>\n", | |
"Also, there could be situations (e.g. in CI/CD workflows) where you'd prefere to implement the two requests you'd need isntead of downlaoding the whole `ayon-python-api` library." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 3, | |
"id": "4fc56e7c-e15f-4c6e-b301-9df45e3c90f2", | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"\"\"\"\n", | |
"Many thanks to Danell, \n", | |
"This code was directly inspired by his community guide.\n", | |
"https://community.ynput.io/t/developing-with-ayons-rest-api/1237\n", | |
"\n", | |
"This code can:\n", | |
"- login\n", | |
"- get_projects\n", | |
"- get_bundles\n", | |
"- get_addons_info\n", | |
"- delete_addon_version\n", | |
"- upload_addon_zip_url\n", | |
"- upload_addon_zip_file\n", | |
"\"\"\"\n", | |
"\n", | |
"import httpx\n", | |
"\n", | |
"\n", | |
"class SimpleAyonRestCommands:\n", | |
" def __init__(self, ayon_server_url, username, password):\n", | |
" self.ayon_server_url = ayon_server_url\n", | |
" self.credentials = {\n", | |
" \"name\": username,\n", | |
" \"password\":password\n", | |
" }\n", | |
" self.headers = {}\n", | |
" self.ayon_login()\n", | |
" \n", | |
" def ayon_login(self):\n", | |
" req = f\"{self.ayon_server_url}/api/auth/login\"\n", | |
" response = httpx.post(\n", | |
" req,\n", | |
" json=self.credentials,\n", | |
" )\n", | |
" self.token = response.json().get(\"token\")\n", | |
" self.headers[\"Authorization\"] = f\"Bearer {self.token}\"\n", | |
"\n", | |
" def get_projects(self):\n", | |
" req = f\"{self.ayon_server_url}/api/projects\"\n", | |
" response = httpx.get(\n", | |
" req,\n", | |
" headers=self.headers\n", | |
" )\n", | |
" return response.json().get(\"projects\")\n", | |
" \n", | |
" def get_bundles(self):\n", | |
" req = f\"{self.ayon_server_url}/api/bundles\"\n", | |
" response = httpx.get(\n", | |
" req,\n", | |
" params={\n", | |
" \"archived\": False \n", | |
" },\n", | |
" headers=self.headers\n", | |
" )\n", | |
" return response.json()\n", | |
" \n", | |
" def get_addons_info(self):\n", | |
" req = f\"{self.ayon_server_url}/api/addons\"\n", | |
" response = httpx.get(\n", | |
" req,\n", | |
" headers=self.headers\n", | |
" )\n", | |
" return response.json()\n", | |
"\n", | |
" def delete_addon_version(self, addon_name, addon_version): \n", | |
" req = f\"{self.ayon_server_url}/api/addons/{addon_name}/{addon_version}\"\n", | |
" response = httpx.delete(\n", | |
" req,\n", | |
" params={\n", | |
" \"purge\" : True\n", | |
" },\n", | |
" headers=self.headers\n", | |
" )\n", | |
" return response.json()\n", | |
" \n", | |
" def upload_addon_zip_url(self, addon_url, addon_name, addon_version):\n", | |
" req = f\"{self.ayon_server_url}/api/addons/install\"\n", | |
" response = httpx.post(\n", | |
" req,\n", | |
" params = {\n", | |
" \"url\" : addon_url,\n", | |
" \"addonName\": addon_name,\n", | |
" \"addonVersion\" :addon_version\n", | |
" },\n", | |
" headers=self.headers\n", | |
" )\n", | |
" return response.json()\n", | |
"\n", | |
" def upload_addon_zip_file(self, addon_filepath):\n", | |
" chunk_size = 1024 * 1024\n", | |
" req = f\"{self.ayon_server_url}/api/addons/install\"\n", | |
" \n", | |
" with open(addon_filepath, \"rb\") as stream:\n", | |
" response = httpx.post(\n", | |
" req, \n", | |
" data=self.upload_chunks_iter(stream, chunk_size),\n", | |
" headers=self.headers\n", | |
" )\n", | |
" response.raise_for_status() \n", | |
" return response.json()\n", | |
"\n", | |
" @staticmethod\n", | |
" def upload_chunks_iter(file_stream, chunk_size):\n", | |
" while True:\n", | |
" chunk = file_stream.read(chunk_size)\n", | |
" if not chunk:\n", | |
" break\n", | |
" yield chunk\n", | |
" " | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"id": "f392c851-020a-4977-b81e-d93f919b86b7", | |
"metadata": {}, | |
"source": [ | |
"## Simple AYON Python API\n", | |
"It uses `username`, `password` and `ayon_Server_url` to connect with AYON Server." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 4, | |
"id": "6eb2bc6e-bbe7-40b2-b3d5-e156fed928cf", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"Current Projects: ['demo_Big_Episodic', 'demo_Big_Feature', 'demo_Commercial', 'Robo', 'RoboAyon', 'RoboPype', 'Test']\n", | |
"Available Bundles: ['AYON-CORE-0.2.0-2024-02-08', 'Dev-2023-12-20-01']\n", | |
"Available versions of Core addon: ['0.2.0', '0.3.0-dev.1']\n" | |
] | |
} | |
], | |
"source": [ | |
"username = \"<your-user-name>\"\n", | |
"password = \"<your-password>\"\n", | |
"ayon_server_url = \"<your-ayon-server-url>\"\n", | |
"\n", | |
"con = SimpleAyonRestCommands(ayon_server_url, \n", | |
" username,\n", | |
" password)\n", | |
"\n", | |
"projects = get_projects_names(con)\n", | |
"print(\"Current Projects:\", projects)\n", | |
"bundles = get_bundle_names(con)\n", | |
"print(\"Available Bundles:\", bundles)\n", | |
"core_versions = get_available_versions_of_addon(con, \"core\")\n", | |
"print(\"Available versions of Core addon:\", core_versions)" | |
] | |
} | |
], | |
"metadata": { | |
"kernelspec": { | |
"display_name": "Python 3 (ipykernel)", | |
"language": "python", | |
"name": "python3" | |
}, | |
"language_info": { | |
"codemirror_mode": { | |
"name": "ipython", | |
"version": 3 | |
}, | |
"file_extension": ".py", | |
"mimetype": "text/x-python", | |
"name": "python", | |
"nbconvert_exporter": "python", | |
"pygments_lexer": "ipython3", | |
"version": "3.10.10" | |
} | |
}, | |
"nbformat": 4, | |
"nbformat_minor": 5 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment