Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Integrate with Starbase #422

Draft
wants to merge 32 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
6fe4c5b
chore(linter): use starbase
syu-w Nov 28, 2023
42670ba
chore(deps): sync dev deps with starbase
syu-w Nov 28, 2023
ab04163
chore(tests): update tox.ini with starbase
syu-w Nov 28, 2023
c20d6d5
chore(linter): update to 3.10 style
syu-w Nov 28, 2023
518aa7e
chore(linter): misc auto fix
syu-w Nov 28, 2023
bbb3493
chore(linter): use tuple for pytest.mark.parametrize
syu-w Nov 28, 2023
9fc89bc
chore(linter): create list without concatenate
syu-w Nov 28, 2023
d9ef893
chore(linter): misc fix
syu-w Nov 28, 2023
d1a6efb
chore(linter): fix some annotations
syu-w Nov 28, 2023
d4b888a
chore(linter): temporarily turn off unfixed rules
syu-w Nov 29, 2023
39303dc
feat(project): migrate to pyproject.toml
syu-w Nov 29, 2023
7dd8598
feat(ci): use tox.ini for ci
syu-w Nov 29, 2023
f7ce055
test: allow venv sh shebang
syu-w Nov 30, 2023
cecd533
docs: use starbase readthedocs
syu-w Nov 30, 2023
aaca617
test(docs): delete docs build spread test
syu-w Dec 1, 2023
d48cb9a
chore(linter): fix mypy annotation errors
syu-w Dec 1, 2023
3144a2b
chore(linter): fix pyright annotation errors
syu-w Dec 1, 2023
7d2cd8e
chore(linter): fix docs linter errors
syu-w Dec 1, 2023
a3c4eac
chore(linter): fix yaml linter errors
syu-w Dec 1, 2023
b17987a
Merge branch 'main' into CRAFT-2249-starbase
syu-w Dec 4, 2023
49990bc
chore(ci): sync pre commit config with pyproject
syu-w Dec 4, 2023
33e8ca3
chore(linter): move run_user typing to the top
syu-w Dec 4, 2023
af5594d
chore(linter): fix _create_app return type
syu-w Dec 4, 2023
5ad6554
chore: update the snapcraft workaround comment
syu-w Dec 4, 2023
83ffa4f
chore(linter): increase line length for README
syu-w Dec 4, 2023
aaf57c0
fix: use values for get services
syu-w Dec 4, 2023
bf6a312
test: disable tests that will not work in tox
syu-w Dec 4, 2023
c8c2259
test(spread): add an spread test for shebang
syu-w Dec 5, 2023
d12616a
docs: update the how-to build docs to use tox
syu-w Dec 5, 2023
20a0ab9
chore(ci): fix naming
syu-w Dec 5, 2023
a1fd0ef
chore(deps): use requirements.txt with pyproject.toml
syu-w Dec 5, 2023
a3417f8
chore(snap): use setup.py
syu-w Dec 5, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion rockcraft/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
from typing import Any

from craft_application import Application, AppMetadata, util
from overrides import override
from overrides import override # type: ignore[reportUnknownVariableType]

from rockcraft import models
from rockcraft.models import project
Expand Down
2 changes: 1 addition & 1 deletion rockcraft/commands/extensions.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
import tabulate
from craft_application.commands import AppCommand
from craft_cli import emit
from overrides import overrides
from overrides import overrides # type: ignore[reportUnknownVariableType]
from pydantic import BaseModel

from rockcraft import extensions
Expand Down
2 changes: 1 addition & 1 deletion rockcraft/commands/init.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

from craft_application.commands import AppCommand
from craft_cli import emit
from overrides import overrides
from overrides import overrides # type: ignore[reportUnknownVariableType]

from rockcraft import errors

Expand Down
2 changes: 1 addition & 1 deletion rockcraft/extensions/_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ def _apply_extension(
if "parts" not in yaml_data:
yaml_data["parts"] = {}

parts = yaml_data["parts"]
parts: dict[str, Any] = yaml_data["parts"]
for part_definition in parts.values():
for property_name, property_value in part_extension.items():
part_definition[property_name] = _apply_extension_property(
Expand Down
46 changes: 25 additions & 21 deletions rockcraft/models/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"""Project definition and helpers."""
import re
import shlex
from collections.abc import Mapping, Sequence
from collections.abc import Callable, Mapping, Sequence
from pathlib import Path
from typing import (
TYPE_CHECKING,
Expand Down Expand Up @@ -59,7 +59,9 @@ class Config: # pylint: disable=too-few-public-methods
"""Pydantic model configuration."""

allow_population_by_field_name = True
alias_generator = lambda s: s.replace("_", "-") # noqa: E731
alias_generator: Callable[[str], str] = lambda s: s.replace( # noqa: E731
"_", "-"
)

@pydantic.validator("build_for", pre=True)
@classmethod
Expand All @@ -73,8 +75,8 @@ def _vectorise_build_for(cls, val: str | list[str]) -> list[str]:
@classmethod
def _validate_platform_set(cls, values: Mapping[str, Any]) -> Mapping[str, Any]:
"""Validate the build_on build_for combination."""
build_for = values["build_for"] if values.get("build_for") else []
build_on = values["build_on"] if values.get("build_on") else []
build_for: list[str] = values["build_for"] if values.get("build_for") else []
build_on: list[str] = values["build_on"] if values.get("build_on") else []

# We can only build for 1 arch at the moment
if len(build_for) > 1:
Expand Down Expand Up @@ -126,13 +128,16 @@ class Project(YamlModelMixin, BaseProject):
name: NameStr # type: ignore
# summary is Optional[str] in BaseProject
summary: str # type: ignore
description: str
description: str # type: ignore[reportIncompatibleVariableOverride]
rock_license: str = pydantic.Field(alias="license")
platforms: dict[str, Any]
base: Literal["bare", "[email protected]", "[email protected]"]
build_base: Literal["[email protected]", "[email protected]"] | None
environment: dict[str, str] | None
run_user: Literal[tuple(SUPPORTED_GLOBAL_USERNAMES)] | None # type: ignore
if TYPE_CHECKING:
syu-w marked this conversation as resolved.
Show resolved Hide resolved
run_user: str | None
else:
run_user: Literal[tuple(SUPPORTED_GLOBAL_USERNAMES)] | None # type: ignore
services: dict[str, Service] | None
checks: dict[str, Check] | None
entrypoint_service: str | None
Expand All @@ -148,7 +153,9 @@ class Config: # pylint: disable=too-few-public-methods
extra = "forbid"
allow_mutation = False
allow_population_by_field_name = True
alias_generator = lambda s: s.replace("_", "-") # noqa: E731
alias_generator: Callable[[str], str] = lambda s: s.replace( # noqa: E731
"_", "-"
)
error_msg_templates = {
"value_error.str.regex": INVALID_NAME_MESSAGE,
}
Expand Down Expand Up @@ -185,12 +192,12 @@ def _validate_license(cls, rock_license: str) -> str:
# This is the license name we use on our stores.
return rock_license

lic: spdx_lookup.License | None = spdx_lookup.by_id(rock_license)
lic: spdx_lookup.License | None = spdx_lookup.by_id(rock_license) # type: ignore[reportUnknownMemberType]
if lic is None:
raise ProjectValidationError(
f"License {rock_license} not valid. It must be valid and in SPDX format."
)
return str(lic.id)
return str(lic.id) # type: ignore[reportUnknownMemberType]

@pydantic.validator("title", always=True)
@classmethod
Expand Down Expand Up @@ -246,7 +253,9 @@ def _check_deprecated_base(base_value: str | None, field_name: str) -> str | Non
def _validate_all_platforms(cls, platforms: dict[str, Any]) -> dict[str, Any]:
"""Make sure all provided platforms are tangible and sane."""
for platform_label in platforms:
platform = platforms[platform_label] if platforms[platform_label] else {}
platform: dict[str, Any] = (
platforms[platform_label] if platforms[platform_label] else {}
)
error_prefix = f"Error for platform entry '{platform_label}'"

# Make sure the provided platform_set is valid
Expand Down Expand Up @@ -371,7 +380,7 @@ def _validate_package_repositories(
if not package_repositories:
return []

errors = []
errors: list[ErrorDict] = []
for repository in package_repositories:
try:
repo.validate_repository(repository)
Expand Down Expand Up @@ -412,11 +421,11 @@ def to_yaml(self) -> str:
def _repr_str(dumper: yaml.SafeDumper, data: str) -> yaml.ScalarNode:
"""Multi-line string representer for the YAML dumper."""
if "\n" in data:
return dumper.represent_scalar("tag:yaml.org,2002:str", data, style="|")
return dumper.represent_scalar("tag:yaml.org,2002:str", data)
return dumper.represent_scalar("tag:yaml.org,2002:str", data, style="|") # type: ignore[reportUnknownMemberType]
return dumper.represent_scalar("tag:yaml.org,2002:str", data) # type: ignore[reportUnknownMemberType]

yaml.add_representer(str, _repr_str, Dumper=yaml.SafeDumper)
return super().yaml(
return super().yaml( # type: ignore[reportUnknownMemberType]
by_alias=True,
exclude_none=True,
allow_unicode=True,
Expand All @@ -427,9 +436,6 @@ def _repr_str(dumper: yaml.SafeDumper, data: str) -> yaml.ScalarNode:
@classmethod
def unmarshal(cls, data: dict[str, Any]) -> "Project":
"""Overridden to raise ProjectValidationError() for Pydantic errors."""
if not isinstance(data, dict):
raise TypeError("project data is not a dictionary")

try:
project = super().unmarshal(data)
except pydantic.ValidationError as err:
Expand Down Expand Up @@ -538,18 +544,16 @@ def _format_pydantic_errors(

def _format_pydantic_error_location(loc: Sequence[str | int]) -> str:
"""Format location."""
loc_parts = []
loc_parts: list[str] = []
for loc_part in loc:
if isinstance(loc_part, str):
loc_parts.append(loc_part)
elif isinstance(loc_part, int):
else:
# Integer indicates an index. Go
# back and fix up previous part.
previous_part = loc_parts.pop()
previous_part += f"[{loc_part}]"
loc_parts.append(previous_part)
else:
raise RuntimeError(f"unhandled loc: {loc_part}")

new_loc = ".".join(loc_parts)

Expand Down
6 changes: 3 additions & 3 deletions rockcraft/oci.py
Original file line number Diff line number Diff line change
Expand Up @@ -442,8 +442,8 @@ def set_environment(self, env: dict[str, str]) -> None:
"""
emit.progress("Configuring OCI environment...")
image_path = self.path / self.image_name
params = []
env_list = []
params: list[str] = []
env_list: list[str] = []

for name, value in env.items():
env_item = f"{name}={value}"
Expand Down Expand Up @@ -491,7 +491,7 @@ def set_annotations(self, annotations: dict[str, Any]) -> None:
label_params = ["--clear=config.labels"]
annotation_params = ["--clear=manifest.annotations"]

labels_list = []
labels_list: list[str] = []
for label_key, label_value in annotations.items():
label_item = f"{label_key}={label_value}"
labels_list.append(label_item)
Expand Down
14 changes: 10 additions & 4 deletions rockcraft/pebble.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"""Pebble metadata and configuration helpers."""

import glob
from collections.abc import Mapping
from collections.abc import Callable, Mapping
from pathlib import Path
from typing import Any, Literal

Expand Down Expand Up @@ -70,7 +70,9 @@ class Config: # pylint: disable=too-few-public-methods
"""Pydantic model configuration."""

allow_population_by_field_name = True
alias_generator = lambda s: s.replace("_", "-") # noqa: E731
alias_generator: Callable[[str], str] = lambda s: s.replace( # noqa: E731
"_", "-"
)
extra = "forbid"


Expand Down Expand Up @@ -116,7 +118,9 @@ class Config: # pylint: disable=too-few-public-methods
"""Pydantic model configuration."""

allow_population_by_field_name = True
alias_generator = lambda s: s.replace("_", "-") # noqa: E731
alias_generator: Callable[[str], str] = lambda s: s.replace( # noqa: E731
"_", "-"
)
extra = "forbid"


Expand Down Expand Up @@ -153,7 +157,9 @@ class Config: # pylint: disable=too-few-public-methods
"""Pydantic model configuration."""

allow_population_by_field_name = True
alias_generator = lambda s: s.replace("_", "-") # noqa: E731
alias_generator: Callable[[str], str] = lambda s: s.replace( # noqa: E731
"_", "-"
)
extra = "forbid"


Expand Down
4 changes: 2 additions & 2 deletions rockcraft/plugins/python_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
from textwrap import dedent

from craft_parts.plugins import python_plugin
from overrides import override
from overrides import override # type: ignore[reportUnknownVariableType]

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -90,7 +90,7 @@ def _get_script_interpreter(self) -> str:
@override
def get_build_commands(self) -> list[str]:
"""Overridden to add a sitecustomize.py ."""
commands = []
commands: list[str] = []

# Detect whether PARTS_PYTHON_INTERPRETER is a full path (not supported)
commands.append(
Expand Down
2 changes: 1 addition & 1 deletion rockcraft/services/lifecycle.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
from craft_parts import Features, LifecycleManager, Step, callbacks
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ir seems that this can imported only if TYPE_CHECKING?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I got:

rockcraft/services/lifecycle.py:35:29: TCH004 Move import `craft_parts.LifecycleManager` out of type-checking block. Import is used for more than type hinting.

from craft_parts.errors import CallbackRegistrationError
from craft_parts.infos import ProjectInfo, StepInfo
from overrides import override
from overrides import override # type: ignore[reportUnknownVariableType]

from rockcraft import layers
from rockcraft.models.project import Project
Expand Down
4 changes: 2 additions & 2 deletions rockcraft/services/package.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@

from craft_application import AppMetadata, PackageService, models, util
from craft_cli import emit
from overrides import override
from overrides import override # type: ignore[reportUnknownVariableType]

from rockcraft import errors, oci
from rockcraft.models import Project
Expand All @@ -39,7 +39,7 @@ class RockcraftPackageService(PackageService):
def __init__(
self,
app: AppMetadata,
services: RockcraftServiceFactory,
services: "RockcraftServiceFactory",
*,
project: models.Project,
platform: str | None,
Expand Down
2 changes: 1 addition & 1 deletion rockcraft/services/provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"""Rockcraft Provider service."""

from craft_application import ProviderService
from overrides import override
from overrides import override # type: ignore[reportUnknownVariableType]


class RockcraftProviderService(ProviderService):
Expand Down
4 changes: 2 additions & 2 deletions rockcraft/services/service_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,11 @@ class RockcraftServiceFactory(ServiceFactory):
ImageClass: type[services.RockcraftImageService] = services.RockcraftImageService

# These are overrides of default ServiceFactory services
LifecycleClass: type[
LifecycleClass: type[ # type: ignore[reportIncompatibleVariableOverride]
services.RockcraftLifecycleService
] = services.RockcraftLifecycleService
PackageClass: type[base_services.PackageService] = services.RockcraftPackageService
ProviderClass: type[
ProviderClass: type[ # type: ignore[reportIncompatibleVariableOverride]
services.RockcraftProviderService
] = services.RockcraftProviderService

Expand Down
10 changes: 8 additions & 2 deletions rockcraft/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,20 @@
import pathlib
import shutil
import sys
from collections import namedtuple
from distutils.util import strtobool # pylint: disable=deprecated-module
from typing import NamedTuple

import rockcraft.errors

logger = logging.getLogger(__name__)

OSPlatform = namedtuple("OSPlatform", "system release machine")

class OSPlatform(NamedTuple):
"""Tuple containing the OS platform information."""

system: str
release: str
machine: str


def is_managed_mode() -> bool:
Expand Down