diff --git a/.changelog/_unreleased.toml b/.changelog/_unreleased.toml index 91751341..74c24870 100644 --- a/.changelog/_unreleased.toml +++ b/.changelog/_unreleased.toml @@ -9,3 +9,15 @@ id = "17854ad9-56e6-41a9-9d69-a4a55a830682" type = "feature" description = "Add `kraken.std.git.gitignore_extend()` function" author = "@NiklasRosenstein" + +[[entries]] +id = "afea35ef-4ce0-4c2e-9b25-b72d288ce6c7" +type = "breaking change" +description = "Remove `Project.do()` as it was deprecated for a long time. Use `Project.task()` instead" +author = "@NiklasRosenstein" + +[[entries]] +id = "aabad4ba-ff7c-47b7-9703-5a84366b6d2b" +type = "fix" +description = "Temporarily remove @deprecated from Task.outputs; the API is actively used and we have no replacement API for it" +author = "@NiklasRosenstein" diff --git a/kraken-build/src/kraken/core/system/project.py b/kraken-build/src/kraken/core/system/project.py index 3c09b182..491205e3 100644 --- a/kraken-build/src/kraken/core/system/project.py +++ b/kraken-build/src/kraken/core/system/project.py @@ -1,17 +1,13 @@ from __future__ import annotations -import re import warnings from collections.abc import Mapping from pathlib import Path -from typing import TYPE_CHECKING, Any, Literal, TypeVar, cast, overload +from typing import TYPE_CHECKING, Any, Literal, TypeVar, overload -from deprecated import deprecated -from kraken.core.address import Address from kraken.core.base import Currentable, MetadataContainer from kraken.core.system.kraken_object import KrakenObject -from kraken.core.system.property import Property from kraken.core.system.task import GroupTask, Task if TYPE_CHECKING: @@ -298,73 +294,6 @@ def remove_child(self, project: Project) -> None: del self._members[project.name] - @deprecated(reason="Use Project.task() instead") - def do( - self, - name: str, - task_type: type[T_Task] = cast(Any, Task), - default: bool | None = None, - *, - group: str | GroupTask | None = None, - description: str | None = None, - **kwargs: Any, - ) -> T_Task: - """Add a task to the project under the given name, executing the specified action. - - :param name: The name of the task to add. - :param task_type: The type of task to add. - :param default: Override :attr:`Task.default`. - :param group: Add the task to the given group in the project. - :param kwargs: Any number of properties to set on the task. Unknown properties will be ignored - with a warning log. - :return: The created task. - """ - - # NOTE(NiklasRosenstein): In versions prior to kraken-core 0.12.0, we did not validate task names. - # Now, the #Address class performs the validation and is rather strict. In order to not fully - # break usage of this function with invalid names, we convert the name to a valid form instead - # and issue a warning. This behaviour shall be removed in kraken-core 0.14.0. - - if not re.match(Address.Element.VALIDATION_REGEX, name): - new_name = re.sub(f"[^{Address.Element.VALID_CHARACTERS}]+", "-", name) - warnings.warn( - f"Task name `{name}` is invalid and will be normalized to `{new_name}`. Starting with " - "kraken-core 0.12.0, Task names must follow a stricter naming convention subject to the " - f"Address class' validation (must match /{Address.Element.VALIDATION_REGEX}/).", - DeprecationWarning, - stacklevel=2, - ) - name = new_name - - if name in self._members: - raise ValueError(f"{self} already has a member {name!r}") - - task = task_type(name, self) - if default is not None: - task.default = default - if description is not None: - task.description = description - - invalid_keys = set() - for key, value in kwargs.items(): - prop = getattr(task, key, None) - if isinstance(prop, Property): - if value is not None: - prop.set(value) - else: - invalid_keys.add(key) - if invalid_keys: - task.logger.warning( - "properties %s cannot be set because they don't exist (task %s)", invalid_keys, task.address - ) - - self.add_task(task) - if isinstance(group, str): - group = self.group(group) - if group is not None: - group.add(task) - return task - def group(self, name: str, *, description: str | None = None, default: bool | None = None) -> GroupTask: """Create or get a group of the given name. If a task with the given name already exists, it must refer to a task of type :class:`GroupTask`, otherwise a :class:`RuntimeError` is raised. diff --git a/kraken-build/src/kraken/core/system/task.py b/kraken-build/src/kraken/core/system/task.py index 7e6506e1..61ecbc36 100644 --- a/kraken-build/src/kraken/core/system/task.py +++ b/kraken-build/src/kraken/core/system/task.py @@ -14,7 +14,6 @@ from pathlib import Path from typing import TYPE_CHECKING, Any, ForwardRef, Generic, Literal, TypeVar, cast, overload -from deprecated import deprecated from kraken.common import Supplier from kraken.core.address import Address @@ -236,7 +235,7 @@ def project(self) -> Project: return self._parent @property - @deprecated(reason="Task.outputs is deprecated.") + # @deprecated(reason="Task.outputs is deprecated.") def outputs(self) -> list[Any]: return self._outputs diff --git a/kraken-build/src/kraken/std/docker/__init__.py b/kraken-build/src/kraken/std/docker/__init__.py index 1f966521..5dc3badc 100644 --- a/kraken-build/src/kraken/std/docker/__init__.py +++ b/kraken-build/src/kraken/std/docker/__init__.py @@ -5,6 +5,8 @@ from kraken.common import import_class from kraken.core import Project, Task +from kraken.core.system.property import Property +from kraken.core.system.task import GroupTask from kraken.std.docker.tasks.base_build_task import BaseBuildTask from kraken.std.docker.tasks.manifest_tool_push_task import ManifestToolPushTask @@ -23,12 +25,32 @@ def build_docker_image( name: str = "buildDocker", backend: str = DEFAULT_BUILD_BACKEND, project: Project | None = None, + default: bool = False, + group: str | GroupTask | None = None, + description: str | None = None, **kwds: Any, ) -> BaseBuildTask: """Create a new task in the current project that builds a Docker image and eventually pushes it.""" + project = project or Project.current() task_class = import_class(BUILD_BACKENDS[backend], BaseBuildTask) # type: ignore[type-abstract] - return (project or Project.current()).do(name, task_class, **kwds) + task = project.task(name, task_class, default=default, group=group, description=description) + + # Assign properties from the kwargs. + invalid_keys = set() + for key, value in kwds.items(): + prop = getattr(task, key, None) + if isinstance(prop, Property): + if value is not None: + prop.set(value) + else: + invalid_keys.add(key) + if invalid_keys: + task.logger.warning( + "properties %s cannot be set because they don't exist (task %s)", invalid_keys, task.address + ) + + return task def manifest_tool(