mirror of
https://github.com/arcan1s/ahriman.git
synced 2025-07-15 06:55:48 +00:00
constistent classmethod and staticmethod usage
General idea is to use classmethod for every constructor and statismethod otherwise. Also use self and cls whenever it's possible to call static and class methods
This commit is contained in:
@ -80,7 +80,7 @@ class Lock:
|
||||
:param exc_tb: exception traceback if any
|
||||
:return: always False (do not suppress any exception)
|
||||
"""
|
||||
self.remove()
|
||||
self.clear()
|
||||
status = BuildStatusEnum.Success if exc_val is None else BuildStatusEnum.Failed
|
||||
self.reporter.update_self(status)
|
||||
return False
|
||||
@ -96,6 +96,14 @@ class Lock:
|
||||
if current_uid != root_uid:
|
||||
raise UnsafeRun(current_uid, root_uid)
|
||||
|
||||
def clear(self) -> None:
|
||||
"""
|
||||
remove lock file
|
||||
"""
|
||||
if self.path is None:
|
||||
return
|
||||
self.path.unlink(missing_ok=True)
|
||||
|
||||
def create(self) -> None:
|
||||
"""
|
||||
create lock file
|
||||
@ -106,11 +114,3 @@ class Lock:
|
||||
self.path.touch(exist_ok=self.force)
|
||||
except FileExistsError:
|
||||
raise DuplicateRun()
|
||||
|
||||
def remove(self) -> None:
|
||||
"""
|
||||
remove lock file
|
||||
"""
|
||||
if self.path is None:
|
||||
return
|
||||
self.path.unlink(missing_ok=True)
|
||||
|
@ -123,4 +123,4 @@ class Task:
|
||||
if self.cache_path.is_dir():
|
||||
# no need to clone whole repository, just copy from cache first
|
||||
shutil.copytree(self.cache_path, git_path)
|
||||
return Task.fetch(git_path, self.package.git_url)
|
||||
return self.fetch(git_path, self.package.git_url)
|
||||
|
@ -17,9 +17,11 @@
|
||||
# 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 __future__ import annotations
|
||||
|
||||
import logging
|
||||
|
||||
from typing import Iterable
|
||||
from typing import Iterable, Type
|
||||
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.exceptions import ReportFailed
|
||||
@ -45,30 +47,34 @@ class Report:
|
||||
self.architecture = architecture
|
||||
self.configuration = configuration
|
||||
|
||||
@staticmethod
|
||||
def run(architecture: str, configuration: Configuration, target: str, packages: Iterable[Package]) -> None:
|
||||
@classmethod
|
||||
def load(cls: Type[Report], architecture: str, configuration: Configuration, target: str) -> Report:
|
||||
"""
|
||||
run report generation
|
||||
load client from settings
|
||||
:param architecture: repository architecture
|
||||
:param configuration: configuration instance
|
||||
:param target: target to generate report (e.g. html)
|
||||
:param packages: list of packages to generate report
|
||||
:return: client according to current settings
|
||||
"""
|
||||
provider = ReportSettings.from_option(target)
|
||||
if provider == ReportSettings.HTML:
|
||||
from ahriman.core.report.html import HTML
|
||||
report: Report = HTML(architecture, configuration)
|
||||
else:
|
||||
report = Report(architecture, configuration)
|
||||
|
||||
try:
|
||||
report.generate(packages)
|
||||
except Exception:
|
||||
report.logger.exception(f"report generation failed for target {provider.name}")
|
||||
raise ReportFailed()
|
||||
return HTML(architecture, configuration)
|
||||
return cls(architecture, configuration) # should never happen
|
||||
|
||||
def generate(self, packages: Iterable[Package]) -> None:
|
||||
"""
|
||||
generate report for the specified packages
|
||||
:param packages: list of packages to generate report
|
||||
"""
|
||||
|
||||
def run(self, packages: Iterable[Package]) -> None:
|
||||
"""
|
||||
run report generation
|
||||
:param packages: list of packages to generate report
|
||||
"""
|
||||
try:
|
||||
self.generate(packages)
|
||||
except Exception:
|
||||
self.logger.exception("report generation failed")
|
||||
raise ReportFailed()
|
||||
|
@ -108,7 +108,8 @@ class Executor(Cleaner):
|
||||
if targets is None:
|
||||
targets = self.configuration.getlist("report", "target")
|
||||
for target in targets:
|
||||
Report.run(self.architecture, self.configuration, target, self.packages())
|
||||
runner = Report.load(self.architecture, self.configuration, target)
|
||||
runner.run(self.packages())
|
||||
|
||||
def process_sync(self, targets: Optional[Iterable[str]]) -> None:
|
||||
"""
|
||||
@ -118,7 +119,8 @@ class Executor(Cleaner):
|
||||
if targets is None:
|
||||
targets = self.configuration.getlist("upload", "target")
|
||||
for target in targets:
|
||||
Upload.run(self.architecture, self.configuration, target, self.paths.repository)
|
||||
runner = Upload.load(self.architecture, self.configuration, target)
|
||||
runner.run(self.paths.repository)
|
||||
|
||||
def process_update(self, packages: Iterable[Path]) -> Path:
|
||||
"""
|
||||
|
@ -19,7 +19,7 @@
|
||||
#
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import List, Optional, Tuple
|
||||
from typing import List, Optional, Tuple, Type
|
||||
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.models.build_status import BuildStatus, BuildStatusEnum
|
||||
@ -31,6 +31,20 @@ class Client:
|
||||
base build status reporter client
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def load(cls: Type[Client], configuration: Configuration) -> Client:
|
||||
"""
|
||||
load client from settings
|
||||
:param configuration: configuration instance
|
||||
:return: client according to current settings
|
||||
"""
|
||||
host = configuration.get("web", "host", fallback=None)
|
||||
port = configuration.getint("web", "port", fallback=None)
|
||||
if host is not None and port is not None:
|
||||
from ahriman.core.status.web_client import WebClient
|
||||
return WebClient(host, port)
|
||||
return cls()
|
||||
|
||||
def add(self, package: Package, status: BuildStatusEnum) -> None:
|
||||
"""
|
||||
add new package with status
|
||||
@ -109,18 +123,3 @@ class Client:
|
||||
:param package: current package properties
|
||||
"""
|
||||
return self.add(package, BuildStatusEnum.Unknown)
|
||||
|
||||
@staticmethod
|
||||
def load(configuration: Configuration) -> Client:
|
||||
"""
|
||||
load client from settings
|
||||
:param configuration: configuration instance
|
||||
:return: client according to current settings
|
||||
"""
|
||||
host = configuration.get("web", "host", fallback=None)
|
||||
port = configuration.getint("web", "port", fallback=None)
|
||||
if host is None or port is None:
|
||||
return Client()
|
||||
|
||||
from ahriman.core.status.web_client import WebClient
|
||||
return WebClient(host, port)
|
||||
|
@ -17,9 +17,12 @@
|
||||
# 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 __future__ import annotations
|
||||
|
||||
import logging
|
||||
|
||||
from pathlib import Path
|
||||
from typing import Type
|
||||
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.exceptions import SyncFailed
|
||||
@ -44,29 +47,33 @@ class Upload:
|
||||
self.architecture = architecture
|
||||
self.config = configuration
|
||||
|
||||
@staticmethod
|
||||
def run(architecture: str, configuration: Configuration, target: str, path: Path) -> None:
|
||||
@classmethod
|
||||
def load(cls: Type[Upload], architecture: str, configuration: Configuration, target: str) -> Upload:
|
||||
"""
|
||||
run remote sync
|
||||
load client from settings
|
||||
:param architecture: repository architecture
|
||||
:param configuration: configuration instance
|
||||
:param target: target to run sync (e.g. s3)
|
||||
:param path: local path to sync
|
||||
:return: client according to current settings
|
||||
"""
|
||||
provider = UploadSettings.from_option(target)
|
||||
if provider == UploadSettings.Rsync:
|
||||
from ahriman.core.upload.rsync import Rsync
|
||||
upload: Upload = Rsync(architecture, configuration)
|
||||
elif provider == UploadSettings.S3:
|
||||
return Rsync(architecture, configuration)
|
||||
if provider == UploadSettings.S3:
|
||||
from ahriman.core.upload.s3 import S3
|
||||
upload = S3(architecture, configuration)
|
||||
else:
|
||||
upload = Upload(architecture, configuration)
|
||||
return S3(architecture, configuration)
|
||||
return cls(architecture, configuration) # should never happen
|
||||
|
||||
def run(self, path: Path) -> None:
|
||||
"""
|
||||
run remote sync
|
||||
:param path: local path to sync
|
||||
"""
|
||||
try:
|
||||
upload.sync(path)
|
||||
self.sync(path)
|
||||
except Exception:
|
||||
upload.logger.exception(f"remote sync failed for {provider.name}")
|
||||
self.logger.exception("remote sync failed")
|
||||
raise SyncFailed()
|
||||
|
||||
def sync(self, path: Path) -> None:
|
||||
|
@ -63,7 +63,7 @@ class BuildStatus:
|
||||
"""
|
||||
build status holder
|
||||
:ivar status: build status
|
||||
:ivar _timestamp: build status update time
|
||||
:ivar timestamp: build status update time
|
||||
"""
|
||||
|
||||
def __init__(self, status: Union[BuildStatusEnum, str, None] = None,
|
||||
|
@ -156,6 +156,27 @@ class Package:
|
||||
aur_url=dump["aur_url"],
|
||||
packages=packages)
|
||||
|
||||
@classmethod
|
||||
def load(cls: Type[Package], path: Union[Path, str], pacman: Pacman, aur_url: str) -> Package:
|
||||
"""
|
||||
package constructor from available sources
|
||||
:param path: one of path to sources directory, path to archive or package name/base
|
||||
:param pacman: alpm wrapper instance (required to load from archive)
|
||||
:param aur_url: AUR root url
|
||||
:return: package properties
|
||||
"""
|
||||
try:
|
||||
maybe_path = Path(path)
|
||||
if maybe_path.is_dir():
|
||||
return cls.from_build(maybe_path, aur_url)
|
||||
if maybe_path.is_file():
|
||||
return cls.from_archive(maybe_path, pacman, aur_url)
|
||||
return cls.from_aur(str(path), aur_url)
|
||||
except InvalidPackageInfo:
|
||||
raise
|
||||
except Exception as e:
|
||||
raise InvalidPackageInfo(str(e))
|
||||
|
||||
@staticmethod
|
||||
def dependencies(path: Path) -> Set[str]:
|
||||
"""
|
||||
@ -194,29 +215,6 @@ class Package:
|
||||
prefix = f"{epoch}:" if epoch else ""
|
||||
return f"{prefix}{pkgver}-{pkgrel}"
|
||||
|
||||
@staticmethod
|
||||
def load(path: Union[Path, str], pacman: Pacman, aur_url: str) -> Package:
|
||||
"""
|
||||
package constructor from available sources
|
||||
:param path: one of path to sources directory, path to archive or package name/base
|
||||
:param pacman: alpm wrapper instance (required to load from archive)
|
||||
:param aur_url: AUR root url
|
||||
:return: package properties
|
||||
"""
|
||||
try:
|
||||
maybe_path = Path(path)
|
||||
if maybe_path.is_dir():
|
||||
package: Package = Package.from_build(maybe_path, aur_url)
|
||||
elif maybe_path.is_file():
|
||||
package = Package.from_archive(maybe_path, pacman, aur_url)
|
||||
else:
|
||||
package = Package.from_aur(str(path), aur_url)
|
||||
return package
|
||||
except InvalidPackageInfo:
|
||||
raise
|
||||
except Exception as e:
|
||||
raise InvalidPackageInfo(str(e))
|
||||
|
||||
def actual_version(self, paths: RepositoryPaths) -> str:
|
||||
"""
|
||||
additional method to handle VCS package versions
|
||||
|
@ -65,7 +65,7 @@ class PackageDescription:
|
||||
:param path: path to package archive
|
||||
:return: package properties based on tarball
|
||||
"""
|
||||
return PackageDescription(
|
||||
return cls(
|
||||
architecture=package.arch,
|
||||
archive_size=package.size,
|
||||
build_date=package.builddate,
|
||||
|
@ -20,6 +20,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from enum import Enum, auto
|
||||
from typing import Type
|
||||
|
||||
from ahriman.core.exceptions import InvalidOption
|
||||
|
||||
@ -32,13 +33,13 @@ class ReportSettings(Enum):
|
||||
|
||||
HTML = auto()
|
||||
|
||||
@staticmethod
|
||||
def from_option(value: str) -> ReportSettings:
|
||||
@classmethod
|
||||
def from_option(cls: Type[ReportSettings], value: str) -> ReportSettings:
|
||||
"""
|
||||
construct value from configuration
|
||||
:param value: configuration value
|
||||
:return: parsed value
|
||||
"""
|
||||
if value.lower() in ("html",):
|
||||
return ReportSettings.HTML
|
||||
return cls.HTML
|
||||
raise InvalidOption(value)
|
||||
|
@ -20,6 +20,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from enum import Enum, auto
|
||||
from typing import Type
|
||||
|
||||
from ahriman.core.exceptions import InvalidOption
|
||||
|
||||
@ -34,15 +35,15 @@ class SignSettings(Enum):
|
||||
SignPackages = auto()
|
||||
SignRepository = auto()
|
||||
|
||||
@staticmethod
|
||||
def from_option(value: str) -> SignSettings:
|
||||
@classmethod
|
||||
def from_option(cls: Type[SignSettings], value: str) -> SignSettings:
|
||||
"""
|
||||
construct value from configuration
|
||||
:param value: configuration value
|
||||
:return: parsed value
|
||||
"""
|
||||
if value.lower() in ("package", "packages", "sign-package"):
|
||||
return SignSettings.SignPackages
|
||||
return cls.SignPackages
|
||||
if value.lower() in ("repository", "sign-repository"):
|
||||
return SignSettings.SignRepository
|
||||
return cls.SignRepository
|
||||
raise InvalidOption(value)
|
||||
|
@ -20,6 +20,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from enum import Enum, auto
|
||||
from typing import Type
|
||||
|
||||
from ahriman.core.exceptions import InvalidOption
|
||||
|
||||
@ -34,15 +35,15 @@ class UploadSettings(Enum):
|
||||
Rsync = auto()
|
||||
S3 = auto()
|
||||
|
||||
@staticmethod
|
||||
def from_option(value: str) -> UploadSettings:
|
||||
@classmethod
|
||||
def from_option(cls: Type[UploadSettings], value: str) -> UploadSettings:
|
||||
"""
|
||||
construct value from configuration
|
||||
:param value: configuration value
|
||||
:return: parsed value
|
||||
"""
|
||||
if value.lower() in ("rsync",):
|
||||
return UploadSettings.Rsync
|
||||
return cls.Rsync
|
||||
if value.lower() in ("s3",):
|
||||
return UploadSettings.S3
|
||||
return cls.S3
|
||||
raise InvalidOption(value)
|
||||
|
Reference in New Issue
Block a user