mirror of
https://github.com/arcan1s/ahriman.git
synced 2025-04-29 01:37:17 +00:00
set package context in main functions
This commit is contained in:
parent
e22e57bf08
commit
88c9b29e74
@ -17,9 +17,10 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
|
import contextlib
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from typing import Any
|
from typing import Any, Generator
|
||||||
|
|
||||||
|
|
||||||
class LazyLogging:
|
class LazyLogging:
|
||||||
@ -63,14 +64,15 @@ class LazyLogging:
|
|||||||
prefix = "" if clazz.__module__ is None else f"{clazz.__module__}."
|
prefix = "" if clazz.__module__ is None else f"{clazz.__module__}."
|
||||||
return f"{prefix}{clazz.__qualname__}"
|
return f"{prefix}{clazz.__qualname__}"
|
||||||
|
|
||||||
def package_logger_reset(self) -> None:
|
@staticmethod
|
||||||
|
def _package_logger_reset() -> None:
|
||||||
"""
|
"""
|
||||||
reset package logger to empty one
|
reset package logger to empty one
|
||||||
"""
|
"""
|
||||||
self.logger.debug("reset package logging")
|
|
||||||
logging.setLogRecordFactory(logging.LogRecord)
|
logging.setLogRecordFactory(logging.LogRecord)
|
||||||
|
|
||||||
def package_logger_set(self, package_base: str) -> None:
|
@staticmethod
|
||||||
|
def _package_logger_set(package_base: str) -> None:
|
||||||
"""
|
"""
|
||||||
set package base as extra info to the logger
|
set package base as extra info to the logger
|
||||||
|
|
||||||
@ -85,4 +87,23 @@ class LazyLogging:
|
|||||||
return record
|
return record
|
||||||
|
|
||||||
logging.setLogRecordFactory(package_record_factory)
|
logging.setLogRecordFactory(package_record_factory)
|
||||||
self.logger.debug("start package %s logging", package_base)
|
|
||||||
|
@contextlib.contextmanager
|
||||||
|
def in_package_context(self, package_base: str) -> Generator[None, None, None]:
|
||||||
|
"""
|
||||||
|
execute function while setting package context
|
||||||
|
|
||||||
|
Args:
|
||||||
|
package_base(str): package base to set context in
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
This function is designed to be called as context manager with ``package_base`` argument, e.g.:
|
||||||
|
|
||||||
|
>>> with self.in_package_context(package.base):
|
||||||
|
>>> build_package(package)
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
self._package_logger_set(package_base)
|
||||||
|
yield
|
||||||
|
finally:
|
||||||
|
self._package_logger_reset()
|
||||||
|
@ -84,7 +84,8 @@ class Executor(Cleaner):
|
|||||||
|
|
||||||
result = Result()
|
result = Result()
|
||||||
for single in updates:
|
for single in updates:
|
||||||
with TemporaryDirectory(ignore_cleanup_errors=True) as dir_name, (build_dir := Path(dir_name)):
|
with self.in_package_context(single.base), \
|
||||||
|
TemporaryDirectory(ignore_cleanup_errors=True) as dir_name, (build_dir := Path(dir_name)):
|
||||||
try:
|
try:
|
||||||
build_single(single, build_dir)
|
build_single(single, build_dir)
|
||||||
result.add_success(single)
|
result.add_success(single)
|
||||||
@ -110,6 +111,7 @@ class Executor(Cleaner):
|
|||||||
self.paths.tree_clear(package_base) # remove all internal files
|
self.paths.tree_clear(package_base) # remove all internal files
|
||||||
self.database.build_queue_clear(package_base)
|
self.database.build_queue_clear(package_base)
|
||||||
self.database.patches_remove(package_base, [])
|
self.database.patches_remove(package_base, [])
|
||||||
|
self.database.logs_remove(package_base, None)
|
||||||
self.reporter.remove(package_base) # we only update status page in case of base removal
|
self.reporter.remove(package_base) # we only update status page in case of base removal
|
||||||
except Exception:
|
except Exception:
|
||||||
self.logger.exception("could not remove base %s", package_base)
|
self.logger.exception("could not remove base %s", package_base)
|
||||||
@ -180,24 +182,25 @@ class Executor(Cleaner):
|
|||||||
|
|
||||||
result = Result()
|
result = Result()
|
||||||
for local in updates:
|
for local in updates:
|
||||||
try:
|
with self.in_package_context(local.base):
|
||||||
for description in local.packages.values():
|
try:
|
||||||
rename(description, local.base)
|
for description in local.packages.values():
|
||||||
update_single(description.filename, local.base)
|
rename(description, local.base)
|
||||||
self.reporter.set_success(local)
|
update_single(description.filename, local.base)
|
||||||
result.add_success(local)
|
self.reporter.set_success(local)
|
||||||
|
result.add_success(local)
|
||||||
|
|
||||||
current_package_archives = {
|
current_package_archives = {
|
||||||
package
|
package
|
||||||
for current in current_packages
|
for current in current_packages
|
||||||
if current.base == local.base
|
if current.base == local.base
|
||||||
for package in current.packages
|
for package in current.packages
|
||||||
}
|
}
|
||||||
removed_packages.extend(current_package_archives.difference(local.packages))
|
removed_packages.extend(current_package_archives.difference(local.packages))
|
||||||
except Exception:
|
except Exception:
|
||||||
self.reporter.set_failed(local.base)
|
self.reporter.set_failed(local.base)
|
||||||
result.add_failed(local)
|
result.add_failed(local)
|
||||||
self.logger.exception("could not process %s", local.base)
|
self.logger.exception("could not process %s", local.base)
|
||||||
self.clear_packages()
|
self.clear_packages()
|
||||||
|
|
||||||
self.process_remove(removed_packages)
|
self.process_remove(removed_packages)
|
||||||
|
@ -56,26 +56,26 @@ class UpdateHandler(Cleaner):
|
|||||||
result: List[Package] = []
|
result: List[Package] = []
|
||||||
|
|
||||||
for local in self.packages():
|
for local in self.packages():
|
||||||
if local.base in self.ignore_list:
|
with self.in_package_context(local.base):
|
||||||
continue
|
if local.base in self.ignore_list:
|
||||||
if local.is_vcs and not vcs:
|
continue
|
||||||
continue
|
if local.is_vcs and not vcs:
|
||||||
if filter_packages and local.base not in filter_packages:
|
continue
|
||||||
continue
|
if filter_packages and local.base not in filter_packages:
|
||||||
source = local.remote.source if local.remote is not None else None
|
continue
|
||||||
|
source = local.remote.source if local.remote is not None else None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if source == PackageSource.Repository:
|
if source == PackageSource.Repository:
|
||||||
remote = Package.from_official(local.base, self.pacman)
|
remote = Package.from_official(local.base, self.pacman)
|
||||||
else:
|
else:
|
||||||
remote = Package.from_aur(local.base, self.pacman)
|
remote = Package.from_aur(local.base, self.pacman)
|
||||||
if local.is_outdated(remote, self.paths):
|
if local.is_outdated(remote, self.paths):
|
||||||
self.reporter.set_pending(local.base)
|
self.reporter.set_pending(local.base)
|
||||||
result.append(remote)
|
result.append(remote)
|
||||||
except Exception:
|
except Exception:
|
||||||
self.reporter.set_failed(local.base)
|
self.reporter.set_failed(local.base)
|
||||||
self.logger.exception("could not load remote package %s", local.base)
|
self.logger.exception("could not load remote package %s", local.base)
|
||||||
continue
|
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
@ -90,19 +90,20 @@ class UpdateHandler(Cleaner):
|
|||||||
packages = {local.base: local for local in self.packages()}
|
packages = {local.base: local for local in self.packages()}
|
||||||
|
|
||||||
for cache_dir in self.paths.cache.iterdir():
|
for cache_dir in self.paths.cache.iterdir():
|
||||||
try:
|
with self.in_package_context(cache_dir.name):
|
||||||
Sources.fetch(cache_dir, remote=None)
|
try:
|
||||||
remote = Package.from_build(cache_dir)
|
Sources.fetch(cache_dir, remote=None)
|
||||||
|
remote = Package.from_build(cache_dir)
|
||||||
|
|
||||||
local = packages.get(remote.base)
|
local = packages.get(remote.base)
|
||||||
if local is None:
|
if local is None:
|
||||||
self.reporter.set_unknown(remote)
|
self.reporter.set_unknown(remote)
|
||||||
result.append(remote)
|
result.append(remote)
|
||||||
elif local.is_outdated(remote, self.paths):
|
elif local.is_outdated(remote, self.paths):
|
||||||
self.reporter.set_pending(local.base)
|
self.reporter.set_pending(local.base)
|
||||||
result.append(remote)
|
result.append(remote)
|
||||||
except Exception:
|
except Exception:
|
||||||
self.logger.exception("could not process package at %s", cache_dir)
|
self.logger.exception("could not process package at %s", cache_dir)
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
import logging
|
import logging
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
|
from pytest_mock import MockerFixture
|
||||||
|
|
||||||
from ahriman.core.alpm.repo import Repo
|
from ahriman.core.alpm.repo import Repo
|
||||||
from ahriman.core.database import SQLite
|
from ahriman.core.database import SQLite
|
||||||
|
from ahriman.models.package import Package
|
||||||
|
|
||||||
|
|
||||||
def test_logger(database: SQLite) -> None:
|
def test_logger(database: SQLite) -> None:
|
||||||
@ -35,11 +38,39 @@ def test_package_logger_set_reset(database: SQLite) -> None:
|
|||||||
"""
|
"""
|
||||||
package_base = "package base"
|
package_base = "package base"
|
||||||
|
|
||||||
database.package_logger_set(package_base)
|
database._package_logger_set(package_base)
|
||||||
record = logging.makeLogRecord({})
|
record = logging.makeLogRecord({})
|
||||||
assert record.package_base == package_base
|
assert record.package_base == package_base
|
||||||
|
|
||||||
database.package_logger_reset()
|
database._package_logger_reset()
|
||||||
record = logging.makeLogRecord({})
|
record = logging.makeLogRecord({})
|
||||||
with pytest.raises(AttributeError):
|
with pytest.raises(AttributeError):
|
||||||
record.package_base
|
record.package_base
|
||||||
|
|
||||||
|
|
||||||
|
def test_in_package_context(database: SQLite, package_ahriman: Package, mocker: MockerFixture) -> None:
|
||||||
|
"""
|
||||||
|
must set package log context
|
||||||
|
"""
|
||||||
|
set_mock = mocker.patch("ahriman.core.log.LazyLogging._package_logger_set")
|
||||||
|
reset_mock = mocker.patch("ahriman.core.log.LazyLogging._package_logger_reset")
|
||||||
|
|
||||||
|
with database.in_package_context(package_ahriman.base):
|
||||||
|
pass
|
||||||
|
|
||||||
|
set_mock.assert_called_once_with(package_ahriman.base)
|
||||||
|
reset_mock.assert_called_once_with()
|
||||||
|
|
||||||
|
|
||||||
|
def test_in_package_context_failed(database: SQLite, package_ahriman: Package, mocker: MockerFixture) -> None:
|
||||||
|
"""
|
||||||
|
must reset package context even if exception occurs
|
||||||
|
"""
|
||||||
|
mocker.patch("ahriman.core.log.LazyLogging._package_logger_set")
|
||||||
|
reset_mock = mocker.patch("ahriman.core.log.LazyLogging._package_logger_reset")
|
||||||
|
|
||||||
|
with pytest.raises(Exception):
|
||||||
|
with database.in_package_context(package_ahriman.base):
|
||||||
|
raise Exception()
|
||||||
|
|
||||||
|
reset_mock.assert_called_once_with()
|
||||||
|
@ -63,6 +63,7 @@ def test_process_remove_base(executor: Executor, package_ahriman: Package, mocke
|
|||||||
repo_remove_mock = mocker.patch("ahriman.core.alpm.repo.Repo.remove")
|
repo_remove_mock = mocker.patch("ahriman.core.alpm.repo.Repo.remove")
|
||||||
build_queue_mock = mocker.patch("ahriman.core.database.SQLite.build_queue_clear")
|
build_queue_mock = mocker.patch("ahriman.core.database.SQLite.build_queue_clear")
|
||||||
patches_mock = mocker.patch("ahriman.core.database.SQLite.patches_remove")
|
patches_mock = mocker.patch("ahriman.core.database.SQLite.patches_remove")
|
||||||
|
logs_mock = mocker.patch("ahriman.core.database.SQLite.logs_remove")
|
||||||
status_client_mock = mocker.patch("ahriman.core.status.client.Client.remove")
|
status_client_mock = mocker.patch("ahriman.core.status.client.Client.remove")
|
||||||
|
|
||||||
executor.process_remove([package_ahriman.base])
|
executor.process_remove([package_ahriman.base])
|
||||||
@ -73,6 +74,7 @@ def test_process_remove_base(executor: Executor, package_ahriman: Package, mocke
|
|||||||
tree_clear_mock.assert_called_once_with(package_ahriman.base)
|
tree_clear_mock.assert_called_once_with(package_ahriman.base)
|
||||||
build_queue_mock.assert_called_once_with(package_ahriman.base)
|
build_queue_mock.assert_called_once_with(package_ahriman.base)
|
||||||
patches_mock.assert_called_once_with(package_ahriman.base, [])
|
patches_mock.assert_called_once_with(package_ahriman.base, [])
|
||||||
|
logs_mock.assert_called_once_with(package_ahriman.base, None)
|
||||||
status_client_mock.assert_called_once_with(package_ahriman.base)
|
status_client_mock.assert_called_once_with(package_ahriman.base)
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
|
from pathlib import Path
|
||||||
from pytest_mock import MockerFixture
|
from pytest_mock import MockerFixture
|
||||||
|
|
||||||
from ahriman.core.repository.update_handler import UpdateHandler
|
from ahriman.core.repository.update_handler import UpdateHandler
|
||||||
@ -103,15 +104,15 @@ def test_updates_local(update_handler: UpdateHandler, package_ahriman: Package,
|
|||||||
must check for updates for locally stored packages
|
must check for updates for locally stored packages
|
||||||
"""
|
"""
|
||||||
mocker.patch("ahriman.core.repository.update_handler.UpdateHandler.packages", return_value=[package_ahriman])
|
mocker.patch("ahriman.core.repository.update_handler.UpdateHandler.packages", return_value=[package_ahriman])
|
||||||
mocker.patch("pathlib.Path.iterdir", return_value=[package_ahriman.base])
|
mocker.patch("pathlib.Path.iterdir", return_value=[Path(package_ahriman.base)])
|
||||||
mocker.patch("ahriman.models.package.Package.is_outdated", return_value=True)
|
mocker.patch("ahriman.models.package.Package.is_outdated", return_value=True)
|
||||||
fetch_mock = mocker.patch("ahriman.core.build_tools.sources.Sources.fetch")
|
fetch_mock = mocker.patch("ahriman.core.build_tools.sources.Sources.fetch")
|
||||||
package_load_mock = mocker.patch("ahriman.models.package.Package.from_build", return_value=package_ahriman)
|
package_load_mock = mocker.patch("ahriman.models.package.Package.from_build", return_value=package_ahriman)
|
||||||
status_client_mock = mocker.patch("ahriman.core.status.client.Client.set_pending")
|
status_client_mock = mocker.patch("ahriman.core.status.client.Client.set_pending")
|
||||||
|
|
||||||
assert update_handler.updates_local() == [package_ahriman]
|
assert update_handler.updates_local() == [package_ahriman]
|
||||||
fetch_mock.assert_called_once_with(package_ahriman.base, remote=None)
|
fetch_mock.assert_called_once_with(Path(package_ahriman.base), remote=None)
|
||||||
package_load_mock.assert_called_once_with(package_ahriman.base)
|
package_load_mock.assert_called_once_with(Path(package_ahriman.base))
|
||||||
status_client_mock.assert_called_once_with(package_ahriman.base)
|
status_client_mock.assert_called_once_with(package_ahriman.base)
|
||||||
|
|
||||||
|
|
||||||
@ -120,7 +121,7 @@ def test_updates_local_unknown(update_handler: UpdateHandler, package_ahriman: P
|
|||||||
must return unknown package as out-dated
|
must return unknown package as out-dated
|
||||||
"""
|
"""
|
||||||
mocker.patch("ahriman.core.repository.update_handler.UpdateHandler.packages", return_value=[])
|
mocker.patch("ahriman.core.repository.update_handler.UpdateHandler.packages", return_value=[])
|
||||||
mocker.patch("pathlib.Path.iterdir", return_value=[package_ahriman.base])
|
mocker.patch("pathlib.Path.iterdir", return_value=[Path(package_ahriman.base)])
|
||||||
mocker.patch("ahriman.models.package.Package.is_outdated", return_value=True)
|
mocker.patch("ahriman.models.package.Package.is_outdated", return_value=True)
|
||||||
mocker.patch("ahriman.core.build_tools.sources.Sources.fetch")
|
mocker.patch("ahriman.core.build_tools.sources.Sources.fetch")
|
||||||
mocker.patch("ahriman.models.package.Package.from_build", return_value=package_ahriman)
|
mocker.patch("ahriman.models.package.Package.from_build", return_value=package_ahriman)
|
||||||
@ -136,7 +137,7 @@ def test_updates_local_with_failures(update_handler: UpdateHandler, package_ahri
|
|||||||
must process local through the packages with failure
|
must process local through the packages with failure
|
||||||
"""
|
"""
|
||||||
mocker.patch("ahriman.core.repository.update_handler.UpdateHandler.packages")
|
mocker.patch("ahriman.core.repository.update_handler.UpdateHandler.packages")
|
||||||
mocker.patch("pathlib.Path.iterdir", return_value=[package_ahriman.base])
|
mocker.patch("pathlib.Path.iterdir", return_value=[Path(package_ahriman.base)])
|
||||||
mocker.patch("ahriman.core.build_tools.sources.Sources.fetch", side_effect=Exception())
|
mocker.patch("ahriman.core.build_tools.sources.Sources.fetch", side_effect=Exception())
|
||||||
|
|
||||||
assert not update_handler.updates_local()
|
assert not update_handler.updates_local()
|
||||||
|
Loading…
Reference in New Issue
Block a user