mirror of
https://github.com/arcan1s/ahriman.git
synced 2025-04-24 07:17:17 +00:00
review loggers once more
This commit makes loggers like java.util.logging with fully qualified logger name which is created by LazyLogging trait
This commit is contained in:
parent
eb5ac5a52b
commit
fac228d6c6
@ -60,6 +60,7 @@ Again, the most checks can be performed by `make check` command, though some add
|
||||
* The file size mentioned above must be applicable in general. In case of big classes consider splitting them into traits.
|
||||
* No global variable allowed outside of `ahriman.version` module.
|
||||
* Single quotes are not allowed. The reason behind this restriction is the fact that docstrings must be written by using double quotes only, and we would like to make style consistent.
|
||||
* If your class writes anything to log, the `ahriman.core.lazy_logging.LazyLogging` trait must be used.
|
||||
|
||||
### Other checks
|
||||
|
||||
|
@ -692,7 +692,7 @@ You can also edit configuration and forward logs to ``stderr``, just change ``ha
|
||||
|
||||
sed -i 's/handlers = syslog_handler/handlers = console_handler/g' /etc/ahriman.ini.d/logging.ini
|
||||
|
||||
You can even configure logging as you wish, but kindly refer to python ``logging`` module `configuration <https://docs.python.org/3/library/logging.config.html>`_.
|
||||
You can even configure logging as you wish, but kindly refer to python ``logging`` module `configuration <https://docs.python.org/3/library/logging.config.html>`_. The application uses java concept to log messages, e.g. class ``Application`` imported from ``ahriman.application.application`` package will have logger called ``ahriman.application.application.Application``. In order to e.g. change logger name for whole application package it is possible to change values for ``ahriman.application`` package; thus editing ``ahriman`` logger configuration will change logging for whole application (unless there are overrides for another logger).
|
||||
|
||||
Html customization
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
@ -1,5 +1,5 @@
|
||||
[loggers]
|
||||
keys = root,build,http,stderr,boto3,botocore,nose,s3transfer
|
||||
keys = root,http,stderr,boto3,botocore,nose,s3transfer
|
||||
|
||||
[handlers]
|
||||
keys = console_handler,syslog_handler
|
||||
@ -20,11 +20,11 @@ formatter = syslog_format
|
||||
args = ("/dev/log",)
|
||||
|
||||
[formatter_generic_format]
|
||||
format = [%(levelname)s %(asctime)s] [%(filename)s:%(lineno)d %(funcName)s]: %(message)s
|
||||
format = [%(levelname)s %(asctime)s] [%(threadName)s] [%(name)s]: %(message)s
|
||||
datefmt =
|
||||
|
||||
[formatter_syslog_format]
|
||||
format = [%(levelname)s] [%(name)s] [%(filename)s:%(lineno)d] [%(funcName)s]: %(message)s
|
||||
format = [%(levelname)s] [%(threadName)s] [%(name)s]: %(message)s
|
||||
datefmt =
|
||||
|
||||
[logger_root]
|
||||
@ -32,12 +32,6 @@ level = DEBUG
|
||||
handlers = syslog_handler
|
||||
qualname = root
|
||||
|
||||
[logger_build]
|
||||
level = DEBUG
|
||||
handlers = syslog_handler
|
||||
qualname = build
|
||||
propagate = 0
|
||||
|
||||
[logger_http]
|
||||
level = DEBUG
|
||||
handlers = syslog_handler
|
||||
|
@ -17,14 +17,13 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
import logging
|
||||
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.database import SQLite
|
||||
from ahriman.core.lazy_logging import LazyLogging
|
||||
from ahriman.core.repository import Repository
|
||||
|
||||
|
||||
class ApplicationProperties:
|
||||
class ApplicationProperties(LazyLogging):
|
||||
"""
|
||||
application base properties class
|
||||
|
||||
@ -32,7 +31,6 @@ class ApplicationProperties:
|
||||
architecture(str): repository architecture
|
||||
configuration(Configuration): configuration instance
|
||||
database(SQLite): database instance
|
||||
logger(logging.Logger): application logger
|
||||
repository(Repository): repository instance
|
||||
"""
|
||||
|
||||
@ -46,7 +44,6 @@ class ApplicationProperties:
|
||||
no_report(bool): force disable reporting
|
||||
unsafe(bool): if set no user check will be performed before path creation
|
||||
"""
|
||||
self.logger = logging.getLogger("root")
|
||||
self.configuration = configuration
|
||||
self.architecture = architecture
|
||||
self.database = SQLite.load(configuration)
|
||||
|
@ -20,7 +20,6 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import logging
|
||||
|
||||
from pathlib import Path
|
||||
from types import TracebackType
|
||||
@ -29,12 +28,13 @@ from typing import Literal, Optional, Type
|
||||
from ahriman import version
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.exceptions import DuplicateRun
|
||||
from ahriman.core.lazy_logging import LazyLogging
|
||||
from ahriman.core.status.client import Client
|
||||
from ahriman.core.util import check_user
|
||||
from ahriman.models.build_status import BuildStatusEnum
|
||||
|
||||
|
||||
class Lock:
|
||||
class Lock(LazyLogging):
|
||||
"""
|
||||
wrapper for application lock file
|
||||
|
||||
@ -115,10 +115,8 @@ class Lock:
|
||||
"""
|
||||
status = self.reporter.get_internal()
|
||||
if status.version is not None and status.version != version.__version__:
|
||||
logging.getLogger("root").warning(
|
||||
"status watcher version mismatch, our %s, their %s",
|
||||
version.__version__,
|
||||
status.version)
|
||||
self.logger.warning("status watcher version mismatch, our %s, their %s",
|
||||
version.__version__, status.version)
|
||||
|
||||
def check_user(self) -> None:
|
||||
"""
|
||||
|
@ -19,21 +19,17 @@
|
||||
#
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
|
||||
from typing import Dict, List, Type
|
||||
|
||||
from ahriman.core.alpm.pacman import Pacman
|
||||
from ahriman.core.lazy_logging import LazyLogging
|
||||
from ahriman.models.aur_package import AURPackage
|
||||
|
||||
|
||||
class Remote:
|
||||
class Remote(LazyLogging):
|
||||
"""
|
||||
base class for remote package search
|
||||
|
||||
Attributes:
|
||||
logger(logging.Logger): class logger
|
||||
|
||||
Examples:
|
||||
These classes are designed to be used without instancing. In order to achieve it several class methods are
|
||||
provided: ``info``, ``multisearch`` and ``search``. Thus, the basic flow is the following::
|
||||
@ -47,12 +43,6 @@ class Remote:
|
||||
directly, whereas ``multisearch`` splits search one by one and finds intersection between search results.
|
||||
"""
|
||||
|
||||
def __init__(self) -> None:
|
||||
"""
|
||||
default constructor
|
||||
"""
|
||||
self.logger = logging.getLogger("build")
|
||||
|
||||
@classmethod
|
||||
def info(cls: Type[Remote], package_name: str, *, pacman: Pacman) -> AURPackage:
|
||||
"""
|
||||
|
@ -17,22 +17,20 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
import logging
|
||||
|
||||
from pathlib import Path
|
||||
from typing import List
|
||||
|
||||
from ahriman.core.exceptions import BuildFailed
|
||||
from ahriman.core.lazy_logging import LazyLogging
|
||||
from ahriman.core.util import check_output
|
||||
from ahriman.models.repository_paths import RepositoryPaths
|
||||
|
||||
|
||||
class Repo:
|
||||
class Repo(LazyLogging):
|
||||
"""
|
||||
repo-add and repo-remove wrapper
|
||||
|
||||
Attributes:
|
||||
logger(logging.Logger): class logger
|
||||
name(str): repository name
|
||||
paths(RepositoryPaths): repository paths instance
|
||||
sign_args(List[str]): additional args which have to be used to sign repository archive
|
||||
@ -50,7 +48,6 @@ class Repo:
|
||||
paths(RepositoryPaths): repository paths instance
|
||||
sign_args(List[str]): additional args which have to be used to sign repository archive
|
||||
"""
|
||||
self.logger = logging.getLogger("build")
|
||||
self.name = name
|
||||
self.paths = paths
|
||||
self.uid, _ = paths.root_owner
|
||||
|
@ -19,23 +19,21 @@
|
||||
#
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
|
||||
from typing import Optional, Type
|
||||
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.database import SQLite
|
||||
from ahriman.core.lazy_logging import LazyLogging
|
||||
from ahriman.models.auth_settings import AuthSettings
|
||||
from ahriman.models.user_access import UserAccess
|
||||
|
||||
|
||||
class Auth:
|
||||
class Auth(LazyLogging):
|
||||
"""
|
||||
helper to deal with user authorization
|
||||
|
||||
Attributes:
|
||||
enabled(bool): indicates if authorization is enabled
|
||||
logger(logging.Logger): class logger
|
||||
max_age(int): session age in seconds. It will be used for both client side and server side checks
|
||||
allow_read_only(bool): allow read only access to APIs
|
||||
"""
|
||||
@ -48,8 +46,6 @@ class Auth:
|
||||
configuration(Configuration): configuration instance
|
||||
provider(AuthSettings, optional): authorization type definition (Default value = AuthSettings.Disabled)
|
||||
"""
|
||||
self.logger = logging.getLogger("http")
|
||||
|
||||
self.allow_read_only = configuration.getboolean("auth", "allow_read_only")
|
||||
|
||||
self.enabled = provider.is_enabled
|
||||
|
@ -17,82 +17,31 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
import logging
|
||||
import shutil
|
||||
|
||||
from pathlib import Path
|
||||
from typing import List, Optional
|
||||
|
||||
from ahriman.core.lazy_logging import LazyLogging
|
||||
from ahriman.core.util import check_output, walk
|
||||
from ahriman.models.package import Package
|
||||
from ahriman.models.remote_source import RemoteSource
|
||||
from ahriman.models.repository_paths import RepositoryPaths
|
||||
|
||||
|
||||
class Sources:
|
||||
class Sources(LazyLogging):
|
||||
"""
|
||||
helper to download package sources (PKGBUILD etc)
|
||||
|
||||
Attributes:
|
||||
DEFAULT_BRANCH(str): (class attribute) default branch to process git repositories.
|
||||
Must be used only for local stored repositories, use RemoteSource descriptor instead for real packages
|
||||
logger(logging.Logger): (class attribute) class logger
|
||||
"""
|
||||
|
||||
DEFAULT_BRANCH = "master" # default fallback branch
|
||||
logger = logging.getLogger("build")
|
||||
|
||||
_check_output = check_output
|
||||
|
||||
@staticmethod
|
||||
def _add(sources_dir: Path, *pattern: str) -> None:
|
||||
"""
|
||||
track found files via git
|
||||
|
||||
Args:
|
||||
sources_dir(Path): local path to git repository
|
||||
*pattern(str): glob patterns
|
||||
"""
|
||||
# glob directory to find files which match the specified patterns
|
||||
found_files: List[Path] = []
|
||||
for glob in pattern:
|
||||
found_files.extend(sources_dir.glob(glob))
|
||||
if not found_files:
|
||||
return # no additional files found
|
||||
Sources.logger.info("found matching files %s", found_files)
|
||||
# add them to index
|
||||
Sources._check_output("git", "add", "--intent-to-add",
|
||||
*[str(fn.relative_to(sources_dir)) for fn in found_files],
|
||||
exception=None, cwd=sources_dir, logger=Sources.logger)
|
||||
|
||||
@staticmethod
|
||||
def _diff(sources_dir: Path) -> str:
|
||||
"""
|
||||
generate diff from the current version and write it to the output file
|
||||
|
||||
Args:
|
||||
sources_dir(Path): local path to git repository
|
||||
|
||||
Returns:
|
||||
str: patch as plain string
|
||||
"""
|
||||
return Sources._check_output("git", "diff", exception=None, cwd=sources_dir, logger=Sources.logger)
|
||||
|
||||
@staticmethod
|
||||
def _move(pkgbuild_dir: Path, sources_dir: Path) -> None:
|
||||
"""
|
||||
move content from pkgbuild_dir to sources_dir
|
||||
|
||||
Args:
|
||||
pkgbuild_dir(Path): path to directory with pkgbuild from which need to move
|
||||
sources_dir(Path): path to target directory
|
||||
"""
|
||||
if pkgbuild_dir == sources_dir:
|
||||
return # directories are the same, no need to move
|
||||
for src in walk(pkgbuild_dir):
|
||||
dst = sources_dir / src.relative_to(pkgbuild_dir)
|
||||
shutil.move(src, dst)
|
||||
|
||||
@staticmethod
|
||||
def fetch(sources_dir: Path, remote: Optional[RemoteSource]) -> None:
|
||||
"""
|
||||
@ -102,37 +51,38 @@ class Sources:
|
||||
sources_dir(Path): local path to fetch
|
||||
remote(Optional[RemoteSource]): remote target (from where to fetch)
|
||||
"""
|
||||
instance = Sources()
|
||||
# local directory exists and there is .git directory
|
||||
is_initialized_git = (sources_dir / ".git").is_dir()
|
||||
if is_initialized_git and not Sources.has_remotes(sources_dir):
|
||||
if is_initialized_git and not instance.has_remotes(sources_dir):
|
||||
# there is git repository, but no remote configured so far
|
||||
Sources.logger.info("skip update at %s because there are no branches configured", sources_dir)
|
||||
instance.logger.info("skip update at %s because there are no branches configured", sources_dir)
|
||||
return
|
||||
|
||||
branch = remote.branch if remote is not None else Sources.DEFAULT_BRANCH
|
||||
branch = remote.branch if remote is not None else instance.DEFAULT_BRANCH
|
||||
if is_initialized_git:
|
||||
Sources.logger.info("update HEAD to remote at %s using branch %s", sources_dir, branch)
|
||||
instance.logger.info("update HEAD to remote at %s using branch %s", sources_dir, branch)
|
||||
Sources._check_output("git", "fetch", "origin", branch,
|
||||
exception=None, cwd=sources_dir, logger=Sources.logger)
|
||||
exception=None, cwd=sources_dir, logger=instance.logger)
|
||||
elif remote is not None:
|
||||
Sources.logger.info("clone remote %s to %s using branch %s", remote.git_url, sources_dir, branch)
|
||||
instance.logger.info("clone remote %s to %s using branch %s", remote.git_url, sources_dir, branch)
|
||||
Sources._check_output("git", "clone", "--branch", branch, "--single-branch",
|
||||
remote.git_url, str(sources_dir),
|
||||
exception=None, cwd=sources_dir, logger=Sources.logger)
|
||||
exception=None, cwd=sources_dir, logger=instance.logger)
|
||||
else:
|
||||
# it will cause an exception later
|
||||
Sources.logger.error("%s is not initialized, but no remote provided", sources_dir)
|
||||
instance.logger.error("%s is not initialized, but no remote provided", sources_dir)
|
||||
|
||||
# and now force reset to our branch
|
||||
Sources._check_output("git", "checkout", "--force", branch,
|
||||
exception=None, cwd=sources_dir, logger=Sources.logger)
|
||||
exception=None, cwd=sources_dir, logger=instance.logger)
|
||||
Sources._check_output("git", "reset", "--hard", f"origin/{branch}",
|
||||
exception=None, cwd=sources_dir, logger=Sources.logger)
|
||||
exception=None, cwd=sources_dir, logger=instance.logger)
|
||||
|
||||
# move content if required
|
||||
# we are using full path to source directory in order to make append possible
|
||||
pkgbuild_dir = remote.pkgbuild_dir if remote is not None else sources_dir.resolve()
|
||||
Sources._move((sources_dir / pkgbuild_dir).resolve(), sources_dir)
|
||||
instance.move((sources_dir / pkgbuild_dir).resolve(), sources_dir)
|
||||
|
||||
@staticmethod
|
||||
def has_remotes(sources_dir: Path) -> bool:
|
||||
@ -145,7 +95,8 @@ class Sources:
|
||||
Returns:
|
||||
bool: True in case if there is any remote and false otherwise
|
||||
"""
|
||||
remotes = Sources._check_output("git", "remote", exception=None, cwd=sources_dir, logger=Sources.logger)
|
||||
instance = Sources()
|
||||
remotes = Sources._check_output("git", "remote", exception=None, cwd=sources_dir, logger=instance.logger)
|
||||
return bool(remotes)
|
||||
|
||||
@staticmethod
|
||||
@ -156,8 +107,9 @@ class Sources:
|
||||
Args:
|
||||
sources_dir(Path): local path to sources
|
||||
"""
|
||||
instance = Sources()
|
||||
Sources._check_output("git", "init", "--initial-branch", Sources.DEFAULT_BRANCH,
|
||||
exception=None, cwd=sources_dir, logger=Sources.logger)
|
||||
exception=None, cwd=sources_dir, logger=instance.logger)
|
||||
|
||||
@staticmethod
|
||||
def load(sources_dir: Path, package: Package, patch: Optional[str], paths: RepositoryPaths) -> None:
|
||||
@ -170,29 +122,16 @@ class Sources:
|
||||
patch(Optional[str]): optional patch to be applied
|
||||
paths(RepositoryPaths): repository paths instance
|
||||
"""
|
||||
instance = Sources()
|
||||
if (cache_dir := paths.cache_for(package.base)).is_dir() and cache_dir != sources_dir:
|
||||
# no need to clone whole repository, just copy from cache first
|
||||
shutil.copytree(cache_dir, sources_dir, dirs_exist_ok=True)
|
||||
Sources.fetch(sources_dir, package.remote)
|
||||
|
||||
if patch is None:
|
||||
Sources.logger.info("no patches found")
|
||||
instance.logger.info("no patches found")
|
||||
return
|
||||
Sources.patch_apply(sources_dir, patch)
|
||||
|
||||
@staticmethod
|
||||
def patch_apply(sources_dir: Path, patch: str) -> None:
|
||||
"""
|
||||
apply patches if any
|
||||
|
||||
Args:
|
||||
sources_dir(Path): local path to directory with git sources
|
||||
patch(str): patch to be applied
|
||||
"""
|
||||
# create patch
|
||||
Sources.logger.info("apply patch from database")
|
||||
Sources._check_output("git", "apply", "--ignore-space-change", "--ignore-whitespace",
|
||||
exception=None, cwd=sources_dir, input_data=patch, logger=Sources.logger)
|
||||
instance.patch_apply(sources_dir, patch)
|
||||
|
||||
@staticmethod
|
||||
def patch_create(sources_dir: Path, *pattern: str) -> str:
|
||||
@ -206,6 +145,67 @@ class Sources:
|
||||
Returns:
|
||||
str: patch as plain text
|
||||
"""
|
||||
Sources._add(sources_dir, *pattern)
|
||||
diff = Sources._diff(sources_dir)
|
||||
instance = Sources()
|
||||
instance.add(sources_dir, *pattern)
|
||||
diff = instance.diff(sources_dir)
|
||||
return f"{diff}\n" # otherwise, patch will be broken
|
||||
|
||||
def add(self, sources_dir: Path, *pattern: str) -> None:
|
||||
"""
|
||||
track found files via git
|
||||
|
||||
Args:
|
||||
sources_dir(Path): local path to git repository
|
||||
*pattern(str): glob patterns
|
||||
"""
|
||||
# glob directory to find files which match the specified patterns
|
||||
found_files: List[Path] = []
|
||||
for glob in pattern:
|
||||
found_files.extend(sources_dir.glob(glob))
|
||||
if not found_files:
|
||||
return # no additional files found
|
||||
self.logger.info("found matching files %s", found_files)
|
||||
# add them to index
|
||||
Sources._check_output("git", "add", "--intent-to-add",
|
||||
*[str(fn.relative_to(sources_dir)) for fn in found_files],
|
||||
exception=None, cwd=sources_dir, logger=self.logger)
|
||||
|
||||
def diff(self, sources_dir: Path) -> str:
|
||||
"""
|
||||
generate diff from the current version and write it to the output file
|
||||
|
||||
Args:
|
||||
sources_dir(Path): local path to git repository
|
||||
|
||||
Returns:
|
||||
str: patch as plain string
|
||||
"""
|
||||
return Sources._check_output("git", "diff", exception=None, cwd=sources_dir, logger=self.logger)
|
||||
|
||||
def move(self, pkgbuild_dir: Path, sources_dir: Path) -> None:
|
||||
"""
|
||||
move content from pkgbuild_dir to sources_dir
|
||||
|
||||
Args:
|
||||
pkgbuild_dir(Path): path to directory with pkgbuild from which need to move
|
||||
sources_dir(Path): path to target directory
|
||||
"""
|
||||
del self
|
||||
if pkgbuild_dir == sources_dir:
|
||||
return # directories are the same, no need to move
|
||||
for src in walk(pkgbuild_dir):
|
||||
dst = sources_dir / src.relative_to(pkgbuild_dir)
|
||||
shutil.move(src, dst)
|
||||
|
||||
def patch_apply(self, sources_dir: Path, patch: str) -> None:
|
||||
"""
|
||||
apply patches if any
|
||||
|
||||
Args:
|
||||
sources_dir(Path): local path to directory with git sources
|
||||
patch(str): patch to be applied
|
||||
"""
|
||||
# create patch
|
||||
self.logger.info("apply patch from database")
|
||||
Sources._check_output("git", "apply", "--ignore-space-change", "--ignore-whitespace",
|
||||
exception=None, cwd=sources_dir, input_data=patch, logger=self.logger)
|
||||
|
@ -17,8 +17,6 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
import logging
|
||||
|
||||
from pathlib import Path
|
||||
from typing import List
|
||||
|
||||
@ -26,17 +24,17 @@ from ahriman.core.build_tools.sources import Sources
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.database import SQLite
|
||||
from ahriman.core.exceptions import BuildFailed
|
||||
from ahriman.core.lazy_logging import LazyLogging
|
||||
from ahriman.core.util import check_output
|
||||
from ahriman.models.package import Package
|
||||
from ahriman.models.repository_paths import RepositoryPaths
|
||||
|
||||
|
||||
class Task:
|
||||
class Task(LazyLogging):
|
||||
"""
|
||||
base package build task
|
||||
|
||||
Attributes:
|
||||
logger(logging.Logger): class logger
|
||||
package(Package): package definitions
|
||||
paths(RepositoryPaths): repository paths instance
|
||||
uid(int): uid of the repository owner user
|
||||
@ -53,7 +51,6 @@ class Task:
|
||||
configuration(Configuration): configuration instance
|
||||
paths(RepositoryPaths): repository paths instance
|
||||
"""
|
||||
self.logger = logging.getLogger("build")
|
||||
self.package = package
|
||||
self.paths = paths
|
||||
self.uid, _ = paths.root_owner
|
||||
|
@ -19,8 +19,6 @@
|
||||
#
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
|
||||
from importlib import import_module
|
||||
from pathlib import Path
|
||||
from pkgutil import iter_modules
|
||||
@ -29,11 +27,12 @@ from typing import List, Type
|
||||
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.database.data import migrate_data
|
||||
from ahriman.core.lazy_logging import LazyLogging
|
||||
from ahriman.models.migration import Migration
|
||||
from ahriman.models.migration_result import MigrationResult
|
||||
|
||||
|
||||
class Migrations:
|
||||
class Migrations(LazyLogging):
|
||||
"""
|
||||
simple migration wrapper for the sqlite
|
||||
idea comes from https://www.ash.dev/blog/simple-migration-system-in-sqlite/
|
||||
@ -41,7 +40,6 @@ class Migrations:
|
||||
Attributes:
|
||||
configuration(Configuration): configuration instance
|
||||
connection(Connection): database connection
|
||||
logger(logging.Logger): class logger
|
||||
"""
|
||||
|
||||
def __init__(self, connection: Connection, configuration: Configuration) -> None:
|
||||
@ -54,7 +52,6 @@ class Migrations:
|
||||
"""
|
||||
self.connection = connection
|
||||
self.configuration = configuration
|
||||
self.logger = logging.getLogger("root")
|
||||
|
||||
@classmethod
|
||||
def migrate(cls: Type[Migrations], connection: Connection, configuration: Configuration) -> MigrationResult:
|
||||
|
@ -17,23 +17,22 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
import logging
|
||||
import sqlite3
|
||||
|
||||
from pathlib import Path
|
||||
from sqlite3 import Connection, Cursor
|
||||
from typing import Any, Dict, Tuple, TypeVar, Callable
|
||||
|
||||
from ahriman.core.lazy_logging import LazyLogging
|
||||
|
||||
T = TypeVar("T")
|
||||
|
||||
|
||||
class Operations:
|
||||
class Operations(LazyLogging):
|
||||
"""
|
||||
base operation class
|
||||
|
||||
Attributes:
|
||||
logger(logging.Logger): class logger
|
||||
path(Path): path to the database file
|
||||
"""
|
||||
|
||||
@ -45,7 +44,6 @@ class Operations:
|
||||
path(Path): path to the database file
|
||||
"""
|
||||
self.path = path
|
||||
self.logger = logging.getLogger("root")
|
||||
|
||||
@staticmethod
|
||||
def factory(cursor: Cursor, row: Tuple[Any, ...]) -> Dict[str, Any]:
|
||||
|
64
src/ahriman/core/lazy_logging.py
Normal file
64
src/ahriman/core/lazy_logging.py
Normal file
@ -0,0 +1,64 @@
|
||||
#
|
||||
# Copyright (c) 2021-2022 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/>.
|
||||
#
|
||||
import logging
|
||||
|
||||
from typing import Any
|
||||
|
||||
|
||||
class LazyLogging:
|
||||
"""
|
||||
wrapper for the logger library inspired by scala lazy logging module
|
||||
|
||||
Attributes:
|
||||
logger(logging.Logger): class logger instance
|
||||
"""
|
||||
|
||||
logger: logging.Logger
|
||||
|
||||
def __getattr__(self, item: str) -> Any:
|
||||
"""
|
||||
logger extractor
|
||||
|
||||
Args:
|
||||
item(str) property name:
|
||||
|
||||
Returns:
|
||||
Any: attribute by its name
|
||||
|
||||
Raises:
|
||||
AttributeError: in case if no such attribute found
|
||||
"""
|
||||
if item == "logger":
|
||||
logger = logging.getLogger(self.logger_name)
|
||||
setattr(self, item, logger)
|
||||
return logger
|
||||
raise AttributeError(f"'{self.__class__.__qualname__}' object has no attribute '{item}'")
|
||||
|
||||
@property
|
||||
def logger_name(self) -> str:
|
||||
"""
|
||||
extract logger name for the class
|
||||
|
||||
Returns:
|
||||
str: logger name as combination of module name and class name
|
||||
"""
|
||||
clazz = self.__class__
|
||||
prefix = "" if clazz.__module__ is None else f"{clazz.__module__}."
|
||||
return f"{prefix}{self.__class__.__qualname__}"
|
@ -19,25 +19,23 @@
|
||||
#
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
|
||||
from typing import Iterable, Type
|
||||
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.exceptions import ReportFailed
|
||||
from ahriman.core.lazy_logging import LazyLogging
|
||||
from ahriman.models.package import Package
|
||||
from ahriman.models.report_settings import ReportSettings
|
||||
from ahriman.models.result import Result
|
||||
|
||||
|
||||
class Report:
|
||||
class Report(LazyLogging):
|
||||
"""
|
||||
base report generator
|
||||
|
||||
Attributes:
|
||||
architecture(str): repository architecture
|
||||
configuration(Configuration): configuration instance
|
||||
logger(logging.Logger): class logger
|
||||
|
||||
Examples:
|
||||
``Report`` classes provide several method in order to operate with the report generation and additional class
|
||||
@ -67,7 +65,6 @@ class Report:
|
||||
architecture(str): repository architecture
|
||||
configuration(Configuration): configuration instance
|
||||
"""
|
||||
self.logger = logging.getLogger("root")
|
||||
self.architecture = architecture
|
||||
self.configuration = configuration
|
||||
|
||||
|
@ -17,20 +17,19 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
import logging
|
||||
|
||||
from ahriman.core.alpm.pacman import Pacman
|
||||
from ahriman.core.alpm.repo import Repo
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.database import SQLite
|
||||
from ahriman.core.exceptions import UnsafeRun
|
||||
from ahriman.core.lazy_logging import LazyLogging
|
||||
from ahriman.core.sign.gpg import GPG
|
||||
from ahriman.core.status.client import Client
|
||||
from ahriman.core.triggers import TriggerLoader
|
||||
from ahriman.core.util import check_user
|
||||
|
||||
|
||||
class RepositoryProperties:
|
||||
class RepositoryProperties(LazyLogging):
|
||||
"""
|
||||
repository internal objects holder
|
||||
|
||||
@ -39,7 +38,6 @@ class RepositoryProperties:
|
||||
configuration(Configuration): configuration instance
|
||||
database(SQLite): database instance
|
||||
ignore_list(List[str]): package bases which will be ignored during auto updates
|
||||
logger(logging.Logger): class logger
|
||||
name(str): repository name
|
||||
pacman(Pacman): alpm wrapper instance
|
||||
paths(RepositoryPaths): repository paths instance
|
||||
@ -61,7 +59,6 @@ class RepositoryProperties:
|
||||
no_report(bool): force disable reporting
|
||||
unsafe(bool): if set no user check will be performed before path creation
|
||||
"""
|
||||
self.logger = logging.getLogger("root")
|
||||
self.architecture = architecture
|
||||
self.configuration = configuration
|
||||
self.database = database
|
||||
|
@ -17,7 +17,6 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
import logging
|
||||
import requests
|
||||
|
||||
from pathlib import Path
|
||||
@ -25,11 +24,12 @@ from typing import List, Optional, Set, Tuple
|
||||
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.exceptions import BuildFailed
|
||||
from ahriman.core.lazy_logging import LazyLogging
|
||||
from ahriman.core.util import check_output, exception_response_text
|
||||
from ahriman.models.sign_settings import SignSettings
|
||||
|
||||
|
||||
class GPG:
|
||||
class GPG(LazyLogging):
|
||||
"""
|
||||
gnupg wrapper
|
||||
|
||||
@ -37,7 +37,6 @@ class GPG:
|
||||
architecture(str): repository architecture
|
||||
configuration(Configuration): configuration instance
|
||||
default_key(Optional[str]): default PGP key ID to use
|
||||
logger(logging.Logger): class logger
|
||||
targets(Set[SignSettings]): list of targets to sign (repository, package etc)
|
||||
"""
|
||||
|
||||
@ -51,7 +50,6 @@ class GPG:
|
||||
architecture(str): repository architecture
|
||||
configuration(Configuration): configuration instance
|
||||
"""
|
||||
self.logger = logging.getLogger("build")
|
||||
self.architecture = architecture
|
||||
self.configuration = configuration
|
||||
self.targets, self.default_key = self.sign_options(configuration)
|
||||
|
@ -20,7 +20,6 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import logging
|
||||
import uuid
|
||||
|
||||
from multiprocessing import Process, Queue
|
||||
@ -28,10 +27,11 @@ from threading import Lock, Thread
|
||||
from typing import Callable, Dict, Iterable, Tuple
|
||||
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.lazy_logging import LazyLogging
|
||||
from ahriman.models.package_source import PackageSource
|
||||
|
||||
|
||||
class Spawn(Thread):
|
||||
class Spawn(Thread, LazyLogging):
|
||||
"""
|
||||
helper to spawn external ahriman process
|
||||
MUST NOT be used directly, the only one usage allowed is to spawn process from web services
|
||||
@ -40,7 +40,6 @@ class Spawn(Thread):
|
||||
active(Dict[str, Process]): map of active child processes required to avoid zombies
|
||||
architecture(str): repository architecture
|
||||
configuration(Configuration): configuration instance
|
||||
logger(logging.Logger): spawner logger
|
||||
queue(Queue[Tuple[str, bool]]): multiprocessing queue to read updates from processes
|
||||
"""
|
||||
|
||||
@ -57,7 +56,6 @@ class Spawn(Thread):
|
||||
self.architecture = architecture
|
||||
self.args_parser = args_parser
|
||||
self.configuration = configuration
|
||||
self.logger = logging.getLogger("http")
|
||||
|
||||
self.lock = Lock()
|
||||
self.active: Dict[str, Process] = {}
|
||||
|
@ -17,19 +17,18 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
import logging
|
||||
|
||||
from typing import Dict, List, Optional, Tuple
|
||||
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.database import SQLite
|
||||
from ahriman.core.exceptions import UnknownPackage
|
||||
from ahriman.core.lazy_logging import LazyLogging
|
||||
from ahriman.core.repository import Repository
|
||||
from ahriman.models.build_status import BuildStatus, BuildStatusEnum
|
||||
from ahriman.models.package import Package
|
||||
|
||||
|
||||
class Watcher:
|
||||
class Watcher(LazyLogging):
|
||||
"""
|
||||
package status watcher
|
||||
|
||||
@ -38,7 +37,6 @@ class Watcher:
|
||||
database(SQLite): database instance
|
||||
known(Dict[str, Tuple[Package, BuildStatus]]): list of known packages. For the most cases ``packages`` should
|
||||
be used instead
|
||||
logger(logging.Logger): class logger
|
||||
repository(Repository): repository object
|
||||
status(BuildStatus): daemon status
|
||||
"""
|
||||
@ -52,8 +50,6 @@ class Watcher:
|
||||
configuration(Configuration): configuration instance
|
||||
database(SQLite): database instance
|
||||
"""
|
||||
self.logger = logging.getLogger("http")
|
||||
|
||||
self.architecture = architecture
|
||||
self.database = database
|
||||
self.repository = Repository(architecture, configuration, database, no_report=True, unsafe=False)
|
||||
|
@ -17,12 +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/>.
|
||||
#
|
||||
import logging
|
||||
import requests
|
||||
|
||||
from typing import List, Optional, Tuple
|
||||
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.lazy_logging import LazyLogging
|
||||
from ahriman.core.status.client import Client
|
||||
from ahriman.core.util import exception_response_text
|
||||
from ahriman.models.build_status import BuildStatusEnum, BuildStatus
|
||||
@ -31,13 +31,12 @@ from ahriman.models.package import Package
|
||||
from ahriman.models.user import User
|
||||
|
||||
|
||||
class WebClient(Client):
|
||||
class WebClient(Client, LazyLogging):
|
||||
"""
|
||||
build status reporter web client
|
||||
|
||||
Attributes:
|
||||
address(str): address of the web service
|
||||
logger(logging.Logger): class logger
|
||||
user(Optional[User]): web service user descriptor
|
||||
"""
|
||||
|
||||
@ -48,7 +47,6 @@ class WebClient(Client):
|
||||
Args:
|
||||
configuration(Configuration): configuration instance
|
||||
"""
|
||||
self.logger = logging.getLogger("http")
|
||||
self.address = self.parse_address(configuration)
|
||||
self.user = User.from_option(
|
||||
configuration.get("web", "username", fallback=None),
|
||||
|
@ -17,23 +17,21 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
import logging
|
||||
|
||||
from typing import Iterable
|
||||
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.lazy_logging import LazyLogging
|
||||
from ahriman.models.package import Package
|
||||
from ahriman.models.result import Result
|
||||
|
||||
|
||||
class Trigger:
|
||||
class Trigger(LazyLogging):
|
||||
"""
|
||||
trigger base class
|
||||
|
||||
Attributes:
|
||||
architecture(str): repository architecture
|
||||
configuration(Configuration): configuration instance
|
||||
logger(logging.Logger): application logger
|
||||
|
||||
Examples:
|
||||
This class must be used in order to create own extension. Basically idea is the following::
|
||||
@ -61,7 +59,6 @@ class Trigger:
|
||||
architecture(str): repository architecture
|
||||
configuration(Configuration): configuration instance
|
||||
"""
|
||||
self.logger = logging.getLogger("root")
|
||||
self.architecture = architecture
|
||||
self.configuration = configuration
|
||||
|
||||
|
@ -18,7 +18,6 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
import importlib
|
||||
import logging
|
||||
import os
|
||||
|
||||
from pathlib import Path
|
||||
@ -27,19 +26,19 @@ from typing import Iterable
|
||||
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.exceptions import InvalidExtension
|
||||
from ahriman.core.lazy_logging import LazyLogging
|
||||
from ahriman.core.triggers import Trigger
|
||||
from ahriman.models.package import Package
|
||||
from ahriman.models.result import Result
|
||||
|
||||
|
||||
class TriggerLoader:
|
||||
class TriggerLoader(LazyLogging):
|
||||
"""
|
||||
trigger loader class
|
||||
|
||||
Attributes:
|
||||
architecture(str): repository architecture
|
||||
configuration(Configuration): configuration instance
|
||||
logger(logging.Logger): application logger
|
||||
triggers(List[Trigger]): list of loaded triggers according to the configuration
|
||||
|
||||
Examples:
|
||||
@ -66,7 +65,6 @@ class TriggerLoader:
|
||||
architecture(str): repository architecture
|
||||
configuration(Configuration): configuration instance
|
||||
"""
|
||||
self.logger = logging.getLogger("root")
|
||||
self.architecture = architecture
|
||||
self.configuration = configuration
|
||||
|
||||
|
@ -19,25 +19,23 @@
|
||||
#
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
|
||||
from pathlib import Path
|
||||
from typing import Iterable, Type
|
||||
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.exceptions import SyncFailed
|
||||
from ahriman.core.lazy_logging import LazyLogging
|
||||
from ahriman.models.package import Package
|
||||
from ahriman.models.upload_settings import UploadSettings
|
||||
|
||||
|
||||
class Upload:
|
||||
class Upload(LazyLogging):
|
||||
"""
|
||||
base remote sync class
|
||||
|
||||
Attributes:
|
||||
architecture(str): repository architecture
|
||||
configuration(Configuration): configuration instance
|
||||
logger(logging.Logger): application logger
|
||||
|
||||
Examples:
|
||||
These classes provide the way to upload packages to remote sources as it is described in their implementations.
|
||||
@ -66,7 +64,6 @@ class Upload:
|
||||
architecture(str): repository architecture
|
||||
configuration(Configuration): configuration instance
|
||||
"""
|
||||
self.logger = logging.getLogger("root")
|
||||
self.architecture = architecture
|
||||
self.configuration = configuration
|
||||
|
||||
|
@ -20,14 +20,13 @@
|
||||
import datetime
|
||||
import io
|
||||
import os
|
||||
from enum import Enum
|
||||
|
||||
import requests
|
||||
import shutil
|
||||
import subprocess
|
||||
import tempfile
|
||||
|
||||
from contextlib import contextmanager
|
||||
from enum import Enum
|
||||
from logging import Logger
|
||||
from pathlib import Path
|
||||
from typing import Any, Dict, Generator, IO, Iterable, List, Optional, Type, Union
|
||||
|
@ -20,7 +20,6 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import copy
|
||||
import logging
|
||||
|
||||
from dataclasses import asdict, dataclass
|
||||
from pathlib import Path
|
||||
@ -31,6 +30,7 @@ from typing import Any, Dict, Iterable, List, Optional, Set, Type
|
||||
from ahriman.core.alpm.pacman import Pacman
|
||||
from ahriman.core.alpm.remote import AUR, Official, OfficialSyncdb
|
||||
from ahriman.core.exceptions import InvalidPackageInfo
|
||||
from ahriman.core.lazy_logging import LazyLogging
|
||||
from ahriman.core.util import check_output, full_version
|
||||
from ahriman.models.package_description import PackageDescription
|
||||
from ahriman.models.package_source import PackageSource
|
||||
@ -39,7 +39,7 @@ from ahriman.models.repository_paths import RepositoryPaths
|
||||
|
||||
|
||||
@dataclass
|
||||
class Package:
|
||||
class Package(LazyLogging):
|
||||
"""
|
||||
package properties representation
|
||||
|
||||
@ -281,23 +281,22 @@ class Package:
|
||||
|
||||
from ahriman.core.build_tools.sources import Sources
|
||||
|
||||
logger = logging.getLogger("build")
|
||||
Sources.load(paths.cache_for(self.base), self, None, paths)
|
||||
|
||||
try:
|
||||
# update pkgver first
|
||||
Package._check_output("makepkg", "--nodeps", "--nobuild",
|
||||
exception=None, cwd=paths.cache_for(self.base), logger=logger)
|
||||
exception=None, cwd=paths.cache_for(self.base), logger=self.logger)
|
||||
# generate new .SRCINFO and put it to parser
|
||||
srcinfo_source = Package._check_output("makepkg", "--printsrcinfo",
|
||||
exception=None, cwd=paths.cache_for(self.base), logger=logger)
|
||||
exception=None, cwd=paths.cache_for(self.base), logger=self.logger)
|
||||
srcinfo, errors = parse_srcinfo(srcinfo_source)
|
||||
if errors:
|
||||
raise InvalidPackageInfo(errors)
|
||||
|
||||
return full_version(srcinfo.get("epoch"), srcinfo["pkgver"], srcinfo["pkgrel"])
|
||||
except Exception:
|
||||
logger.exception("cannot determine version of VCS package, make sure that you have VCS tools installed")
|
||||
self.logger.exception("cannot determine version of VCS package, make sure that VCS tools are installed")
|
||||
|
||||
return self.version
|
||||
|
||||
|
@ -94,7 +94,7 @@ def setup_service(architecture: str, configuration: Configuration, spawner: Spaw
|
||||
Returns:
|
||||
web.Application: web application instance
|
||||
"""
|
||||
application = web.Application(logger=logging.getLogger("http"))
|
||||
application = web.Application(logger=logging.getLogger(__name__))
|
||||
application.on_shutdown.append(on_shutdown)
|
||||
application.on_startup.append(on_startup)
|
||||
|
||||
|
14
tests/ahriman/core/build_tools/conftest.py
Normal file
14
tests/ahriman/core/build_tools/conftest.py
Normal file
@ -0,0 +1,14 @@
|
||||
import pytest
|
||||
|
||||
from ahriman.core.build_tools.sources import Sources
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def sources() -> Sources:
|
||||
"""
|
||||
sources fixture
|
||||
|
||||
Returns:
|
||||
Sources: sources instance
|
||||
"""
|
||||
return Sources()
|
@ -10,64 +10,6 @@ from ahriman.models.remote_source import RemoteSource
|
||||
from ahriman.models.repository_paths import RepositoryPaths
|
||||
|
||||
|
||||
def test_add(mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must add files to git
|
||||
"""
|
||||
glob_mock = mocker.patch("pathlib.Path.glob", return_value=[Path("local/1"), Path("local/2")])
|
||||
check_output_mock = mocker.patch("ahriman.core.build_tools.sources.Sources._check_output")
|
||||
|
||||
local = Path("local")
|
||||
Sources._add(local, "pattern1", "pattern2")
|
||||
glob_mock.assert_has_calls([mock.call("pattern1"), mock.call("pattern2")])
|
||||
check_output_mock.assert_called_once_with(
|
||||
"git", "add", "--intent-to-add", "1", "2", "1", "2",
|
||||
exception=None, cwd=local, logger=pytest.helpers.anyvar(int))
|
||||
|
||||
|
||||
def test_add_skip(mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must skip addition of files to index if no fiels found
|
||||
"""
|
||||
mocker.patch("pathlib.Path.glob", return_value=[])
|
||||
check_output_mock = mocker.patch("ahriman.core.build_tools.sources.Sources._check_output")
|
||||
|
||||
Sources._add(Path("local"), "pattern1")
|
||||
check_output_mock.assert_not_called()
|
||||
|
||||
|
||||
def test_diff(mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must calculate diff
|
||||
"""
|
||||
check_output_mock = mocker.patch("ahriman.core.build_tools.sources.Sources._check_output")
|
||||
|
||||
local = Path("local")
|
||||
assert Sources._diff(local)
|
||||
check_output_mock.assert_called_once_with(
|
||||
"git", "diff", exception=None, cwd=local, logger=pytest.helpers.anyvar(int))
|
||||
|
||||
|
||||
def test_move(mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must move content between directories
|
||||
"""
|
||||
mocker.patch("ahriman.core.build_tools.sources.walk", return_value=[Path("/source/path")])
|
||||
move_mock = mocker.patch("shutil.move")
|
||||
|
||||
Sources._move(Path("/source"), Path("/destination"))
|
||||
move_mock.assert_called_once_with(Path("/source/path"), Path("/destination/path"))
|
||||
|
||||
|
||||
def test_move_same(mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must not do anything in case if directories are the same
|
||||
"""
|
||||
walk_mock = mocker.patch("ahriman.core.build_tools.sources.walk")
|
||||
Sources._move(Path("/same"), Path("/same"))
|
||||
walk_mock.assert_not_called()
|
||||
|
||||
|
||||
def test_fetch_empty(remote_source: RemoteSource, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must do nothing in case if no branches available
|
||||
@ -87,7 +29,7 @@ def test_fetch_existing(remote_source: RemoteSource, mocker: MockerFixture) -> N
|
||||
mocker.patch("pathlib.Path.is_dir", return_value=True)
|
||||
mocker.patch("ahriman.core.build_tools.sources.Sources.has_remotes", return_value=True)
|
||||
check_output_mock = mocker.patch("ahriman.core.build_tools.sources.Sources._check_output")
|
||||
move_mock = mocker.patch("ahriman.core.build_tools.sources.Sources._move")
|
||||
move_mock = mocker.patch("ahriman.core.build_tools.sources.Sources.move")
|
||||
|
||||
local = Path("local")
|
||||
Sources.fetch(local, remote_source)
|
||||
@ -108,7 +50,7 @@ def test_fetch_new(remote_source: RemoteSource, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
mocker.patch("pathlib.Path.is_dir", return_value=False)
|
||||
check_output_mock = mocker.patch("ahriman.core.build_tools.sources.Sources._check_output")
|
||||
move_mock = mocker.patch("ahriman.core.build_tools.sources.Sources._move")
|
||||
move_mock = mocker.patch("ahriman.core.build_tools.sources.Sources.move")
|
||||
|
||||
local = Path("local")
|
||||
Sources.fetch(local, remote_source)
|
||||
@ -129,7 +71,7 @@ def test_fetch_new_without_remote(mocker: MockerFixture) -> None:
|
||||
"""
|
||||
mocker.patch("pathlib.Path.is_dir", return_value=False)
|
||||
check_output_mock = mocker.patch("ahriman.core.build_tools.sources.Sources._check_output")
|
||||
move_mock = mocker.patch("ahriman.core.build_tools.sources.Sources._move")
|
||||
move_mock = mocker.patch("ahriman.core.build_tools.sources.Sources.move")
|
||||
|
||||
local = Path("local")
|
||||
Sources.fetch(local, None)
|
||||
@ -147,7 +89,7 @@ def test_fetch_relative(remote_source: RemoteSource, mocker: MockerFixture) -> N
|
||||
must process move correctly on relative directory
|
||||
"""
|
||||
mocker.patch("ahriman.core.build_tools.sources.Sources._check_output")
|
||||
move_mock = mocker.patch("ahriman.core.build_tools.sources.Sources._move")
|
||||
move_mock = mocker.patch("ahriman.core.build_tools.sources.Sources.move")
|
||||
|
||||
Sources.fetch(Path("path"), remote_source)
|
||||
move_mock.assert_called_once_with(Path("path").resolve(), Path("path"))
|
||||
@ -222,26 +164,12 @@ def test_load_with_cache(package_ahriman: Package, repository_paths: RepositoryP
|
||||
copytree_mock.assert_called_once() # we do not check full command here, sorry
|
||||
|
||||
|
||||
def test_patch_apply(mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must apply patches if any
|
||||
"""
|
||||
check_output_mock = mocker.patch("ahriman.core.build_tools.sources.Sources._check_output")
|
||||
|
||||
local = Path("local")
|
||||
Sources.patch_apply(local, "patches")
|
||||
check_output_mock.assert_called_once_with(
|
||||
"git", "apply", "--ignore-space-change", "--ignore-whitespace",
|
||||
exception=None, cwd=local, input_data="patches", logger=pytest.helpers.anyvar(int)
|
||||
)
|
||||
|
||||
|
||||
def test_patch_create(mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must create patch set for the package
|
||||
"""
|
||||
add_mock = mocker.patch("ahriman.core.build_tools.sources.Sources._add")
|
||||
diff_mock = mocker.patch("ahriman.core.build_tools.sources.Sources._diff")
|
||||
add_mock = mocker.patch("ahriman.core.build_tools.sources.Sources.add")
|
||||
diff_mock = mocker.patch("ahriman.core.build_tools.sources.Sources.diff")
|
||||
|
||||
Sources.patch_create(Path("local"), "glob")
|
||||
add_mock.assert_called_once_with(Path("local"), "glob")
|
||||
@ -252,6 +180,78 @@ def test_patch_create_with_newline(mocker: MockerFixture) -> None:
|
||||
"""
|
||||
created patch must have new line at the end
|
||||
"""
|
||||
mocker.patch("ahriman.core.build_tools.sources.Sources._add")
|
||||
mocker.patch("ahriman.core.build_tools.sources.Sources._diff", return_value="diff")
|
||||
mocker.patch("ahriman.core.build_tools.sources.Sources.add")
|
||||
mocker.patch("ahriman.core.build_tools.sources.Sources.diff", return_value="diff")
|
||||
assert Sources.patch_create(Path("local"), "glob").endswith("\n")
|
||||
|
||||
|
||||
def test_add(sources: Sources, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must add files to git
|
||||
"""
|
||||
glob_mock = mocker.patch("pathlib.Path.glob", return_value=[Path("local/1"), Path("local/2")])
|
||||
check_output_mock = mocker.patch("ahriman.core.build_tools.sources.Sources._check_output")
|
||||
|
||||
local = Path("local")
|
||||
sources.add(local, "pattern1", "pattern2")
|
||||
glob_mock.assert_has_calls([mock.call("pattern1"), mock.call("pattern2")])
|
||||
check_output_mock.assert_called_once_with(
|
||||
"git", "add", "--intent-to-add", "1", "2", "1", "2",
|
||||
exception=None, cwd=local, logger=pytest.helpers.anyvar(int))
|
||||
|
||||
|
||||
def test_add_skip(sources: Sources, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must skip addition of files to index if no fiels found
|
||||
"""
|
||||
mocker.patch("pathlib.Path.glob", return_value=[])
|
||||
check_output_mock = mocker.patch("ahriman.core.build_tools.sources.Sources._check_output")
|
||||
|
||||
sources.add(Path("local"), "pattern1")
|
||||
check_output_mock.assert_not_called()
|
||||
|
||||
|
||||
def test_diff(sources: Sources, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must calculate diff
|
||||
"""
|
||||
check_output_mock = mocker.patch("ahriman.core.build_tools.sources.Sources._check_output")
|
||||
|
||||
local = Path("local")
|
||||
assert sources.diff(local)
|
||||
check_output_mock.assert_called_once_with(
|
||||
"git", "diff", exception=None, cwd=local, logger=pytest.helpers.anyvar(int))
|
||||
|
||||
|
||||
def test_move(sources: Sources, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must move content between directories
|
||||
"""
|
||||
mocker.patch("ahriman.core.build_tools.sources.walk", return_value=[Path("/source/path")])
|
||||
move_mock = mocker.patch("shutil.move")
|
||||
|
||||
sources.move(Path("/source"), Path("/destination"))
|
||||
move_mock.assert_called_once_with(Path("/source/path"), Path("/destination/path"))
|
||||
|
||||
|
||||
def test_move_same(sources: Sources, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must not do anything in case if directories are the same
|
||||
"""
|
||||
walk_mock = mocker.patch("ahriman.core.build_tools.sources.walk")
|
||||
sources.move(Path("/same"), Path("/same"))
|
||||
walk_mock.assert_not_called()
|
||||
|
||||
|
||||
def test_patch_apply(sources: Sources, mocker: MockerFixture) -> None:
|
||||
"""
|
||||
must apply patches if any
|
||||
"""
|
||||
check_output_mock = mocker.patch("ahriman.core.build_tools.sources.Sources._check_output")
|
||||
|
||||
local = Path("local")
|
||||
sources.patch_apply(local, "patches")
|
||||
check_output_mock.assert_called_once_with(
|
||||
"git", "apply", "--ignore-space-change", "--ignore-whitespace",
|
||||
exception=None, cwd=local, input_data="patches", logger=pytest.helpers.anyvar(int)
|
||||
)
|
||||
|
28
tests/ahriman/core/test_lazy_logging.py
Normal file
28
tests/ahriman/core/test_lazy_logging.py
Normal file
@ -0,0 +1,28 @@
|
||||
import pytest
|
||||
|
||||
from ahriman.core.alpm.repo import Repo
|
||||
from ahriman.core.database import SQLite
|
||||
|
||||
|
||||
def test_logger(database: SQLite) -> None:
|
||||
"""
|
||||
must set logger attribute
|
||||
"""
|
||||
assert database.logger
|
||||
assert database.logger.name == "ahriman.core.database.sqlite.SQLite"
|
||||
|
||||
|
||||
def test_logger_attribute_error(database: SQLite) -> None:
|
||||
"""
|
||||
must raise AttributeError in case if no attribute found
|
||||
"""
|
||||
with pytest.raises(AttributeError):
|
||||
database.loggerrrr
|
||||
|
||||
|
||||
def test_logger_name(database: SQLite, repo: Repo) -> None:
|
||||
"""
|
||||
must correctly generate logger name
|
||||
"""
|
||||
assert database.logger_name == "ahriman.core.database.sqlite.SQLite"
|
||||
assert repo.logger_name == "ahriman.core.alpm.repo.Repo"
|
Loading…
Reference in New Issue
Block a user