diff --git a/src/ahriman/core/report/html.py b/src/ahriman/core/report/html.py
index 3bff8567..3d5dab1f 100644
--- a/src/ahriman/core/report/html.py
+++ b/src/ahriman/core/report/html.py
@@ -23,7 +23,7 @@ from typing import Callable, Dict, Iterable
from ahriman.core.configuration import Configuration
from ahriman.core.report.report import Report
-from ahriman.core.util import pretty_size, pretty_datetime
+from ahriman.core.util import pretty_datetime, pretty_size
from ahriman.models.package import Package
from ahriman.models.sign_settings import SignSettings
@@ -38,7 +38,18 @@ class HTML(Report):
link_path - prefix fo packages to download, string, required
has_package_signed - True in case if package sign enabled, False otherwise, required
has_repo_signed - True in case if repository database sign enabled, False otherwise, required
- packages - sorted list of packages properties: archive_size, build_date, filename, installed_size, name, version. Required
+ packages - sorted list of packages properties, required
+ * architecture, string
+ * archive_size, pretty printed size, string
+ * build_date, pretty printed datetime, string
+ * description, string
+ * filename, string,
+ * groups, sorted list of strings
+ * installed_size, pretty printed datetime, string
+ * licenses, sorted list of strings
+ * name, string
+ * url, string
+ * version, string
pgp_key - default PGP key ID, string, optional
repository - repository name, string, required
@@ -48,7 +59,7 @@ class HTML(Report):
:ivar pgp_key: default PGP key
:ivar report_path: output path to html report
:ivar sign_targets: targets to sign enabled in configuration
- :ivar tempate_path: path to directory with jinja templates
+ :ivar template_path: path to directory with jinja templates
"""
def __init__(self, architecture: str, config: Configuration) -> None:
@@ -83,11 +94,16 @@ class HTML(Report):
content = [
{
+ "architecture": properties.architecture or "",
"archive_size": pretty_size(properties.archive_size),
"build_date": pretty_datetime(properties.build_date),
+ "description": properties.description or "",
"filename": properties.filename,
+ "groups": properties.groups,
"installed_size": pretty_size(properties.installed_size),
+ "licenses": properties.licenses,
"name": package,
+ "url": properties.url or "",
"version": base.version
} for base in packages for package, properties in base.packages.items()
]
diff --git a/src/ahriman/models/package.py b/src/ahriman/models/package.py
index f028efed..3692dd55 100644
--- a/src/ahriman/models/package.py
+++ b/src/ahriman/models/package.py
@@ -59,6 +59,13 @@ class Package:
"""
return f"{self.aur_url}/{self.base}.git"
+ @property
+ def groups(self) -> List[str]:
+ """
+ :return: sum of groups per each package
+ """
+ return sorted(set(sum([package.groups for package in self.packages.values()], start=[])))
+
@property
def is_single_package(self) -> bool:
"""
@@ -78,6 +85,13 @@ class Package:
or self.base.endswith("-hg")\
or self.base.endswith("-svn")
+ @property
+ def licenses(self) -> List[str]:
+ """
+ :return: sum of licenses per each package
+ """
+ return sorted(set(sum([package.licenses for package in self.packages.values()], start=[])))
+
@property
def web_url(self) -> str:
"""
@@ -95,8 +109,8 @@ class Package:
:return: package properties
"""
package = pacman.handle.load_pkg(str(path))
- properties = PackageDescription(package.size, package.builddate, path.name, package.isize)
- return cls(package.base, package.version, aur_url, {package.name: properties})
+ return cls(package.base, package.version, aur_url,
+ {package.name: PackageDescription.from_package(package, path)})
@classmethod
def from_aur(cls: Type[Package], name: str, aur_url: str) -> Package:
diff --git a/src/ahriman/models/package_desciption.py b/src/ahriman/models/package_desciption.py
index 4e98adf0..e71a2e50 100644
--- a/src/ahriman/models/package_desciption.py
+++ b/src/ahriman/models/package_desciption.py
@@ -17,25 +17,38 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
#
-from dataclasses import dataclass
+from __future__ import annotations
+
+from dataclasses import dataclass, field
from pathlib import Path
-from typing import Optional
+from pyalpm import Package # type: ignore
+from typing import List, Optional, Type
@dataclass
class PackageDescription:
"""
package specific properties
+ :ivar architecture: package architecture
:ivar archive_size: package archive size
:ivar build_date: package build date
+ :ivar description: package description
:ivar filename: package archive name
+ :ivar groups: package groups
:ivar installed_size: package installed size
+ :ivar licenses: package licenses list
+ :ivar url: package url
"""
+ architecture: Optional[str] = None
archive_size: Optional[int] = None
build_date: Optional[int] = None
+ description: Optional[str] = None
filename: Optional[str] = None
+ groups: List[str] = field(default_factory=list)
installed_size: Optional[int] = None
+ licenses: List[str] = field(default_factory=list)
+ url: Optional[str] = None
@property
def filepath(self) -> Optional[Path]:
@@ -43,3 +56,22 @@ class PackageDescription:
:return: path object for current filename
"""
return Path(self.filename) if self.filename is not None else None
+
+ @classmethod
+ def from_package(cls: Type[PackageDescription], package: Package, path: Path) -> PackageDescription:
+ """
+ construct class from alpm package class
+ :param package: alpm generated object
+ :param path: path to package archive
+ :return: package properties based on tarball
+ """
+ return PackageDescription(
+ architecture=package.arch,
+ archive_size=package.size,
+ build_date=package.builddate,
+ description=package.desc,
+ filename=path.name,
+ groups=package.groups,
+ installed_size=package.isize,
+ licenses=package.licenses,
+ url=package.url)
diff --git a/src/ahriman/web/views/index.py b/src/ahriman/web/views/index.py
index 270a983d..e0ebac3d 100644
--- a/src/ahriman/web/views/index.py
+++ b/src/ahriman/web/views/index.py
@@ -34,10 +34,20 @@ class IndexView(BaseView):
It uses jinja2 templates for report generation, the following variables are allowed:
architecture - repository architecture, string, required
- packages - sorted list of packages properties: base, packages (sorted list), status,
- timestamp, version, web_url. Required
+ packages - sorted list of packages properties, required
+ * base, string
+ * groups, sorted list of strings
+ * licenses, sorted list of strings
+ * packages, sorted list of strings
+ * status, string based on enum value
+ * timestamp, pretty printed datetime, string
+ * version, string
+ * web_url, string
repository - repository name, string, required
- service - service status properties: status, status_color, timestamp. Required
+ service - service status properties, required
+ * status, string based on enum value
+ * status_color, string based on enum value
+ * timestamp, pretty printed datetime, string
version - ahriman version, string, required
"""
@@ -51,6 +61,8 @@ class IndexView(BaseView):
packages = [
{
"base": package.base,
+ "groups": package.groups,
+ "licenses": package.licenses,
"packages": list(sorted(package.packages)),
"status": status.status.value,
"timestamp": pretty_datetime(status.timestamp),
diff --git a/tests/ahriman/conftest.py b/tests/ahriman/conftest.py
index ee5aa2d2..cd99799b 100644
--- a/tests/ahriman/conftest.py
+++ b/tests/ahriman/conftest.py
@@ -58,28 +58,43 @@ def package_python_schedule(
@pytest.fixture
def package_description_ahriman() -> PackageDescription:
return PackageDescription(
+ architecture="x86_64",
archive_size=4200,
build_date=42,
+ description="ArcHlinux ReposItory MANager",
filename="ahriman-0.12.1-1-any.pkg.tar.zst",
- installed_size=4200000)
+ groups=[],
+ installed_size=4200000,
+ licenses=["GPL3"],
+ url="https://github.com/arcan1s/ahriman")
@pytest.fixture
def package_description_python_schedule() -> PackageDescription:
return PackageDescription(
+ architecture="x86_64",
archive_size=4201,
build_date=421,
+ description="Python job scheduling for humans.",
filename="python-schedule-1.0.0-2-any.pkg.tar.zst",
- installed_size=4200001)
+ groups=[],
+ installed_size=4200001,
+ licenses=["MIT"],
+ url="https://github.com/dbader/schedule")
@pytest.fixture
def package_description_python2_schedule() -> PackageDescription:
return PackageDescription(
+ architecture="x86_64",
archive_size=4202,
build_date=422,
+ description="Python job scheduling for humans.",
filename="python2-schedule-1.0.0-2-any.pkg.tar.zst",
- installed_size=4200002)
+ groups=[],
+ installed_size=4200002,
+ licenses=["MIT"],
+ url="https://github.com/dbader/schedule")
@pytest.fixture
diff --git a/tests/ahriman/models/test_package.py b/tests/ahriman/models/test_package.py
index cb3b9640..c8201f4a 100644
--- a/tests/ahriman/models/test_package.py
+++ b/tests/ahriman/models/test_package.py
@@ -14,6 +14,17 @@ def test_git_url(package_ahriman: Package) -> None:
assert package_ahriman.base in package_ahriman.git_url
+def test_groups(package_ahriman: Package) -> None:
+ """
+ must return list of groups for each package
+ """
+ assert all(
+ all(group in package_ahriman.groups for group in package.groups)
+ for package in package_ahriman.packages.values()
+ )
+ assert sorted(package_ahriman.groups) == package_ahriman.groups
+
+
def test_is_single_package_false(package_python_schedule: Package) -> None:
"""
python-schedule must not be single package
@@ -42,6 +53,17 @@ def test_is_vcs_true(package_tpacpi_bat_git: Package) -> None:
assert package_tpacpi_bat_git.is_vcs
+def test_licenses(package_ahriman: Package) -> None:
+ """
+ must return list of licenses for each package
+ """
+ assert all(
+ all(lic in package_ahriman.licenses for lic in package.licenses)
+ for package in package_ahriman.packages.values()
+ )
+ assert sorted(package_ahriman.licenses) == package_ahriman.licenses
+
+
def test_web_url(package_ahriman: Package) -> None:
"""
must generate valid web url