diff --git a/rockcraft/application.py b/rockcraft/application.py
index 7871bb93f..f724f7171 100644
--- a/rockcraft/application.py
+++ b/rockcraft/application.py
@@ -18,10 +18,8 @@
from __future__ import annotations
-import functools
-import pathlib
+from typing import Any
-import craft_cli
from craft_application import Application, AppMetadata, util
from overrides import override
@@ -39,12 +37,9 @@
class Rockcraft(Application):
"""Rockcraft application definition."""
- @functools.cached_property
- def project(self) -> models.Project:
- """Get this application's Project metadata."""
- project_file = (pathlib.Path.cwd() / f"{self.app.name}.yaml").resolve()
- craft_cli.emit.debug(f"Loading project file '{project_file!s}'")
- return models.Project.from_yaml_file(project_file, work_dir=self._work_dir)
+ @override
+ def _extra_yaml_transform(self, yaml_data: dict[str, Any]) -> dict[str, Any]:
+ return models.transform_yaml(self._work_dir, yaml_data)
@override
def _configure_services(self, platform: str | None, build_for: str | None) -> None:
diff --git a/rockcraft/environment.py b/rockcraft/environment.py
deleted file mode 100644
index da6c26061..000000000
--- a/rockcraft/environment.py
+++ /dev/null
@@ -1,57 +0,0 @@
-# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*-
-#
-# Copyright 2023 Canonical Ltd.
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU 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 warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see .
-
-"""Utilities to expand variables in project environments."""
-
-from __future__ import annotations
-
-import pathlib
-from typing import Any
-
-import craft_parts
-
-
-def expand_environment(
- project_yaml: dict[str, Any],
- *,
- project_vars: dict[str, Any],
- work_dir: pathlib.Path,
-) -> None:
- """Expand global variables in the provided dictionary values.
-
- :param project_yaml: A dictionary containing the rockcraft.yaml's contents.
- :param project_var: A dictionary with the project-specific variables.
- :param work_dir: The working directory.
- """
- info = craft_parts.ProjectInfo(
- application_name="rockcraft", # not used in environment expansion
- cache_dir=pathlib.Path(), # not used in environment expansion
- project_name=project_yaml.get("name", ""),
- project_dirs=craft_parts.ProjectDirs(work_dir=work_dir),
- project_vars=project_vars,
- )
- _set_global_environment(info)
-
- craft_parts.expand_environment(project_yaml, info=info)
-
-
-def _set_global_environment(info: craft_parts.ProjectInfo) -> None:
- """Set global environment variables."""
- info.global_environment.update(
- {
- "CRAFT_PROJECT_VERSION": info.get_project_var("version", raw_read=True),
- }
- )
diff --git a/rockcraft/models/__init__.py b/rockcraft/models/__init__.py
index 97204e05d..f0b68c4be 100644
--- a/rockcraft/models/__init__.py
+++ b/rockcraft/models/__init__.py
@@ -17,6 +17,11 @@
"""Rockcraft models."""
-from rockcraft.models.project import Project, RockcraftBuildInfo, load_project
+from rockcraft.models.project import (
+ Project,
+ RockcraftBuildInfo,
+ load_project,
+ transform_yaml,
+)
-__all__ = ["Project", "RockcraftBuildInfo", "load_project"]
+__all__ = ["Project", "RockcraftBuildInfo", "load_project", "transform_yaml"]
diff --git a/rockcraft/models/project.py b/rockcraft/models/project.py
index d49c82cde..4b01de960 100644
--- a/rockcraft/models/project.py
+++ b/rockcraft/models/project.py
@@ -17,7 +17,6 @@
"""Project definition and helpers."""
import dataclasses
import operator
-import pathlib
import platform as host_platform
import re
from builtins import super
@@ -40,15 +39,12 @@
import pydantic
import spdx_lookup # type: ignore
import yaml
-from craft_application.errors import CraftValidationError
from craft_application.models import BuildInfo
from craft_application.models import Project as BaseProject
from craft_archives import repo
from craft_providers import bases
-from overrides import override
from pydantic_yaml import YamlModelMixin
-from rockcraft.environment import expand_environment
from rockcraft.errors import ProjectLoadError, ProjectValidationError
from rockcraft.extensions import apply_extensions
from rockcraft.parts import part_has_overlay, validate_part
@@ -487,29 +483,6 @@ def unmarshal(cls, data: Dict[str, Any]) -> "Project":
return project
- @classmethod
- @override
- def from_yaml_file(
- cls, path: pathlib.Path, *, work_dir: Optional[pathlib.Path] = None
- ) -> "Project":
- """Instantiate this model from a YAML file."""
- # pylint: disable=import-outside-toplevel
-
- data = load_project(path)
-
- if work_dir is not None:
- project_vars = {"version": data["version"]}
- expand_environment(
- data,
- project_vars=project_vars,
- work_dir=work_dir,
- )
- try:
- # TODO apply extensions here
- return cls.unmarshal(data)
- except pydantic.ValidationError as err:
- raise CraftValidationError.from_pydantic(err, file_name=path.name) from None
-
def generate_metadata(
self, generation_time: str, base_digest: bytes
) -> Tuple[dict, dict]:
@@ -679,7 +652,17 @@ def load_project(filename: Path) -> Dict[str, Any]:
msg = f"{msg}: {err.filename!r}."
raise ProjectLoadError(msg) from err
- yaml_data = apply_extensions(filename.parent, yaml_data)
+ yaml_data = transform_yaml(filename.parent, yaml_data)
+ return yaml_data
+
+
+def transform_yaml(project_root: Path, yaml_data: Dict[str, Any]) -> Dict[str, Any]:
+ """Do Rockcraft-specific transformations on a project yaml.
+
+ :param project_root: The path that contains the "rockcraft.yaml" file.
+ :param yaml_data: The data dict loaded from the yaml file.
+ """
+ yaml_data = apply_extensions(project_root, yaml_data)
_add_pebble_data(yaml_data)
diff --git a/tests/unit/extensions/test_extensions.py b/tests/unit/extensions/test_extensions.py
index 99977a300..57e1b882e 100644
--- a/tests/unit/extensions/test_extensions.py
+++ b/tests/unit/extensions/test_extensions.py
@@ -17,7 +17,7 @@
import pytest
from rockcraft import errors, extensions
-from rockcraft.models.project import load_project
+from rockcraft.models import load_project
from tests.unit.testing.extensions import (
FULL_EXTENSION_YAML,
ExperimentalExtension,
diff --git a/tests/unit/test_application.py b/tests/unit/test_application.py
index cace8e6a3..8aa650946 100644
--- a/tests/unit/test_application.py
+++ b/tests/unit/test_application.py
@@ -15,6 +15,8 @@
# along with this program. If not, see .
from pathlib import Path
+from rockcraft.pebble import Pebble
+
ENVIRONMENT_YAML = """\
name: environment-test
version: 2.0
@@ -53,3 +55,12 @@ def test_application_expand_environment(default_application, new_dir):
"X": "ship it!",
"CRAFT_VAR": "2.0",
}
+
+
+def test_application_pebble_part(default_application, new_dir):
+ """Test that loading the project through the application adds the Pebble part."""
+ project_file = Path(new_dir) / "rockcraft.yaml"
+ project_file.write_text(ENVIRONMENT_YAML)
+
+ project = default_application.project
+ assert project.parts["pebble"] == Pebble.PEBBLE_PART_SPEC