Skip to content

Commit

Permalink
refactor: clean up assertion services
Browse files Browse the repository at this point in the history
Signed-off-by: Callahan Kovacs <[email protected]>
  • Loading branch information
mr-cal committed Sep 20, 2024
1 parent ad3483f commit 3f80395
Show file tree
Hide file tree
Showing 8 changed files with 65 additions and 81 deletions.
8 changes: 4 additions & 4 deletions snapcraft/services/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,20 @@

"""Snapcraft services."""

from snapcraft.services.assertions import AssertionService
from snapcraft.services.assertions import Assertion
from snapcraft.services.lifecycle import Lifecycle
from snapcraft.services.package import Package
from snapcraft.services.provider import Provider
from snapcraft.services.registries import RegistriesService
from snapcraft.services.registries import Registries
from snapcraft.services.remotebuild import RemoteBuild
from snapcraft.services.service_factory import SnapcraftServiceFactory

__all__ = [
"AssertionService",
"Assertion",
"Lifecycle",
"Package",
"Provider",
"RegistriesService",
"Registries",
"RemoteBuild",
"SnapcraftServiceFactory",
]
10 changes: 5 additions & 5 deletions snapcraft/services/assertions.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
from snapcraft import const, errors, models, store


class AssertionService(base.AppService):
class Assertion(base.AppService):
"""Abstract service for interacting with assertions."""

@override
Expand All @@ -41,8 +41,8 @@ def setup(self) -> None:

@property
@abc.abstractmethod
def _assertion_type(self) -> str:
"""The pluralized name of the assertion type."""
def _assertion_name(self) -> str:
"""The lowercase name of the assertion type."""

@abc.abstractmethod
def _get_assertions(self, name: str | None = None) -> list[models.Assertion]:
Expand Down Expand Up @@ -81,7 +81,7 @@ def list_assertions(self, *, output_format: str, name: str | None = None) -> Non
match output_format:
case const.OutputFormat.json:
json_assertions = {
self._assertion_type.lower(): [
f"{self._assertion_name}s": [
{
header.lower(): value
for header, value in zip(headers, assertion)
Expand All @@ -102,4 +102,4 @@ def list_assertions(self, *, output_format: str, name: str | None = None) -> Non
msg=f"'--format {output_format}'",
)
else:
craft_cli.emit.message(f"No {self._assertion_type} found.")
craft_cli.emit.message(f"No {self._assertion_name}s found.")
24 changes: 5 additions & 19 deletions snapcraft/services/registries.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

"""Abstract service class for assertions."""
"""Service class for registries."""

from __future__ import annotations

Expand All @@ -23,39 +23,25 @@
from typing_extensions import override

from snapcraft import models
from snapcraft.services import AssertionService
from snapcraft.services import Assertion


class RegistriesService(AssertionService):
class Registries(Assertion):
"""Service for interacting with registries."""

@property
@override
def _assertion_type(self) -> str:
"""The pluralized name of the assertion type."""
return "registries"
def _assertion_name(self) -> str:
return "registries set"

@override
def _get_assertions(self, name: str | None = None) -> list[models.Assertion]:
"""Get assertions from the store.
:param name: The name of the assertion to retrieve. If not provided, all
assertions are retrieved.
:returns: A list of assertions.
"""
return self._store_client.list_registries(name=name)

@override
def _normalize_assertions(
self, assertions: list[models.Assertion]
) -> tuple[list[str], list[list[Any]]]:
"""Convert a list of assertion models to a tuple of headers and data.
:param assertions: A list of assertions to normalize.
:returns: A tuple containing the headers and normalized assertions.
"""
headers = ["Account ID", "Name", "Revision", "When"]
registries = [
[
Expand Down
6 changes: 3 additions & 3 deletions snapcraft/services/service_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,9 @@ class SnapcraftServiceFactory(ServiceFactory):
services.RemoteBuild
] = services.RemoteBuild
RegistriesClass: type[ # type: ignore[reportIncompatibleVariableOverride]
services.RegistriesService
] = services.RegistriesService
services.Registries
] = services.Registries

if TYPE_CHECKING:
# Allow static type check to report correct types for Snapcraft services
registries: services.RegistriesService = None # type: ignore[assignment]
registries: services.Registries = None # type: ignore[assignment]
4 changes: 1 addition & 3 deletions tests/unit/commands/test_registries.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,7 @@

@pytest.fixture
def mock_list_assertions(mocker):
return mocker.patch(
"snapcraft.services.registries.RegistriesService.list_assertions"
)
return mocker.patch("snapcraft.services.registries.Registries.list_assertions")


@pytest.mark.usefixtures("memory_keyring")
Expand Down
52 changes: 27 additions & 25 deletions tests/unit/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -533,9 +533,9 @@ class FakeRemoteBuildService(RemoteBuild):
@pytest.fixture()
def registries_service(default_factory, mocker):
from snapcraft.application import APP_METADATA
from snapcraft.services import RegistriesService
from snapcraft.services import Registries

service = RegistriesService(app=APP_METADATA, services=default_factory)
service = Registries(app=APP_METADATA, services=default_factory)
service._store_client = mocker.patch(
"snapcraft.store.StoreClientCLI", autospec=True
)
Expand All @@ -544,32 +544,34 @@ def registries_service(default_factory, mocker):


@pytest.fixture()
def fake_registry_assertion_data():
"""Returns a dictionary of assertion data with required fields."""
def fake_registry_assertion():
"""Returns a fake registry assertion with required fields."""
from snapcraft.models import RegistryAssertion

def _assertion_data(**kwargs) -> dict[str, Any]:
return {
"account_id": "test-account-id",
"authority_id": "test-authority-id",
"name": "test-registry",
"timestamp": "2024-01-01T10:20:30Z",
"type": "registry",
"views": {
"wifi-setup": {
"rules": [
{
"access": "read-write",
"request": "ssids",
"storage": "wifi.ssids",
}
]
}
},
**kwargs,
}
def _fake_registry_assertion(**kwargs) -> RegistryAssertion:
return RegistryAssertion.unmarshal(
{
"account_id": "test-account-id",
"authority_id": "test-authority-id",
"name": "test-registry",
"timestamp": "2024-01-01T10:20:30Z",
"type": "registry",
"views": {
"wifi-setup": {
"rules": [
{
"access": "read-write",
"request": "ssids",
"storage": "wifi.ssids",
}
]
}
},
**kwargs,
}
)

return RegistryAssertion.unmarshal(_assertion_data())
return _fake_registry_assertion


@pytest.fixture()
Expand Down
24 changes: 12 additions & 12 deletions tests/unit/services/test_assertions.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,15 @@ class FakeAssertion(CraftBaseModel):


@pytest.fixture
def mock_assertion_service(default_factory):
def fake_assertion_service(default_factory):
from snapcraft.application import APP_METADATA
from snapcraft.services import AssertionService
from snapcraft.services import Assertion

class FakeAssertionService(AssertionService):
class FakeAssertionService(Assertion):
@property
@override
def _assertion_type(self) -> str:
return "fake-assertions"
def _assertion_name(self) -> str:
return "fake assertion"

@override
def _get_assertions( # type: ignore[override]
Expand Down Expand Up @@ -70,9 +70,9 @@ def _normalize_assertions( # type: ignore[override]
return FakeAssertionService(app=APP_METADATA, services=default_factory)


def test_list_assertions_table(mock_assertion_service, emitter):
def test_list_assertions_table(fake_assertion_service, emitter):
"""List assertions as a table."""
mock_assertion_service.list_assertions(
fake_assertion_service.list_assertions(
output_format=const.OutputFormat.table, name="test-registry"
)

Expand All @@ -86,17 +86,17 @@ def test_list_assertions_table(mock_assertion_service, emitter):
)


def test_list_assertions_json(mock_assertion_service, emitter):
def test_list_assertions_json(fake_assertion_service, emitter):
"""List assertions as json."""
mock_assertion_service.list_assertions(
fake_assertion_service.list_assertions(
output_format=const.OutputFormat.json, name="test-registry"
)

emitter.assert_message(
textwrap.dedent(
"""\
{
"fake-assertions": [
"fake assertions": [
{
"test-field-1": "test-value-1",
"test-field-2": 0
Expand All @@ -111,11 +111,11 @@ def test_list_assertions_json(mock_assertion_service, emitter):
)


def test_list_assertions_unknown_format(mock_assertion_service):
def test_list_assertions_unknown_format(fake_assertion_service):
"""Error for unknown formats."""
expected = "Command or feature not implemented: '--format unknown'"

with pytest.raises(errors.FeatureNotImplemented, match=expected):
mock_assertion_service.list_assertions(
fake_assertion_service.list_assertions(
output_format="unknown", name="test-registry"
)
18 changes: 8 additions & 10 deletions tests/unit/services/test_registries.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@


def test_registries_service_type(registries_service):
assert registries_service._assertion_type == "registries"
assert registries_service._assertion_name == "registries set"


def test_get_assertions(registries_service):
Expand All @@ -36,16 +36,14 @@ def test_normalize_assertions_empty(registries_service, check):
check.equal(registries, [])


def test_normalize_assertions(fake_registry_assertion_data, registries_service, check):
def test_normalize_assertions(fake_registry_assertion, registries_service, check):
registries = [
fake_registry_assertion_data,
fake_registry_assertion_data.copy(
update={
"account_id": "test-account-id-2",
"name": "test-registry-2",
"revision": 100,
"timestamp": "2024-12-31",
}
fake_registry_assertion(),
fake_registry_assertion(
account_id="test-account-id-2",
name="test-registry-2",
revision=100,
timestamp="2024-12-31",
),
]

Expand Down

0 comments on commit 3f80395

Please sign in to comment.