Files
ahriman/ahriman-core/src/ahriman/models/package_description.py
T

179 lines
6.5 KiB
Python

#
# Copyright (c) 2021-2026 ahriman team.
#
# This file is part of ahriman
# (see https://github.com/arcan1s/ahriman).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# 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 <http://www.gnu.org/licenses/>.
#
from dataclasses import dataclass, field, fields
from pathlib import Path
from pyalpm import Package # type: ignore[import-not-found]
from typing import Any, Self
from ahriman.core.utils import dataclass_view, filter_json, trim_package
from ahriman.models.aur_package import AURPackage
@dataclass(kw_only=True)
class PackageDescription:
"""
package specific properties
Attributes:
architecture(str | None): package architecture
archive_size(int | None): package archive size
build_date(int | None): package build date
check_depends(list[str]): package dependencies list used for check functions
depends(list[str]): package dependencies list
opt_depends(list[str]): optional package dependencies list
make_depends(list[str]): package dependencies list used for building
description(str | None): package description
filename(str | None): package archive name
groups(list[str]): package groups
installed_size(int | None): package installed size
licenses(list[str]): package licenses list
provides(list[str]): list of provided packages
url(str | None): package url
Examples:
Unlike the :class:`ahriman.models.package.Package` class, this implementation only holds properties.
The recommended way to deal with it is to read data based on the source type - either JSON or
:class:`pyalpm.Package` instance::
>>> description = PackageDescription.from_json(dump)
>>>
>>> from pathlib import Path
>>> from ahriman.core.alpm.pacman import Pacman
>>> from ahriman.core.configuration import Configuration
>>> from ahriman.models.repository_id import RepositoryId
>>>
>>> configuration = Configuration()
>>> pacman = Pacman(RepositoryId("x86_64", "aur"), configuration)
>>> pyalpm_description = next(package for package in pacman.package_get("pacman"))
>>> description = PackageDescription.from_package(
>>> pyalpm_description, Path("/var/cache/pacman/pkg/pacman-6.0.1-4-x86_64.pkg.tar.zst"))
"""
architecture: str | None = None
archive_size: int | None = None
build_date: int | None = None
depends: list[str] = field(default_factory=list)
make_depends: list[str] = field(default_factory=list)
opt_depends: list[str] = field(default_factory=list)
check_depends: list[str] = field(default_factory=list)
description: str | None = None
filename: str | None = None
groups: list[str] = field(default_factory=list)
installed_size: int | None = None
licenses: list[str] = field(default_factory=list)
provides: list[str] = field(default_factory=list)
url: str | None = None
def __post_init__(self) -> None:
"""
update packages lists accordingly
"""
self.depends = [trim_package(package) for package in self.depends]
self.make_depends = [trim_package(package) for package in self.make_depends]
self.opt_depends = [trim_package(package) for package in self.opt_depends]
self.check_depends = [trim_package(package) for package in self.check_depends]
self.provides = [trim_package(package) for package in self.provides]
@property
def filepath(self) -> Path | None:
"""
wrapper for filename, convert it to Path object
Returns:
Path | None: path object for current filename
"""
return Path(self.filename) if self.filename is not None else None
@classmethod
def from_aur(cls, package: AURPackage) -> Self:
"""
construct properties from AUR package model
Args:
package(AURPackage): AUR package model
Returns:
Self: package properties based on source AUR package
"""
return cls(
build_date=int(package.last_modified.timestamp()),
depends=package.depends,
make_depends=package.make_depends,
opt_depends=package.opt_depends,
check_depends=package.check_depends,
description=package.description,
licenses=package.license,
provides=package.provides,
url=package.url,
)
@classmethod
def from_json(cls, dump: dict[str, Any]) -> Self:
"""
construct package properties from JSON dump
Args:
dump(dict[str, Any]): JSON dump body
Returns:
Self: package properties
"""
# filter to only known fields
known_fields = [pair.name for pair in fields(cls)]
return cls(**filter_json(dump, known_fields))
@classmethod
def from_package(cls, package: Package, path: Path) -> Self:
"""
construct class from alpm package class
Args:
package(Package): alpm generated object
path(Path): path to package archive
Returns:
Self: package properties based on tarball
"""
return cls(
architecture=package.arch,
archive_size=package.size,
build_date=package.builddate,
depends=package.depends,
make_depends=package.makedepends,
opt_depends=package.optdepends,
check_depends=package.checkdepends,
description=package.desc,
filename=path.name,
groups=package.groups,
installed_size=package.isize,
licenses=package.licenses,
provides=package.provides,
url=package.url,
)
def view(self) -> dict[str, Any]:
"""
generate JSON package view
Returns:
dict[str, Any]: json-friendly dictionary
"""
return dataclass_view(self)