Source code for craft_application.services.base

#  This file is part of craft-application.
#
#  Copyright 2023 Canonical Ltd.
#
#  This program is free software: you can redistribute it and/or modify it
#  under the terms of the GNU Lesser General Public License version 3, as
#  published by the Free Software Foundation.
#
#  This program is distributed in the hope that it will be useful, but WITHOUT
#  ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
#  SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE.
#  See the GNU Lesser General Public License for more details.
#
#  You should have received a copy of the GNU Lesser General Public License
#  along with this program.  If not, see <http://www.gnu.org/licenses/>.
"""Abstract base service class."""

from __future__ import annotations

import abc
import typing

from craft_cli import emit

from craft_application import errors

if typing.TYPE_CHECKING:
    from craft_platforms import BuildInfo

    from craft_application.application import AppMetadata
    from craft_application.models.project import Project
    from craft_application.services import ServiceFactory


# This is abstract to prevent it from being used directly. Ignore the lack of
# abstract methods.
[docs] class AppService(metaclass=abc.ABCMeta): # noqa: B024 """A service class, containing application business logic. The AppService base class is for services that do not need access to an existing project. """
[docs] def __init__(self, app: AppMetadata, services: ServiceFactory) -> None: self._app = app self._services = services
[docs] def setup(self) -> None: """Service-specific setup to perform. Child classes should always call ``super().setup()``. """ emit.debug(f"Setting up {self.__class__.__name__}")
@property def _project(self) -> Project: """The rendered project to use. This will error if the project is not yet fully configured. """ return self._services.get("project").get() @property def _build_info(self) -> BuildInfo: """The information about the current build. This will error if the build plan is not configured, if the build plan contains multiple entries, or if the build plan is empty. """ plan = self._services.get("build_plan").plan() match len(plan): case 0: raise errors.EmptyBuildPlanError case 1: return plan[0] case _: raise errors.MultipleBuildsError(plan)