Skip to content

Commit

Permalink
Refactor api modules to use the new AddonLibrary
Browse files Browse the repository at this point in the history
Modified all instances where we accessed the AddonLibrary to ensure
we get the same result as previously and that everything works given the
new class.
  • Loading branch information
Minkiu committed Jan 29, 2024
1 parent 88dcf82 commit c5222f5
Show file tree
Hide file tree
Showing 16 changed files with 160 additions and 258 deletions.
53 changes: 21 additions & 32 deletions api/addons/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from fastapi import Query, Request, Response
from nxtools import logging

from ayon_server.addons import AddonLibrary
from ayon_server.addons import AddonLibrary, RezRepo
from ayon_server.addons.models import SourceInfo
from ayon_server.api.dependencies import CurrentUser
from ayon_server.exceptions import (
Expand Down Expand Up @@ -63,56 +63,45 @@ async def list_addons(
) -> AddonList:
"""List all available addons."""

base_url = f"{request.url.scheme}://{request.url.netloc}"
# base_url = f"{request.url.scheme}://{request.url.netloc}"

result = []
library = AddonLibrary.getinstance()
rezrepo = RezRepo.get_instance()

# maybe some ttl here?
active_versions = await library.get_active_versions()
active_versions = await AddonLibrary.get_enabled_addons()

# TODO: for each version, return the information
# whether it has settings (and don't show the addon in the settings editor if not)

for _name, definition in library.data.items():
vers = active_versions.get(definition.name, {})
for addon_name, addon_dict in rezrepo.packages.items():
vers = active_versions.get(addon_name, {})
versions = {}
is_system = False
for version, addon in definition.versions.items():
if addon.system:
addon_title = ""
addon_description = ""

for version_dict in addon_dict.get("versions", []):
((version_number, addon_rez_package),) = version_dict.items()
versions[version_number] = VersionInfo()

if getattr(addon_rez_package, "system", False):
if not user.is_admin:
continue
is_system = True

vinf = {
"has_settings": bool(addon.get_settings_model()),
"has_site_settings": bool(addon.get_site_settings_model()),
"frontend_scopes": addon.frontend_scopes,
}
if details:
vinf["client_pyproject"] = await addon.get_client_pyproject()

source_info = await addon.get_client_source_info(base_url=base_url)
if source_info is None:
pass

elif not all(isinstance(x, SourceInfo) for x in source_info):
logging.error(f"Invalid source info for {addon.name} {version}")
source_info = [x for x in source_info if isinstance(x, SourceInfo)]
vinf["client_source_info"] = source_info
if not addon_title:
addon_title = getattr(addon_rez_package, "nice_name", "")

vinf["services"] = addon.services or None
versions[version] = VersionInfo(**vinf)
if not addon_description:
addon_description = getattr(addon_rez_package, "description", "")

if not versions:
continue

result.append(
AddonListItem(
name=definition.name,
title=definition.friendly_name,
name=addon_name,
title=addon_title if addon_title else addon_name,
versions=versions,
description=definition.__doc__ or "",
description=addon_description if addon_description else "",
production_version=vers.get("production"),
system=is_system or None,
staging_version=vers.get("staging"),
Expand Down
8 changes: 4 additions & 4 deletions api/addons/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ async def remove_override(
variant: str = "production",
project_name: str | None = None,
):
if (addon := AddonLibrary.addon(addon_name, addon_version)) is None:
if (addon := AddonLibrary.get_addon(addon_name, addon_version)) is None:
raise NotFoundException(f"Addon {addon_name} {addon_version} not found")

# TODO: ensure the path is not a part of a group
Expand Down Expand Up @@ -62,7 +62,7 @@ async def pin_override(
variant: str = "production",
project_name: str | None = None,
):
if (addon := AddonLibrary.addon(addon_name, addon_version)) is None:
if (addon := AddonLibrary.get_addon(addon_name, addon_version)) is None:
raise NotFoundException(f"Addon {addon_name} {addon_version} not found")

if project_name:
Expand Down Expand Up @@ -136,7 +136,7 @@ async def remove_site_override(
user_name: str,
path: list[str],
):
if (addon := AddonLibrary.addon(addon_name, addon_version)) is None:
if (addon := AddonLibrary.get_addon(addon_name, addon_version)) is None:
raise NotFoundException(f"Addon {addon_name} {addon_version} not found")

overrides = await addon.get_project_site_overrides(project_name, user_name, site_id)
Expand Down Expand Up @@ -171,7 +171,7 @@ async def pin_site_override(
user_name: str,
path: list[str],
):
if (addon := AddonLibrary.addon(addon_name, addon_version)) is None:
if (addon := AddonLibrary.get_addon(addon_name, addon_version)) is None:
raise NotFoundException(f"Addon {addon_name} {addon_version} not found")

overrides = await addon.get_project_site_overrides(project_name, user_name, site_id)
Expand Down
46 changes: 2 additions & 44 deletions api/addons/delete_addon.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,44 +8,9 @@
from ayon_server.api.responses import EmptyResponse
from ayon_server.exceptions import AyonException, ForbiddenException, NotFoundException

# from ayon_server.lib.postgres import Postgres
from .router import router


async def delete_addon_directory(addon_name: str, addon_version: str | None = None):
"""Delete an addon or addon version"""

addon_definition = AddonLibrary.get(addon_name)
if addon_definition is None:
raise NotFoundException("Addon not found")

addon_dir = addon_definition.addon_dir
is_empty = not os.listdir(addon_dir)

if not is_empty and addon_version is not None:
addon = addon_definition.versions.get(addon_version)
if addon is None:
raise NotFoundException("Addon version not found")

version_dir = addon.addon_dir
try:
await aioshutil.rmtree(version_dir)
except Exception as e:
raise AyonException(
f"Failed to delete {addon_name} {addon_version} directory: {e}"
)
AddonLibrary.unload_addon(addon_name, addon_version, {"error": "Addon deleted"})

is_empty = not os.listdir(addon_dir)

if (addon_version is None) or is_empty:
try:
await aioshutil.rmtree(addon_dir)
except Exception as e:
raise AyonException(f"Failed to delete {addon_name} directory: {e}")
AddonLibrary.data.pop(addon_name, None)


@router.delete("/{addon_name}", tags=["Addons"])
async def delete_addon(
user: CurrentUser,
Expand All @@ -57,11 +22,7 @@ async def delete_addon(
if not user.is_admin:
raise ForbiddenException("Only admins can delete addons")

await delete_addon_directory(addon_name)

if purge:
pass
# TODO: implement purge
AddonLibrary.delete_addon_from_server(addon_name)


@router.delete("/{addon_name}/{addon_version}", tags=["Addons"])
Expand All @@ -76,8 +37,5 @@ async def delete_addon_version(
if not user.is_admin:
raise ForbiddenException("Only admins can delete addons")

await delete_addon_directory(addon_name, addon_version)
AddonLibrary.delete_addon_from_server(addon_name, addon_version)

if purge:
pass
# TODO: implement purge
4 changes: 2 additions & 2 deletions api/addons/install.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from ayon_server.events import dispatch_event, update_event
from ayon_server.exceptions import ForbiddenException
from ayon_server.installer import background_installer
from ayon_server.installer.addons import get_addon_zip_info
from ayon_server.addons import AddonLibrary
from ayon_server.lib.postgres import Postgres
from ayon_server.types import Field, OPModel

Expand Down Expand Up @@ -97,7 +97,7 @@ async def upload_addon_zip_file(

# Get addon name and version from the zip file

addon_name, addon_version = get_addon_zip_info(temp_path)
addon_name, addon_version = AddonLibrary.get_addon_zip_info(temp_path)

# We don't create the event before we know that the zip file is valid
# and contains an addon. If it doesn't, an exception is raised before
Expand Down
12 changes: 5 additions & 7 deletions api/addons/project_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,7 @@ async def get_addon_project_settings_schema(
site: str | None = Query(None, regex="^[a-z0-9-]+$"),
) -> dict[str, Any]:
"""Return the JSON schema of the addon settings."""

if (addon := AddonLibrary.addon(addon_name, version)) is None:
if (addon := AddonLibrary.get_addon(addon_name, version)) is None:
raise NotFoundException(f"Addon {addon_name} {version} not found")

model = addon.get_settings_model()
Expand Down Expand Up @@ -77,7 +76,7 @@ async def get_addon_project_settings(
variant: str = Query("production"),
site: str | None = Query(None, regex="^[a-z0-9-]+$"),
) -> dict[str, Any]:
if (addon := AddonLibrary.addon(addon_name, version)) is None:
if (addon := AddonLibrary.get_addon(addon_name, version)) is None:
raise NotFoundException(f"Addon {addon_name} {version} not found")

if site:
Expand All @@ -101,7 +100,7 @@ async def get_addon_project_overrides(
variant: str = Query("production"),
site: str | None = Query(None, regex="^[a-z0-9-]+$"),
):
addon = AddonLibrary.addon(addon_name, version)
addon = AddonLibrary.get_addon(addon_name, version)
studio_settings = await addon.get_studio_settings(variant=variant)
if studio_settings is None:
return {}
Expand Down Expand Up @@ -142,8 +141,7 @@ async def set_addon_project_settings(
site: str | None = Query(None, regex="^[a-z0-9-]+$"),
) -> EmptyResponse:
"""Set the studio overrides of the given addon."""

addon = AddonLibrary.addon(addon_name, version)
addon = AddonLibrary.get_addon(addon_name, version)
model = addon.get_settings_model()
if model is None:
raise BadRequestException(f"Addon {addon_name} has no settings")
Expand Down Expand Up @@ -242,7 +240,7 @@ async def delete_addon_project_overrides(
site: str | None = Query(None, regex="^[a-z0-9-]+$"),
):
# Ensure the addon and the project exist
_ = AddonLibrary.addon(addon_name, version)
_ = AddonLibrary.get_addon(addon_name, version)
_ = await ProjectEntity.load(project_name)

if not site:
Expand Down
8 changes: 3 additions & 5 deletions api/addons/site_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@ async def get_addon_site_settings_schema(
user: CurrentUser,
) -> dict[str, Any]:
"""Return the JSON schema of the addon site settings."""

if (addon := AddonLibrary.addon(addon_name, version)) is None:
if (addon := AddonLibrary.get_addon(addon_name, version)) is None:
raise NotFoundException(f"Addon {addon_name} {version} not found")

model = addon.get_site_settings_model()
Expand Down Expand Up @@ -54,8 +53,7 @@ async def get_addon_site_settings(
site: str = Query(...),
) -> dict[str, Any]:
"""Return the JSON schema of the addon site settings."""

if (addon := AddonLibrary.addon(addon_name, version)) is None:
if (addon := AddonLibrary.get_addon(addon_name, version)) is None:
raise NotFoundException(f"Addon {addon_name} {version} not found")

model = addon.get_site_settings_model()
Expand Down Expand Up @@ -84,7 +82,7 @@ async def set_addon_site_settings(
user: CurrentUser,
site: str = Query(..., title="Site ID", regex="^[a-z0-9-]+$"),
) -> EmptyResponse:
if (addon := AddonLibrary.addon(addon_name, version)) is None:
if (addon := AddonLibrary.get_addon(addon_name, version)) is None:
raise NotFoundException(f"Addon {addon_name} {version} not found")

model = addon.get_site_settings_model()
Expand Down
12 changes: 5 additions & 7 deletions api/addons/studio_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,7 @@ async def get_addon_settings_schema(
variant: str = Query("production"),
) -> dict[str, Any]:
"""Return the JSON schema of the addon settings."""

if (addon := AddonLibrary.addon(addon_name, addon_version)) is None:
if (addon := AddonLibrary.get_addon(addon_name, addon_version)) is None:
raise NotFoundException(f"Addon {addon_name} {addon_version} not found")

model = addon.get_settings_model()
Expand Down Expand Up @@ -63,8 +62,7 @@ async def get_addon_studio_settings(
variant: str = Query("production"),
) -> dict[str, Any]:
"""Return the settings (including studio overrides) of the given addon."""

if (addon := AddonLibrary.addon(addon_name, addon_version)) is None:
if (addon := AddonLibrary.get_addon(addon_name, addon_version)) is None:
raise NotFoundException(f"Addon {addon_name} {addon_version} not found")

settings = await addon.get_studio_settings(variant=variant)
Expand All @@ -86,7 +84,7 @@ async def set_addon_studio_settings(
if not user.is_manager:
raise ForbiddenException

addon = AddonLibrary.addon(addon_name, addon_version)
addon = AddonLibrary.get_addon(addon_name, addon_version)
original = await addon.get_studio_settings(variant=variant)
existing = await addon.get_studio_overrides(variant=variant)
model = addon.get_settings_model()
Expand Down Expand Up @@ -143,7 +141,7 @@ async def get_addon_studio_overrides(
if not user.is_manager:
raise ForbiddenException

addon = AddonLibrary.addon(addon_name, addon_version)
addon = AddonLibrary.get_addon(addon_name, addon_version)
settings = await addon.get_studio_settings(variant=variant)
if settings is None:
return {}
Expand All @@ -164,7 +162,7 @@ async def delete_addon_studio_overrides(
raise ForbiddenException

# Ensure addon exists
_ = AddonLibrary.addon(addon_name, addon_version)
_ = get_addon(addon_name, addon_version)

await Postgres.execute(
"""
Expand Down
21 changes: 11 additions & 10 deletions api/bundles/bundles.py
Original file line number Diff line number Diff line change
Expand Up @@ -245,16 +245,17 @@ async def create_new_bundle(
# a bundle with an addon that does not exist
if not addon_version:
continue
_ = AddonLibrary.addon(addon_name, addon_version)

for system_addon_name, addon_definition in AddonLibrary.items():
if addon_definition.is_system:
if system_addon_name not in bundle.addons:
logging.debug(
f"Adding missing system addon {system_addon_name} to bundle {bundle.name}"
)
if addon_definition.latest:
bundle.addons[system_addon_name] = addon_definition.latest.version
_ = AddonLibrary.get_addon(addon_name, addon_version)

# TODO reimplement so it looks at the package for this info
# for system_addon_name, addon_definition in rezrepo.packages():
# if addon_definition.is_system:
# if system_addon_name not in bundle.addons:
# logging.debug(
# f"Adding missing system addon {system_addon_name} to bundle {bundle.name}"
# )
# if addon_definition.latest:
# bundle.addons[system_addon_name] = addon_definition.latest.version

await create_bundle(bundle, user, x_sender)

Expand Down
10 changes: 3 additions & 7 deletions api/market/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import httpx

from ayon_server.addons.library import AddonLibrary
from ayon_server.addons import AddonLibrary
from ayon_server.config import ayonconfig
from ayon_server.exceptions import ForbiddenException
from ayon_server.helpers.cloud import get_cloud_api_headers
Expand Down Expand Up @@ -41,12 +41,8 @@ async def get_local_latest_addon_versions() -> dict[str, str]:
Used to check if there are new versions available
"""

result = {}
for addon_name, definition in AddonLibrary.items():
if not definition.latest:
continue
result[addon_name] = definition.latest.version
return result
return AddonLibrary.get_addons_latest_versions()



async def get_local_production_addon_versions() -> dict[str, str]:
Expand Down
4 changes: 2 additions & 2 deletions api/services/services.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,8 @@ async def spawn_service(
if not user.is_admin:
raise ForbiddenException("Only admins can spawn services")

library = AddonLibrary.getinstance()
addon = library.addon(payload.addon_name, payload.addon_version)
addon = AddonLibrary.get_addon(payload.addon_name, payload.addon_version)

if payload.service not in addon.services:
# TODO: be more verbose
raise NotFoundException("This addon does not have this service")
Expand Down
Loading

0 comments on commit c5222f5

Please sign in to comment.