mirror of
https://github.com/arcan1s/ahriman.git
synced 2025-07-13 14:05:47 +00:00
PEP-585 complaint: remove type aliases (#93)
This commit is contained in:
@ -23,7 +23,7 @@ import sys
|
||||
import tempfile
|
||||
|
||||
from pathlib import Path
|
||||
from typing import List, TypeVar
|
||||
from typing import TypeVar
|
||||
|
||||
from ahriman import version
|
||||
from ahriman.application import handlers
|
||||
@ -35,7 +35,7 @@ from ahriman.models.sign_settings import SignSettings
|
||||
from ahriman.models.user_access import UserAccess
|
||||
|
||||
|
||||
__all__: List[str] = []
|
||||
__all__: list[str] = []
|
||||
|
||||
|
||||
# this workaround is for several things
|
||||
|
@ -17,7 +17,7 @@
|
||||
# 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 typing import Iterable, List, Set
|
||||
from collections.abc import Iterable
|
||||
|
||||
from ahriman.application.application.application_packages import ApplicationPackages
|
||||
from ahriman.application.application.application_repository import ApplicationRepository
|
||||
@ -50,14 +50,14 @@ class Application(ApplicationPackages, ApplicationRepository):
|
||||
be used instead.
|
||||
"""
|
||||
|
||||
def _known_packages(self) -> Set[str]:
|
||||
def _known_packages(self) -> set[str]:
|
||||
"""
|
||||
load packages from repository and pacman repositories
|
||||
|
||||
Returns:
|
||||
Set[str]: list of known packages
|
||||
set[str]: list of known packages
|
||||
"""
|
||||
known_packages: Set[str] = set()
|
||||
known_packages: set[str] = set()
|
||||
# local set
|
||||
for base in self.repository.packages():
|
||||
for package, properties in base.packages.items():
|
||||
@ -89,15 +89,15 @@ class Application(ApplicationPackages, ApplicationRepository):
|
||||
"""
|
||||
self.repository.triggers.on_stop()
|
||||
|
||||
def with_dependencies(self, packages: List[Package], *, process_dependencies: bool) -> List[Package]:
|
||||
def with_dependencies(self, packages: list[Package], *, process_dependencies: bool) -> list[Package]:
|
||||
"""
|
||||
add missing dependencies to list of packages
|
||||
|
||||
Args:
|
||||
packages(List[Package]): list of source packages of which dependencies have to be processed
|
||||
packages(list[Package]): list of source packages of which dependencies have to be processed
|
||||
process_dependencies(bool): if no set, dependencies will not be processed
|
||||
"""
|
||||
def missing_dependencies(source: Iterable[Package]) -> Set[str]:
|
||||
def missing_dependencies(source: Iterable[Package]) -> set[str]:
|
||||
# build initial list of dependencies
|
||||
result = set()
|
||||
for package in source:
|
||||
|
@ -20,8 +20,9 @@
|
||||
import requests
|
||||
import shutil
|
||||
|
||||
from collections.abc import Iterable
|
||||
from pathlib import Path
|
||||
from typing import Any, Iterable
|
||||
from typing import Any
|
||||
|
||||
from ahriman.application.application.application_properties import ApplicationProperties
|
||||
from ahriman.core.build_tools.sources import Sources
|
||||
|
@ -17,8 +17,8 @@
|
||||
# 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 collections.abc import Callable, Iterable
|
||||
from pathlib import Path
|
||||
from typing import Callable, Iterable, List
|
||||
|
||||
from ahriman.application.application.application_properties import ApplicationProperties
|
||||
from ahriman.core.build_tools.sources import Sources
|
||||
@ -89,19 +89,19 @@ class ApplicationRepository(ApplicationProperties):
|
||||
# process triggers
|
||||
self.on_result(Result())
|
||||
|
||||
def unknown(self) -> List[str]:
|
||||
def unknown(self) -> list[str]:
|
||||
"""
|
||||
get packages which were not found in AUR
|
||||
|
||||
Returns:
|
||||
List[str]: unknown package archive list
|
||||
list[str]: unknown package archive list
|
||||
"""
|
||||
def has_local(probe: Package) -> bool:
|
||||
cache_dir = self.repository.paths.cache_for(probe.base)
|
||||
return cache_dir.is_dir() and not Sources.has_remotes(cache_dir)
|
||||
|
||||
def unknown_aur(probe: Package) -> List[str]:
|
||||
packages: List[str] = []
|
||||
def unknown_aur(probe: Package) -> list[str]:
|
||||
packages: list[str] = []
|
||||
for single in probe.packages:
|
||||
try:
|
||||
_ = Package.from_aur(single, self.repository.pacman)
|
||||
@ -109,7 +109,7 @@ class ApplicationRepository(ApplicationProperties):
|
||||
packages.append(single)
|
||||
return packages
|
||||
|
||||
def unknown_local(probe: Package) -> List[str]:
|
||||
def unknown_local(probe: Package) -> list[str]:
|
||||
cache_dir = self.repository.paths.cache_for(probe.base)
|
||||
local = Package.from_build(cache_dir, self.architecture)
|
||||
packages = set(probe.packages.keys()).difference(local.packages.keys())
|
||||
@ -155,7 +155,7 @@ class ApplicationRepository(ApplicationProperties):
|
||||
return build_result
|
||||
|
||||
def updates(self, filter_packages: Iterable[str], *,
|
||||
aur: bool, local: bool, manual: bool, vcs: bool, log_fn: Callable[[str], None]) -> List[Package]:
|
||||
aur: bool, local: bool, manual: bool, vcs: bool, log_fn: Callable[[str], None]) -> list[Package]:
|
||||
"""
|
||||
get list of packages to run update process
|
||||
|
||||
@ -168,7 +168,7 @@ class ApplicationRepository(ApplicationProperties):
|
||||
log_fn(Callable[[str], None]): logger function to log updates
|
||||
|
||||
Returns:
|
||||
List[Package]: list of out-of-dated packages
|
||||
list[Package]: list of out-of-dated packages
|
||||
"""
|
||||
updates = {}
|
||||
|
||||
|
@ -19,8 +19,6 @@
|
||||
#
|
||||
import argparse
|
||||
|
||||
from typing import Type
|
||||
|
||||
from ahriman.application.application import Application
|
||||
from ahriman.application.handlers import Handler
|
||||
from ahriman.core.configuration import Configuration
|
||||
@ -32,7 +30,7 @@ class Add(Handler):
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
def run(cls: type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
|
@ -22,7 +22,6 @@ import pwd
|
||||
|
||||
from pathlib import Path
|
||||
from tarfile import TarFile
|
||||
from typing import Set, Type
|
||||
|
||||
from ahriman.application.handlers import Handler
|
||||
from ahriman.core.configuration import Configuration
|
||||
@ -37,7 +36,7 @@ class Backup(Handler):
|
||||
ALLOW_AUTO_ARCHITECTURE_RUN = False # it should be called only as "no-architecture"
|
||||
|
||||
@classmethod
|
||||
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
def run(cls: type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
@ -55,7 +54,7 @@ class Backup(Handler):
|
||||
archive.add(backup_path)
|
||||
|
||||
@staticmethod
|
||||
def get_paths(configuration: Configuration) -> Set[Path]:
|
||||
def get_paths(configuration: Configuration) -> set[Path]:
|
||||
"""
|
||||
extract paths to back up
|
||||
|
||||
@ -63,7 +62,7 @@ class Backup(Handler):
|
||||
configuration(Configuration): configuration instance
|
||||
|
||||
Returns:
|
||||
Set[Path]: map of the filesystem paths
|
||||
set[Path]: map of the filesystem paths
|
||||
"""
|
||||
paths = set(configuration.include.glob("*.ini"))
|
||||
|
||||
|
@ -19,8 +19,6 @@
|
||||
#
|
||||
import argparse
|
||||
|
||||
from typing import Type
|
||||
|
||||
from ahriman.application.application import Application
|
||||
from ahriman.application.handlers import Handler
|
||||
from ahriman.core.configuration import Configuration
|
||||
@ -32,7 +30,7 @@ class Clean(Handler):
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
def run(cls: type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
|
@ -20,8 +20,6 @@
|
||||
import argparse
|
||||
import threading
|
||||
|
||||
from typing import Type
|
||||
|
||||
from ahriman.application.handlers import Handler
|
||||
from ahriman.core.configuration import Configuration
|
||||
|
||||
@ -32,7 +30,7 @@ class Daemon(Handler):
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
def run(cls: type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
|
@ -19,8 +19,6 @@
|
||||
#
|
||||
import argparse
|
||||
|
||||
from typing import Type
|
||||
|
||||
from ahriman.application.handlers import Handler
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.formatters import ConfigurationPrinter
|
||||
@ -34,7 +32,7 @@ class Dump(Handler):
|
||||
ALLOW_AUTO_ARCHITECTURE_RUN = False
|
||||
|
||||
@classmethod
|
||||
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
def run(cls: type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
|
@ -23,7 +23,6 @@ import argparse
|
||||
import logging
|
||||
|
||||
from multiprocessing import Pool
|
||||
from typing import List, Type
|
||||
|
||||
from ahriman.application.lock import Lock
|
||||
from ahriman.core.configuration import Configuration
|
||||
@ -53,7 +52,7 @@ class Handler:
|
||||
ALLOW_MULTI_ARCHITECTURE_RUN = True
|
||||
|
||||
@classmethod
|
||||
def architectures_extract(cls: Type[Handler], args: argparse.Namespace) -> List[str]:
|
||||
def architectures_extract(cls: type[Handler], args: argparse.Namespace) -> list[str]:
|
||||
"""
|
||||
get known architectures
|
||||
|
||||
@ -61,7 +60,7 @@ class Handler:
|
||||
args(argparse.Namespace): command line args
|
||||
|
||||
Returns:
|
||||
List[str]: list of architectures for which tree is created
|
||||
list[str]: list of architectures for which tree is created
|
||||
|
||||
Raises:
|
||||
MissingArchitecture: if no architecture set and automatic detection is not allowed or failed
|
||||
@ -84,7 +83,7 @@ class Handler:
|
||||
return sorted(architectures)
|
||||
|
||||
@classmethod
|
||||
def call(cls: Type[Handler], args: argparse.Namespace, architecture: str) -> bool:
|
||||
def call(cls: type[Handler], args: argparse.Namespace, architecture: str) -> bool:
|
||||
"""
|
||||
additional function to wrap all calls for multiprocessing library
|
||||
|
||||
@ -109,7 +108,7 @@ class Handler:
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
def execute(cls: Type[Handler], args: argparse.Namespace) -> int:
|
||||
def execute(cls: type[Handler], args: argparse.Namespace) -> int:
|
||||
"""
|
||||
execute function for all aru
|
||||
|
||||
@ -138,7 +137,7 @@ class Handler:
|
||||
return 0 if all(result) else 1
|
||||
|
||||
@classmethod
|
||||
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
def run(cls: type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
|
@ -19,8 +19,6 @@
|
||||
#
|
||||
import argparse
|
||||
|
||||
from typing import Type
|
||||
|
||||
from ahriman.application.handlers import Handler
|
||||
from ahriman.core.configuration import Configuration
|
||||
|
||||
@ -33,7 +31,7 @@ class Help(Handler):
|
||||
ALLOW_AUTO_ARCHITECTURE_RUN = False # it should be called only as "no-architecture"
|
||||
|
||||
@classmethod
|
||||
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
def run(cls: type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
|
@ -19,8 +19,6 @@
|
||||
#
|
||||
import argparse
|
||||
|
||||
from typing import Type
|
||||
|
||||
from ahriman.application.application import Application
|
||||
from ahriman.application.handlers import Handler
|
||||
from ahriman.core.configuration import Configuration
|
||||
@ -34,7 +32,7 @@ class KeyImport(Handler):
|
||||
ALLOW_AUTO_ARCHITECTURE_RUN = False # it should be called only as "no-architecture"
|
||||
|
||||
@classmethod
|
||||
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
def run(cls: type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
|
@ -21,7 +21,6 @@ import argparse
|
||||
import sys
|
||||
|
||||
from pathlib import Path
|
||||
from typing import List, Optional, Tuple, Type
|
||||
|
||||
from ahriman.application.application import Application
|
||||
from ahriman.application.handlers import Handler
|
||||
@ -39,7 +38,7 @@ class Patch(Handler):
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
def run(cls: type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
@ -66,17 +65,17 @@ class Patch(Handler):
|
||||
Patch.patch_set_remove(application, args.package, args.variable)
|
||||
|
||||
@staticmethod
|
||||
def patch_create_from_diff(sources_dir: Path, architecture: str, track: List[str]) -> Tuple[str, PkgbuildPatch]:
|
||||
def patch_create_from_diff(sources_dir: Path, architecture: str, track: list[str]) -> tuple[str, PkgbuildPatch]:
|
||||
"""
|
||||
create PKGBUILD plain diff patches from sources directory
|
||||
|
||||
Args:
|
||||
sources_dir(Path): path to directory with the package sources
|
||||
architecture(str): repository architecture
|
||||
track(List[str]): track files which match the glob before creating the patch
|
||||
track(list[str]): track files which match the glob before creating the patch
|
||||
|
||||
Returns:
|
||||
Tuple[str, PkgbuildPatch]: package base and created PKGBUILD patch based on the diff from master HEAD
|
||||
tuple[str, PkgbuildPatch]: package base and created PKGBUILD patch based on the diff from master HEAD
|
||||
to current files
|
||||
"""
|
||||
package = Package.from_build(sources_dir, architecture)
|
||||
@ -84,13 +83,13 @@ class Patch(Handler):
|
||||
return package.base, PkgbuildPatch(None, patch)
|
||||
|
||||
@staticmethod
|
||||
def patch_create_from_function(variable: str, patch_path: Optional[Path]) -> PkgbuildPatch:
|
||||
def patch_create_from_function(variable: str, patch_path: Path | None) -> PkgbuildPatch:
|
||||
"""
|
||||
create single-function patch set for the package base
|
||||
|
||||
Args:
|
||||
variable(str): function or variable name inside PKGBUILD
|
||||
patch_path(Path): optional path to patch content. If not set, it will be read from stdin
|
||||
patch_path(Path | None): optional path to patch content. If not set, it will be read from stdin
|
||||
|
||||
Returns:
|
||||
PkgbuildPatch: created patch for the PKGBUILD function
|
||||
@ -116,15 +115,15 @@ class Patch(Handler):
|
||||
application.database.patches_insert(package_base, patch)
|
||||
|
||||
@staticmethod
|
||||
def patch_set_list(application: Application, package_base: Optional[str], variables: List[str],
|
||||
def patch_set_list(application: Application, package_base: str | None, variables: list[str],
|
||||
exit_code: bool) -> None:
|
||||
"""
|
||||
list patches available for the package base
|
||||
|
||||
Args:
|
||||
application(Application): application instance
|
||||
package_base(Optional[str]): package base
|
||||
variables(List[str]): extract patches only for specified PKGBUILD variables
|
||||
package_base(str | None): package base
|
||||
variables(list[str]): extract patches only for specified PKGBUILD variables
|
||||
exit_code(bool): exit with error on empty search result
|
||||
"""
|
||||
patches = application.database.patches_list(package_base, variables)
|
||||
@ -134,13 +133,13 @@ class Patch(Handler):
|
||||
PatchPrinter(base, patch).print(verbose=True, separator=" = ")
|
||||
|
||||
@staticmethod
|
||||
def patch_set_remove(application: Application, package_base: str, variables: List[str]) -> None:
|
||||
def patch_set_remove(application: Application, package_base: str, variables: list[str]) -> None:
|
||||
"""
|
||||
remove patch set for the package base
|
||||
|
||||
Args:
|
||||
application(Application): application instance
|
||||
package_base(str): package base
|
||||
variables(List[str]): remove patches only for specified PKGBUILD variables
|
||||
variables(list[str]): remove patches only for specified PKGBUILD variables
|
||||
"""
|
||||
application.database.patches_remove(package_base, variables)
|
||||
|
@ -19,8 +19,6 @@
|
||||
#
|
||||
import argparse
|
||||
|
||||
from typing import List, Type
|
||||
|
||||
from ahriman.application.application import Application
|
||||
from ahriman.application.handlers import Handler
|
||||
from ahriman.core.configuration import Configuration
|
||||
@ -34,7 +32,7 @@ class Rebuild(Handler):
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
def run(cls: type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
@ -46,13 +44,11 @@ class Rebuild(Handler):
|
||||
report(bool): force enable or disable reporting
|
||||
unsafe(bool): if set no user check will be performed before path creation
|
||||
"""
|
||||
depends_on = set(args.depends_on) if args.depends_on else None
|
||||
|
||||
application = Application(architecture, configuration, report=report, unsafe=unsafe)
|
||||
application.on_start()
|
||||
|
||||
packages = Rebuild.extract_packages(application, from_database=args.from_database)
|
||||
updates = application.repository.packages_depend_on(packages, depends_on)
|
||||
updates = application.repository.packages_depend_on(packages, args.depends_on or None)
|
||||
|
||||
Rebuild.check_if_empty(args.exit_code, not updates)
|
||||
if args.dry_run:
|
||||
@ -64,7 +60,7 @@ class Rebuild(Handler):
|
||||
Rebuild.check_if_empty(args.exit_code, result.is_empty)
|
||||
|
||||
@staticmethod
|
||||
def extract_packages(application: Application, *, from_database: bool) -> List[Package]:
|
||||
def extract_packages(application: Application, *, from_database: bool) -> list[Package]:
|
||||
"""
|
||||
extract packages from database file
|
||||
|
||||
@ -73,7 +69,7 @@ class Rebuild(Handler):
|
||||
from_database(bool): extract packages from database instead of repository filesystem
|
||||
|
||||
Returns:
|
||||
List[Package]: list of packages which were stored in database
|
||||
list[Package]: list of packages which were stored in database
|
||||
"""
|
||||
if from_database:
|
||||
return [package for (package, _) in application.database.packages_get()]
|
||||
|
@ -19,8 +19,6 @@
|
||||
#
|
||||
import argparse
|
||||
|
||||
from typing import Type
|
||||
|
||||
from ahriman.application.application import Application
|
||||
from ahriman.application.handlers import Handler
|
||||
from ahriman.core.configuration import Configuration
|
||||
@ -32,7 +30,7 @@ class Remove(Handler):
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
def run(cls: type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
|
@ -19,8 +19,6 @@
|
||||
#
|
||||
import argparse
|
||||
|
||||
from typing import Type
|
||||
|
||||
from ahriman.application.application import Application
|
||||
from ahriman.application.handlers import Handler
|
||||
from ahriman.core.configuration import Configuration
|
||||
@ -33,7 +31,7 @@ class RemoveUnknown(Handler):
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
def run(cls: type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
|
@ -19,7 +19,6 @@
|
||||
#
|
||||
import argparse
|
||||
|
||||
from typing import Type
|
||||
from tarfile import TarFile
|
||||
|
||||
from ahriman.application.handlers import Handler
|
||||
@ -34,7 +33,7 @@ class Restore(Handler):
|
||||
ALLOW_AUTO_ARCHITECTURE_RUN = False # it should be called only as "no-architecture"
|
||||
|
||||
@classmethod
|
||||
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
def run(cls: type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
|
@ -20,7 +20,7 @@
|
||||
import argparse
|
||||
|
||||
from dataclasses import fields
|
||||
from typing import Callable, Iterable, List, Tuple, Type
|
||||
from collections.abc import Callable, Iterable
|
||||
|
||||
from ahriman.application.application import Application
|
||||
from ahriman.application.handlers import Handler
|
||||
@ -36,14 +36,14 @@ class Search(Handler):
|
||||
packages search handler
|
||||
|
||||
Attributes:
|
||||
SORT_FIELDS(Set[str]): (class attribute) allowed fields to sort the package list
|
||||
SORT_FIELDS(set[str]): (class attribute) allowed fields to sort the package list
|
||||
"""
|
||||
|
||||
ALLOW_AUTO_ARCHITECTURE_RUN = False # it should be called only as "no-architecture"
|
||||
SORT_FIELDS = {field.name for field in fields(AURPackage) if field.default_factory is not list} # type: ignore
|
||||
|
||||
@classmethod
|
||||
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
def run(cls: type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
@ -67,7 +67,7 @@ class Search(Handler):
|
||||
AurPrinter(package).print(verbose=args.info)
|
||||
|
||||
@staticmethod
|
||||
def sort(packages: Iterable[AURPackage], sort_by: str) -> List[AURPackage]:
|
||||
def sort(packages: Iterable[AURPackage], sort_by: str) -> list[AURPackage]:
|
||||
"""
|
||||
sort package list by specified field
|
||||
|
||||
@ -76,7 +76,7 @@ class Search(Handler):
|
||||
sort_by(str): AUR package field name to sort by
|
||||
|
||||
Returns:
|
||||
List[AURPackage]: sorted list for packages
|
||||
list[AURPackage]: sorted list for packages
|
||||
|
||||
Raises:
|
||||
InvalidOption: if search fields is not in list of allowed ones
|
||||
@ -85,6 +85,6 @@ class Search(Handler):
|
||||
raise OptionError(sort_by)
|
||||
# always sort by package name at the last
|
||||
# well technically it is not a string, but we can deal with it
|
||||
comparator: Callable[[AURPackage], Tuple[str, str]] =\
|
||||
comparator: Callable[[AURPackage], tuple[str, str]] =\
|
||||
lambda package: (getattr(package, sort_by), package.name)
|
||||
return sorted(packages, key=comparator)
|
||||
|
@ -19,8 +19,6 @@
|
||||
#
|
||||
import argparse
|
||||
|
||||
from typing import Type
|
||||
|
||||
from ahriman import version
|
||||
from ahriman.application.application import Application
|
||||
from ahriman.application.handlers import Handler
|
||||
@ -37,7 +35,7 @@ class ServiceUpdates(Handler):
|
||||
ALLOW_AUTO_ARCHITECTURE_RUN = False # it should be called only as "no-architecture"
|
||||
|
||||
@classmethod
|
||||
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
def run(cls: type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
|
@ -21,7 +21,6 @@ import argparse
|
||||
|
||||
from pathlib import Path
|
||||
from pwd import getpwuid
|
||||
from typing import Optional, Type
|
||||
|
||||
from ahriman.application.application import Application
|
||||
from ahriman.application.handlers import Handler
|
||||
@ -46,7 +45,7 @@ class Setup(Handler):
|
||||
SUDOERS_DIR_PATH = Path("/etc/sudoers.d")
|
||||
|
||||
@classmethod
|
||||
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
def run(cls: type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
@ -132,7 +131,7 @@ class Setup(Handler):
|
||||
configuration.write(ahriman_configuration)
|
||||
|
||||
@staticmethod
|
||||
def configuration_create_devtools(prefix: str, architecture: str, source: Path, mirror: Optional[str],
|
||||
def configuration_create_devtools(prefix: str, architecture: str, source: Path, mirror: str | None,
|
||||
multilib: bool, repository: str, paths: RepositoryPaths) -> None:
|
||||
"""
|
||||
create configuration for devtools based on ``source`` configuration
|
||||
@ -144,7 +143,7 @@ class Setup(Handler):
|
||||
prefix(str): command prefix in {prefix}-{architecture}-build
|
||||
architecture(str): repository architecture
|
||||
source(Path): path to source configuration file
|
||||
mirror(Optional[str]): link to package server mirror
|
||||
mirror(str | None): link to package server mirror
|
||||
multilib(bool): add or do not multilib repository to the configuration
|
||||
repository(str): repository name
|
||||
paths(RepositoryPaths): repository paths instance
|
||||
|
@ -22,7 +22,6 @@ import code
|
||||
import sys
|
||||
|
||||
from pathlib import Path
|
||||
from typing import Type
|
||||
|
||||
from ahriman.application.application import Application
|
||||
from ahriman.application.handlers import Handler
|
||||
@ -38,7 +37,7 @@ class Shell(Handler):
|
||||
ALLOW_MULTI_ARCHITECTURE_RUN = False
|
||||
|
||||
@classmethod
|
||||
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
def run(cls: type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
|
@ -19,8 +19,6 @@
|
||||
#
|
||||
import argparse
|
||||
|
||||
from typing import Type
|
||||
|
||||
from ahriman.application.application import Application
|
||||
from ahriman.application.handlers import Handler
|
||||
from ahriman.core.configuration import Configuration
|
||||
@ -32,7 +30,7 @@ class Sign(Handler):
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
def run(cls: type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
|
@ -19,7 +19,7 @@
|
||||
#
|
||||
import argparse
|
||||
|
||||
from typing import Callable, Iterable, Tuple, Type
|
||||
from collections.abc import Callable
|
||||
|
||||
from ahriman.application.application import Application
|
||||
from ahriman.application.handlers import Handler
|
||||
@ -37,7 +37,7 @@ class Status(Handler):
|
||||
ALLOW_AUTO_ARCHITECTURE_RUN = False
|
||||
|
||||
@classmethod
|
||||
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
def run(cls: type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
@ -55,7 +55,7 @@ class Status(Handler):
|
||||
service_status = client.get_internal()
|
||||
StatusPrinter(service_status.status).print(verbose=args.info)
|
||||
if args.package:
|
||||
packages: Iterable[Tuple[Package, BuildStatus]] = sum(
|
||||
packages: list[tuple[Package, BuildStatus]] = sum(
|
||||
(client.get(base) for base in args.package),
|
||||
start=[])
|
||||
else:
|
||||
@ -63,8 +63,8 @@ class Status(Handler):
|
||||
|
||||
Status.check_if_empty(args.exit_code, not packages)
|
||||
|
||||
comparator: Callable[[Tuple[Package, BuildStatus]], str] = lambda item: item[0].base
|
||||
filter_fn: Callable[[Tuple[Package, BuildStatus]], bool] =\
|
||||
comparator: Callable[[tuple[Package, BuildStatus]], str] = lambda item: item[0].base
|
||||
filter_fn: Callable[[tuple[Package, BuildStatus]], bool] =\
|
||||
lambda item: args.status is None or item[1].status == args.status
|
||||
for package, package_status in sorted(filter(filter_fn, packages), key=comparator):
|
||||
PackagePrinter(package, package_status).print(verbose=args.info)
|
||||
|
@ -19,8 +19,6 @@
|
||||
#
|
||||
import argparse
|
||||
|
||||
from typing import Type
|
||||
|
||||
from ahriman.application.application import Application
|
||||
from ahriman.application.handlers import Handler
|
||||
from ahriman.core.configuration import Configuration
|
||||
@ -35,7 +33,7 @@ class StatusUpdate(Handler):
|
||||
ALLOW_AUTO_ARCHITECTURE_RUN = False
|
||||
|
||||
@classmethod
|
||||
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
def run(cls: type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
|
@ -19,8 +19,6 @@
|
||||
#
|
||||
import argparse
|
||||
|
||||
from typing import Type
|
||||
|
||||
from ahriman.application.application import Application
|
||||
from ahriman.application.handlers import Handler
|
||||
from ahriman.core.configuration import Configuration
|
||||
@ -36,7 +34,7 @@ class Structure(Handler):
|
||||
ALLOW_AUTO_ARCHITECTURE_RUN = False
|
||||
|
||||
@classmethod
|
||||
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
def run(cls: type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
|
@ -19,8 +19,6 @@
|
||||
#
|
||||
import argparse
|
||||
|
||||
from typing import Type
|
||||
|
||||
from ahriman.application.application import Application
|
||||
from ahriman.application.handlers import Handler
|
||||
from ahriman.core.configuration import Configuration
|
||||
@ -33,7 +31,7 @@ class Triggers(Handler):
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
def run(cls: type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
|
@ -20,8 +20,6 @@
|
||||
import argparse
|
||||
import shlex
|
||||
|
||||
from typing import List, Type
|
||||
|
||||
from ahriman.application.handlers import Handler
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.formatters import StringPrinter
|
||||
@ -35,7 +33,7 @@ class UnsafeCommands(Handler):
|
||||
ALLOW_AUTO_ARCHITECTURE_RUN = False # it should be called only as "no-architecture"
|
||||
|
||||
@classmethod
|
||||
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
def run(cls: type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
@ -56,20 +54,20 @@ class UnsafeCommands(Handler):
|
||||
UnsafeCommands.check_unsafe(args.command, unsafe_commands, parser)
|
||||
|
||||
@staticmethod
|
||||
def check_unsafe(command: str, unsafe_commands: List[str], parser: argparse.ArgumentParser) -> None:
|
||||
def check_unsafe(command: str, unsafe_commands: list[str], parser: argparse.ArgumentParser) -> None:
|
||||
"""
|
||||
check if command is unsafe
|
||||
|
||||
Args:
|
||||
command(str): command to check
|
||||
unsafe_commands(List[str]): list of unsafe commands
|
||||
unsafe_commands(list[str]): list of unsafe commands
|
||||
parser(argparse.ArgumentParser): generated argument parser
|
||||
"""
|
||||
args = parser.parse_args(shlex.split(command))
|
||||
UnsafeCommands.check_if_empty(True, args.command in unsafe_commands)
|
||||
|
||||
@staticmethod
|
||||
def get_unsafe_commands(parser: argparse.ArgumentParser) -> List[str]:
|
||||
def get_unsafe_commands(parser: argparse.ArgumentParser) -> list[str]:
|
||||
"""
|
||||
extract unsafe commands from argument parser
|
||||
|
||||
@ -77,7 +75,7 @@ class UnsafeCommands(Handler):
|
||||
parser(argparse.ArgumentParser): generated argument parser
|
||||
|
||||
Returns:
|
||||
List[str]: list of commands with default unsafe flag
|
||||
list[str]: list of commands with default unsafe flag
|
||||
"""
|
||||
# should never fail
|
||||
# pylint: disable=protected-access
|
||||
|
@ -19,7 +19,7 @@
|
||||
#
|
||||
import argparse
|
||||
|
||||
from typing import Callable, Type
|
||||
from collections.abc import Callable
|
||||
|
||||
from ahriman.application.application import Application
|
||||
from ahriman.application.handlers import Handler
|
||||
@ -32,7 +32,7 @@ class Update(Handler):
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
def run(cls: type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
|
@ -21,7 +21,6 @@ import argparse
|
||||
import getpass
|
||||
|
||||
from pathlib import Path
|
||||
from typing import Optional, Tuple, Type
|
||||
|
||||
from ahriman.application.handlers import Handler
|
||||
from ahriman.core.configuration import Configuration
|
||||
@ -40,7 +39,7 @@ class Users(Handler):
|
||||
ALLOW_AUTO_ARCHITECTURE_RUN = False # it should be called only as "no-architecture"
|
||||
|
||||
@classmethod
|
||||
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
def run(cls: type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
@ -119,7 +118,7 @@ class Users(Handler):
|
||||
path.chmod(0o600)
|
||||
|
||||
@staticmethod
|
||||
def get_salt(configuration: Configuration, salt_length: int = 20) -> Tuple[Optional[str], str]:
|
||||
def get_salt(configuration: Configuration, salt_length: int = 20) -> tuple[str | None, str]:
|
||||
"""
|
||||
get salt from configuration or create new string
|
||||
|
||||
@ -128,7 +127,7 @@ class Users(Handler):
|
||||
salt_length(int, optional): salt length (Default value = 20)
|
||||
|
||||
Returns:
|
||||
Tuple[Optional[str], str]: tuple containing salt from configuration if any and actual salt which must be
|
||||
tuple[str | None, str]: tuple containing salt from configuration if any and actual salt which must be
|
||||
used for password hash
|
||||
"""
|
||||
if salt := configuration.get("auth", "salt", fallback=None):
|
||||
|
@ -20,7 +20,7 @@
|
||||
import argparse
|
||||
import copy
|
||||
|
||||
from typing import Any, Dict, Type
|
||||
from typing import Any
|
||||
|
||||
from ahriman.application.handlers import Handler
|
||||
from ahriman.core.configuration import Configuration
|
||||
@ -39,7 +39,7 @@ class Validate(Handler):
|
||||
ALLOW_AUTO_ARCHITECTURE_RUN = False
|
||||
|
||||
@classmethod
|
||||
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
def run(cls: type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
@ -112,17 +112,17 @@ class Validate(Handler):
|
||||
return schema
|
||||
|
||||
@staticmethod
|
||||
def schema_merge(source: Dict[str, Any], schema: Dict[str, Any]) -> Dict[str, Any]:
|
||||
def schema_merge(source: dict[str, Any], schema: dict[str, Any]) -> dict[str, Any]:
|
||||
"""
|
||||
merge child schema into source. In case if source already contains values, new keys will be added
|
||||
(possibly with overrides - in case if such key already set also)
|
||||
|
||||
Args:
|
||||
source(Dict[str, Any]): source (current) schema into which will be merged
|
||||
schema(Dict[str, Any]): new schema to be merged
|
||||
source(dict[str, Any]): source (current) schema into which will be merged
|
||||
schema(dict[str, Any]): new schema to be merged
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: schema with added elements from source schema if they were set before and not presented
|
||||
dict[str, Any]: schema with added elements from source schema if they were set before and not presented
|
||||
in the new one. Note, that schema will be modified in-place
|
||||
"""
|
||||
for key, value in source.items():
|
||||
|
@ -21,8 +21,6 @@ import argparse
|
||||
import pkg_resources
|
||||
import sys
|
||||
|
||||
from typing import Dict, List, Tuple, Type
|
||||
|
||||
from ahriman import version
|
||||
from ahriman.application.handlers import Handler
|
||||
from ahriman.core.configuration import Configuration
|
||||
@ -37,7 +35,7 @@ class Versions(Handler):
|
||||
ALLOW_AUTO_ARCHITECTURE_RUN = False # it should be called only as "no-architecture"
|
||||
|
||||
@classmethod
|
||||
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
def run(cls: type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
@ -55,23 +53,23 @@ class Versions(Handler):
|
||||
VersionPrinter("Installed packages", packages).print(verbose=False, separator=" ")
|
||||
|
||||
@staticmethod
|
||||
def package_dependencies(root: str, root_extras: Tuple[str, ...] = ()) -> Dict[str, str]:
|
||||
def package_dependencies(root: str, root_extras: tuple[str, ...] = ()) -> dict[str, str]:
|
||||
"""
|
||||
extract list of ahriman package dependencies installed into system with their versions
|
||||
|
||||
Args:
|
||||
root(str): root package name
|
||||
root_extras(Tuple[str, ...], optional): extras for the root package (Default value = ())
|
||||
root_extras(tuple[str, ...], optional): extras for the root package (Default value = ())
|
||||
|
||||
Returns:
|
||||
Dict[str, str]: map of installed dependency to its version
|
||||
dict[str, str]: map of installed dependency to its version
|
||||
"""
|
||||
resources: Dict[str, pkg_resources.Distribution] = pkg_resources.working_set.by_key # type: ignore
|
||||
resources: dict[str, pkg_resources.Distribution] = pkg_resources.working_set.by_key # type: ignore
|
||||
|
||||
def dependencies_by_key(key: str, extras: Tuple[str, ...] = ()) -> List[str]:
|
||||
def dependencies_by_key(key: str, extras: tuple[str, ...] = ()) -> list[str]:
|
||||
return [entry.key for entry in resources[key].requires(extras)]
|
||||
|
||||
keys: List[str] = []
|
||||
keys: list[str] = []
|
||||
portion = {key for key in dependencies_by_key(root, root_extras) if key in resources}
|
||||
while portion:
|
||||
keys.extend(portion)
|
||||
|
@ -19,8 +19,6 @@
|
||||
#
|
||||
import argparse
|
||||
|
||||
from typing import Type
|
||||
|
||||
from ahriman.application.handlers import Handler
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.spawn import Spawn
|
||||
@ -35,7 +33,7 @@ class Web(Handler):
|
||||
ALLOW_MULTI_ARCHITECTURE_RUN = False # required to be able to spawn external processes
|
||||
|
||||
@classmethod
|
||||
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
def run(cls: type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
|
@ -22,7 +22,7 @@ from __future__ import annotations
|
||||
import argparse
|
||||
|
||||
from types import TracebackType
|
||||
from typing import Literal, Optional, Type
|
||||
from typing import Literal
|
||||
|
||||
from ahriman import version
|
||||
from ahriman.core.configuration import Configuration
|
||||
@ -127,14 +127,14 @@ class Lock(LazyLogging):
|
||||
self.reporter.update_self(BuildStatusEnum.Building)
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type: Optional[Type[Exception]], exc_val: Optional[Exception],
|
||||
def __exit__(self, exc_type: type[Exception] | None, exc_val: Exception | None,
|
||||
exc_tb: TracebackType) -> Literal[False]:
|
||||
"""
|
||||
remove lock file when done
|
||||
|
||||
Args:
|
||||
exc_type(Optional[Type[Exception]]): exception type name if any
|
||||
exc_val(Optional[Exception]): exception raised if any
|
||||
exc_type(type[Exception] | None): exception type name if any
|
||||
exc_val(Exception | None): exception raised if any
|
||||
exc_tb(TracebackType): exception traceback if any
|
||||
|
||||
Returns:
|
||||
|
@ -17,8 +17,9 @@
|
||||
# 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 collections.abc import Iterator
|
||||
from contextvars import ContextVar
|
||||
from typing import Any, Dict, Iterator, TypeVar
|
||||
from typing import Any, TypeVar
|
||||
|
||||
from ahriman.models.context_key import ContextKey
|
||||
|
||||
@ -35,7 +36,7 @@ class _Context:
|
||||
"""
|
||||
default constructor. Must not be used directly
|
||||
"""
|
||||
self._content: Dict[str, Any] = {}
|
||||
self._content: dict[str, Any] = {}
|
||||
|
||||
def get(self, key: ContextKey[T]) -> T:
|
||||
"""
|
||||
|
@ -19,9 +19,10 @@
|
||||
#
|
||||
import shutil
|
||||
|
||||
from collections.abc import Callable, Generator
|
||||
from pathlib import Path
|
||||
from pyalpm import DB, Handle, Package, SIG_PACKAGE, error as PyalpmError # type: ignore
|
||||
from typing import Any, Callable, Generator, Set
|
||||
from typing import Any
|
||||
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.log import LazyLogging
|
||||
@ -166,14 +167,14 @@ class Pacman(LazyLogging):
|
||||
continue
|
||||
yield package
|
||||
|
||||
def packages(self) -> Set[str]:
|
||||
def packages(self) -> set[str]:
|
||||
"""
|
||||
get list of packages known for alpm
|
||||
|
||||
Returns:
|
||||
Set[str]: list of package names
|
||||
set[str]: list of package names
|
||||
"""
|
||||
result: Set[str] = set()
|
||||
result: set[str] = set()
|
||||
for database in self.handle.get_syncdbs():
|
||||
for package in database.pkgcache:
|
||||
# package itself
|
||||
|
@ -19,7 +19,7 @@
|
||||
#
|
||||
import requests
|
||||
|
||||
from typing import Any, Dict, List, Type
|
||||
from typing import Any
|
||||
|
||||
from ahriman.core.alpm.pacman import Pacman
|
||||
from ahriman.core.alpm.remote import Remote
|
||||
@ -45,15 +45,15 @@ class AUR(Remote):
|
||||
DEFAULT_TIMEOUT = 30
|
||||
|
||||
@staticmethod
|
||||
def parse_response(response: Dict[str, Any]) -> List[AURPackage]:
|
||||
def parse_response(response: dict[str, Any]) -> list[AURPackage]:
|
||||
"""
|
||||
parse RPC response to package list
|
||||
|
||||
Args:
|
||||
response(Dict[str, Any]): RPC response json
|
||||
response(dict[str, Any]): RPC response json
|
||||
|
||||
Returns:
|
||||
List[AURPackage]: list of parsed packages
|
||||
list[AURPackage]: list of parsed packages
|
||||
|
||||
Raises:
|
||||
InvalidPackageInfo: for error API response
|
||||
@ -65,7 +65,7 @@ class AUR(Remote):
|
||||
return [AURPackage.from_json(package) for package in response["results"]]
|
||||
|
||||
@classmethod
|
||||
def remote_git_url(cls: Type[Remote], package_base: str, repository: str) -> str:
|
||||
def remote_git_url(cls: type[Remote], package_base: str, repository: str) -> str:
|
||||
"""
|
||||
generate remote git url from the package base
|
||||
|
||||
@ -79,7 +79,7 @@ class AUR(Remote):
|
||||
return f"{AUR.DEFAULT_AUR_URL}/{package_base}.git"
|
||||
|
||||
@classmethod
|
||||
def remote_web_url(cls: Type[Remote], package_base: str) -> str:
|
||||
def remote_web_url(cls: type[Remote], package_base: str) -> str:
|
||||
"""
|
||||
generate remote web url from the package base
|
||||
|
||||
@ -91,7 +91,7 @@ class AUR(Remote):
|
||||
"""
|
||||
return f"{AUR.DEFAULT_AUR_URL}/packages/{package_base}"
|
||||
|
||||
def make_request(self, request_type: str, *args: str, **kwargs: str) -> List[AURPackage]:
|
||||
def make_request(self, request_type: str, *args: str, **kwargs: str) -> list[AURPackage]:
|
||||
"""
|
||||
perform request to AUR RPC
|
||||
|
||||
@ -101,9 +101,9 @@ class AUR(Remote):
|
||||
**kwargs(str): list of additional named parameters like by
|
||||
|
||||
Returns:
|
||||
List[AURPackage]: response parsed to package list
|
||||
list[AURPackage]: response parsed to package list
|
||||
"""
|
||||
query: Dict[str, Any] = {
|
||||
query: dict[str, Any] = {
|
||||
"type": request_type,
|
||||
"v": self.DEFAULT_RPC_VERSION
|
||||
}
|
||||
@ -145,7 +145,7 @@ class AUR(Remote):
|
||||
except StopIteration:
|
||||
raise UnknownPackageError(package_name)
|
||||
|
||||
def package_search(self, *keywords: str, pacman: Pacman) -> List[AURPackage]:
|
||||
def package_search(self, *keywords: str, pacman: Pacman) -> list[AURPackage]:
|
||||
"""
|
||||
search package in AUR web
|
||||
|
||||
@ -154,6 +154,6 @@ class AUR(Remote):
|
||||
pacman(Pacman): alpm wrapper instance
|
||||
|
||||
Returns:
|
||||
List[AURPackage]: list of packages which match the criteria
|
||||
list[AURPackage]: list of packages which match the criteria
|
||||
"""
|
||||
return self.make_request("search", *keywords, by="name-desc")
|
||||
|
@ -19,7 +19,7 @@
|
||||
#
|
||||
import requests
|
||||
|
||||
from typing import Any, Dict, List, Type
|
||||
from typing import Any
|
||||
|
||||
from ahriman.core.alpm.pacman import Pacman
|
||||
from ahriman.core.alpm.remote import Remote
|
||||
@ -34,7 +34,7 @@ class Official(Remote):
|
||||
|
||||
Attributes:
|
||||
DEFAULT_ARCHLINUX_URL(str): (class attribute) default archlinux url
|
||||
DEFAULT_SEARCH_REPOSITORIES(List[str]): (class attribute) default list of repositories to search
|
||||
DEFAULT_SEARCH_REPOSITORIES(list[str]): (class attribute) default list of repositories to search
|
||||
DEFAULT_RPC_URL(str): (class attribute) default archlinux repositories RPC url
|
||||
DEFAULT_TIMEOUT(int): (class attribute) HTTP request timeout in seconds
|
||||
"""
|
||||
@ -45,15 +45,15 @@ class Official(Remote):
|
||||
DEFAULT_TIMEOUT = 30
|
||||
|
||||
@staticmethod
|
||||
def parse_response(response: Dict[str, Any]) -> List[AURPackage]:
|
||||
def parse_response(response: dict[str, Any]) -> list[AURPackage]:
|
||||
"""
|
||||
parse RPC response to package list
|
||||
|
||||
Args:
|
||||
response(Dict[str, Any]): RPC response json
|
||||
response(dict[str, Any]): RPC response json
|
||||
|
||||
Returns:
|
||||
List[AURPackage]: list of parsed packages
|
||||
list[AURPackage]: list of parsed packages
|
||||
|
||||
Raises:
|
||||
InvalidPackageInfo: for error API response
|
||||
@ -63,7 +63,7 @@ class Official(Remote):
|
||||
return [AURPackage.from_repo(package) for package in response["results"]]
|
||||
|
||||
@classmethod
|
||||
def remote_git_url(cls: Type[Remote], package_base: str, repository: str) -> str:
|
||||
def remote_git_url(cls: type[Remote], package_base: str, repository: str) -> str:
|
||||
"""
|
||||
generate remote git url from the package base
|
||||
|
||||
@ -79,7 +79,7 @@ class Official(Remote):
|
||||
return "https://github.com/archlinux/svntogit-community.git"
|
||||
|
||||
@classmethod
|
||||
def remote_web_url(cls: Type[Remote], package_base: str) -> str:
|
||||
def remote_web_url(cls: type[Remote], package_base: str) -> str:
|
||||
"""
|
||||
generate remote web url from the package base
|
||||
|
||||
@ -91,7 +91,7 @@ class Official(Remote):
|
||||
"""
|
||||
return f"{Official.DEFAULT_ARCHLINUX_URL}/packages/{package_base}"
|
||||
|
||||
def make_request(self, *args: str, by: str) -> List[AURPackage]:
|
||||
def make_request(self, *args: str, by: str) -> list[AURPackage]:
|
||||
"""
|
||||
perform request to official repositories RPC
|
||||
|
||||
@ -100,7 +100,7 @@ class Official(Remote):
|
||||
by(str): search by the field
|
||||
|
||||
Returns:
|
||||
List[AURPackage]: response parsed to package list
|
||||
list[AURPackage]: response parsed to package list
|
||||
"""
|
||||
try:
|
||||
response = requests.get(
|
||||
@ -133,7 +133,7 @@ class Official(Remote):
|
||||
except StopIteration:
|
||||
raise UnknownPackageError(package_name)
|
||||
|
||||
def package_search(self, *keywords: str, pacman: Pacman) -> List[AURPackage]:
|
||||
def package_search(self, *keywords: str, pacman: Pacman) -> list[AURPackage]:
|
||||
"""
|
||||
search package in AUR web
|
||||
|
||||
@ -142,6 +142,6 @@ class Official(Remote):
|
||||
pacman(Pacman): alpm wrapper instance
|
||||
|
||||
Returns:
|
||||
List[AURPackage]: list of packages which match the criteria
|
||||
list[AURPackage]: list of packages which match the criteria
|
||||
"""
|
||||
return self.make_request(*keywords, by="q")
|
||||
|
@ -19,8 +19,6 @@
|
||||
#
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Dict, List, Type
|
||||
|
||||
from ahriman.core.alpm.pacman import Pacman
|
||||
from ahriman.core.log import LazyLogging
|
||||
from ahriman.models.aur_package import AURPackage
|
||||
@ -44,7 +42,7 @@ class Remote(LazyLogging):
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def info(cls: Type[Remote], package_name: str, *, pacman: Pacman) -> AURPackage:
|
||||
def info(cls: type[Remote], package_name: str, *, pacman: Pacman) -> AURPackage:
|
||||
"""
|
||||
get package info by its name
|
||||
|
||||
@ -58,7 +56,7 @@ class Remote(LazyLogging):
|
||||
return cls().package_info(package_name, pacman=pacman)
|
||||
|
||||
@classmethod
|
||||
def multisearch(cls: Type[Remote], *keywords: str, pacman: Pacman) -> List[AURPackage]:
|
||||
def multisearch(cls: type[Remote], *keywords: str, pacman: Pacman) -> list[AURPackage]:
|
||||
"""
|
||||
search in remote repository by using API with multiple words. This method is required in order to handle
|
||||
https://bugs.archlinux.org/task/49133. In addition, short words will be dropped
|
||||
@ -68,10 +66,10 @@ class Remote(LazyLogging):
|
||||
pacman(Pacman): alpm wrapper instance
|
||||
|
||||
Returns:
|
||||
List[AURPackage]: list of packages each of them matches all search terms
|
||||
list[AURPackage]: list of packages each of them matches all search terms
|
||||
"""
|
||||
instance = cls()
|
||||
packages: Dict[str, AURPackage] = {}
|
||||
packages: dict[str, AURPackage] = {}
|
||||
for term in filter(lambda word: len(word) >= 3, keywords):
|
||||
portion = instance.search(term, pacman=pacman)
|
||||
packages = {
|
||||
@ -82,7 +80,7 @@ class Remote(LazyLogging):
|
||||
return list(packages.values())
|
||||
|
||||
@classmethod
|
||||
def remote_git_url(cls: Type[Remote], package_base: str, repository: str) -> str:
|
||||
def remote_git_url(cls: type[Remote], package_base: str, repository: str) -> str:
|
||||
"""
|
||||
generate remote git url from the package base
|
||||
|
||||
@ -99,7 +97,7 @@ class Remote(LazyLogging):
|
||||
raise NotImplementedError
|
||||
|
||||
@classmethod
|
||||
def remote_web_url(cls: Type[Remote], package_base: str) -> str:
|
||||
def remote_web_url(cls: type[Remote], package_base: str) -> str:
|
||||
"""
|
||||
generate remote web url from the package base
|
||||
|
||||
@ -115,7 +113,7 @@ class Remote(LazyLogging):
|
||||
raise NotImplementedError
|
||||
|
||||
@classmethod
|
||||
def search(cls: Type[Remote], *keywords: str, pacman: Pacman) -> List[AURPackage]:
|
||||
def search(cls: type[Remote], *keywords: str, pacman: Pacman) -> list[AURPackage]:
|
||||
"""
|
||||
search package in AUR web
|
||||
|
||||
@ -124,7 +122,7 @@ class Remote(LazyLogging):
|
||||
pacman(Pacman): alpm wrapper instance
|
||||
|
||||
Returns:
|
||||
List[AURPackage]: list of packages which match the criteria
|
||||
list[AURPackage]: list of packages which match the criteria
|
||||
"""
|
||||
return cls().package_search(*keywords, pacman=pacman)
|
||||
|
||||
@ -144,7 +142,7 @@ class Remote(LazyLogging):
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def package_search(self, *keywords: str, pacman: Pacman) -> List[AURPackage]:
|
||||
def package_search(self, *keywords: str, pacman: Pacman) -> list[AURPackage]:
|
||||
"""
|
||||
search package in AUR web
|
||||
|
||||
@ -153,7 +151,7 @@ class Remote(LazyLogging):
|
||||
pacman(Pacman): alpm wrapper instance
|
||||
|
||||
Returns:
|
||||
List[AURPackage]: list of packages which match the criteria
|
||||
list[AURPackage]: list of packages which match the criteria
|
||||
|
||||
Raises:
|
||||
NotImplementedError: not implemented method
|
||||
|
@ -18,7 +18,6 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
from pathlib import Path
|
||||
from typing import List
|
||||
|
||||
from ahriman.core.exceptions import BuildError
|
||||
from ahriman.core.log import LazyLogging
|
||||
@ -33,20 +32,20 @@ class Repo(LazyLogging):
|
||||
Attributes:
|
||||
name(str): repository name
|
||||
paths(RepositoryPaths): repository paths instance
|
||||
sign_args(List[str]): additional args which have to be used to sign repository archive
|
||||
sign_args(list[str]): additional args which have to be used to sign repository archive
|
||||
uid(int): uid of the repository owner user
|
||||
"""
|
||||
|
||||
_check_output = check_output
|
||||
|
||||
def __init__(self, name: str, paths: RepositoryPaths, sign_args: List[str]) -> None:
|
||||
def __init__(self, name: str, paths: RepositoryPaths, sign_args: list[str]) -> None:
|
||||
"""
|
||||
default constructor
|
||||
|
||||
Args:
|
||||
name(str): repository name
|
||||
paths(RepositoryPaths): repository paths instance
|
||||
sign_args(List[str]): additional args which have to be used to sign repository archive
|
||||
sign_args(list[str]): additional args which have to be used to sign repository archive
|
||||
"""
|
||||
self.name = name
|
||||
self.paths = paths
|
||||
|
@ -19,8 +19,6 @@
|
||||
#
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Optional, Type
|
||||
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.database import SQLite
|
||||
from ahriman.core.log import LazyLogging
|
||||
@ -65,7 +63,7 @@ class Auth(LazyLogging):
|
||||
return """<button type="button" class="btn btn-link" data-bs-toggle="modal" data-bs-target="#login-modal" style="text-decoration: none"><i class="bi bi-box-arrow-in-right"></i> login</button>"""
|
||||
|
||||
@classmethod
|
||||
def load(cls: Type[Auth], configuration: Configuration, database: SQLite) -> Auth:
|
||||
def load(cls: type[Auth], configuration: Configuration, database: SQLite) -> Auth:
|
||||
"""
|
||||
load authorization module from settings
|
||||
|
||||
@ -85,13 +83,13 @@ class Auth(LazyLogging):
|
||||
return OAuth(configuration, database)
|
||||
return cls(configuration)
|
||||
|
||||
async def check_credentials(self, username: Optional[str], password: Optional[str]) -> bool:
|
||||
async def check_credentials(self, username: str | None, password: str | None) -> bool:
|
||||
"""
|
||||
validate user password
|
||||
|
||||
Args:
|
||||
username(Optional[str]): username
|
||||
password(Optional[str]): entered password
|
||||
username(str | None): username
|
||||
password(str | None): entered password
|
||||
|
||||
Returns:
|
||||
bool: True in case if password matches, False otherwise
|
||||
@ -99,12 +97,12 @@ class Auth(LazyLogging):
|
||||
del username, password
|
||||
return True
|
||||
|
||||
async def known_username(self, username: Optional[str]) -> bool:
|
||||
async def known_username(self, username: str | None) -> bool:
|
||||
"""
|
||||
check if user is known
|
||||
|
||||
Args:
|
||||
username(Optional[str]): username
|
||||
username(str | None): username
|
||||
|
||||
Returns:
|
||||
bool: True in case if user is known and can be authorized and False otherwise
|
||||
@ -112,14 +110,14 @@ class Auth(LazyLogging):
|
||||
del username
|
||||
return True
|
||||
|
||||
async def verify_access(self, username: str, required: UserAccess, context: Optional[str]) -> bool:
|
||||
async def verify_access(self, username: str, required: UserAccess, context: str | None) -> bool:
|
||||
"""
|
||||
validate if user has access to requested resource
|
||||
|
||||
Args:
|
||||
username(str): username
|
||||
required(UserAccess): required access level
|
||||
context(Optional[str]): URI request path
|
||||
context(str | None): URI request path
|
||||
|
||||
Returns:
|
||||
bool: True in case if user is allowed to do this request and False otherwise
|
||||
|
@ -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/>.
|
||||
#
|
||||
from typing import Optional
|
||||
|
||||
from ahriman.core.auth import Auth
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.database import SQLite
|
||||
@ -50,13 +48,13 @@ class Mapping(Auth):
|
||||
self.database = database
|
||||
self.salt = configuration.get("auth", "salt")
|
||||
|
||||
async def check_credentials(self, username: Optional[str], password: Optional[str]) -> bool:
|
||||
async def check_credentials(self, username: str | None, password: str | None) -> bool:
|
||||
"""
|
||||
validate user password
|
||||
|
||||
Args:
|
||||
username(Optional[str]): username
|
||||
password(Optional[str]): entered password
|
||||
username(str | None): username
|
||||
password(str | None): entered password
|
||||
|
||||
Returns:
|
||||
bool: True in case if password matches, False otherwise
|
||||
@ -66,7 +64,7 @@ class Mapping(Auth):
|
||||
user = self.get_user(username)
|
||||
return user is not None and user.check_credentials(password, self.salt)
|
||||
|
||||
def get_user(self, username: str) -> Optional[User]:
|
||||
def get_user(self, username: str) -> User | None:
|
||||
"""
|
||||
retrieve user from in-memory mapping
|
||||
|
||||
@ -74,30 +72,30 @@ class Mapping(Auth):
|
||||
username(str): username
|
||||
|
||||
Returns:
|
||||
Optional[User]: user descriptor if username is known and None otherwise
|
||||
User | None: user descriptor if username is known and None otherwise
|
||||
"""
|
||||
return self.database.user_get(username)
|
||||
|
||||
async def known_username(self, username: Optional[str]) -> bool:
|
||||
async def known_username(self, username: str | None) -> bool:
|
||||
"""
|
||||
check if user is known
|
||||
|
||||
Args:
|
||||
username(Optional[str]): username
|
||||
username(str | None): username
|
||||
|
||||
Returns:
|
||||
bool: True in case if user is known and can be authorized and False otherwise
|
||||
"""
|
||||
return username is not None and self.get_user(username) is not None
|
||||
|
||||
async def verify_access(self, username: str, required: UserAccess, context: Optional[str]) -> bool:
|
||||
async def verify_access(self, username: str, required: UserAccess, context: str | None) -> bool:
|
||||
"""
|
||||
validate if user has access to requested resource
|
||||
|
||||
Args:
|
||||
username(str): username
|
||||
required(UserAccess): required access level
|
||||
context(Optional[str]): URI request path
|
||||
context(str | None): URI request path
|
||||
|
||||
Returns:
|
||||
bool: True in case if user is allowed to do this request and False otherwise
|
||||
|
@ -19,8 +19,6 @@
|
||||
#
|
||||
import aioauth_client
|
||||
|
||||
from typing import Optional, Type
|
||||
|
||||
from ahriman.core.auth.mapping import Mapping
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.database import SQLite
|
||||
@ -72,7 +70,7 @@ class OAuth(Mapping):
|
||||
return """<a class="nav-link" href="/api/v1/login" title="login via OAuth2"><i class="bi bi-google"></i> login</a>"""
|
||||
|
||||
@staticmethod
|
||||
def get_provider(name: str) -> Type[aioauth_client.OAuth2Client]:
|
||||
def get_provider(name: str) -> type[aioauth_client.OAuth2Client]:
|
||||
"""
|
||||
load OAuth2 provider by name
|
||||
|
||||
@ -80,12 +78,12 @@ class OAuth(Mapping):
|
||||
name(str): name of the provider. Must be valid class defined in aioauth-client library
|
||||
|
||||
Returns:
|
||||
Type[aioauth_client.OAuth2Client]: loaded provider type
|
||||
type[aioauth_client.OAuth2Client]: loaded provider type
|
||||
|
||||
Raises:
|
||||
InvalidOption: in case if invalid OAuth provider name supplied
|
||||
"""
|
||||
provider: Type[aioauth_client.OAuth2Client] = getattr(aioauth_client, name)
|
||||
provider: type[aioauth_client.OAuth2Client] = getattr(aioauth_client, name)
|
||||
try:
|
||||
is_oauth2_client = issubclass(provider, aioauth_client.OAuth2Client)
|
||||
except TypeError: # what if it is random string?
|
||||
@ -114,7 +112,7 @@ class OAuth(Mapping):
|
||||
uri: str = client.get_authorize_url(scope=self.scopes, redirect_uri=self.redirect_uri)
|
||||
return uri
|
||||
|
||||
async def get_oauth_username(self, code: str) -> Optional[str]:
|
||||
async def get_oauth_username(self, code: str) -> str | None:
|
||||
"""
|
||||
extract OAuth username from remote
|
||||
|
||||
@ -122,7 +120,7 @@ class OAuth(Mapping):
|
||||
code(str): authorization code provided by external service
|
||||
|
||||
Returns:
|
||||
Optional[str]: username as is in OAuth provider
|
||||
str | None: username as is in OAuth provider
|
||||
"""
|
||||
try:
|
||||
client = self.get_client()
|
||||
|
@ -20,7 +20,6 @@
|
||||
import shutil
|
||||
|
||||
from pathlib import Path
|
||||
from typing import List, Optional
|
||||
|
||||
from ahriman.core.log import LazyLogging
|
||||
from ahriman.core.util import check_output, utcnow, walk
|
||||
@ -44,7 +43,7 @@ class Sources(LazyLogging):
|
||||
_check_output = check_output
|
||||
|
||||
@staticmethod
|
||||
def extend_architectures(sources_dir: Path, architecture: str) -> List[PkgbuildPatch]:
|
||||
def extend_architectures(sources_dir: Path, architecture: str) -> list[PkgbuildPatch]:
|
||||
"""
|
||||
extend existing PKGBUILD with repository architecture
|
||||
|
||||
@ -53,7 +52,7 @@ class Sources(LazyLogging):
|
||||
architecture(str): repository architecture
|
||||
|
||||
Returns:
|
||||
List[PkgbuildPatch]: generated patch for PKGBUILD architectures if required
|
||||
list[PkgbuildPatch]: generated patch for PKGBUILD architectures if required
|
||||
"""
|
||||
architectures = Package.supported_architectures(sources_dir)
|
||||
if "any" in architectures: # makepkg does not like when there is any other arch except for any
|
||||
@ -62,13 +61,13 @@ class Sources(LazyLogging):
|
||||
return [PkgbuildPatch("arch", list(architectures))]
|
||||
|
||||
@staticmethod
|
||||
def fetch(sources_dir: Path, remote: Optional[RemoteSource]) -> None:
|
||||
def fetch(sources_dir: Path, remote: RemoteSource | None) -> None:
|
||||
"""
|
||||
either clone repository or update it to origin/``remote.branch``
|
||||
|
||||
Args:
|
||||
sources_dir(Path): local path to fetch
|
||||
remote(Optional[RemoteSource]): remote target (from where to fetch)
|
||||
remote(RemoteSource | None): remote target (from where to fetch)
|
||||
"""
|
||||
instance = Sources()
|
||||
# local directory exists and there is .git directory
|
||||
@ -127,14 +126,14 @@ class Sources(LazyLogging):
|
||||
cwd=sources_dir, logger=instance.logger)
|
||||
|
||||
@staticmethod
|
||||
def load(sources_dir: Path, package: Package, patches: List[PkgbuildPatch], paths: RepositoryPaths) -> None:
|
||||
def load(sources_dir: Path, package: Package, patches: list[PkgbuildPatch], paths: RepositoryPaths) -> None:
|
||||
"""
|
||||
fetch sources from remote and apply patches
|
||||
|
||||
Args:
|
||||
sources_dir(Path): local path to fetch
|
||||
package(Package): package definitions
|
||||
patches(List[PkgbuildPatch]): optional patch to be applied
|
||||
patches(list[PkgbuildPatch]): optional patch to be applied
|
||||
paths(RepositoryPaths): repository paths instance
|
||||
"""
|
||||
instance = Sources()
|
||||
@ -165,7 +164,7 @@ class Sources(LazyLogging):
|
||||
return f"{diff}\n" # otherwise, patch will be broken
|
||||
|
||||
@staticmethod
|
||||
def push(sources_dir: Path, remote: RemoteSource, *pattern: str, commit_author: Optional[str] = None) -> None:
|
||||
def push(sources_dir: Path, remote: RemoteSource, *pattern: str, commit_author: str | None = None) -> None:
|
||||
"""
|
||||
commit selected changes and push files to the remote repository
|
||||
|
||||
@ -173,7 +172,7 @@ class Sources(LazyLogging):
|
||||
sources_dir(Path): local path to git repository
|
||||
remote(RemoteSource): remote target, branch and url
|
||||
*pattern(str): glob patterns
|
||||
commit_author(Optional[str], optional): commit author in form of git config (i.e. ``user <user@host>``)
|
||||
commit_author(str | None, optional): commit author in form of git config (i.e. ``user <user@host>``)
|
||||
(Default value = None)
|
||||
"""
|
||||
instance = Sources()
|
||||
@ -192,7 +191,7 @@ class Sources(LazyLogging):
|
||||
--intent-to-add git flag (Default value = False)
|
||||
"""
|
||||
# glob directory to find files which match the specified patterns
|
||||
found_files: List[Path] = []
|
||||
found_files: list[Path] = []
|
||||
for glob in pattern:
|
||||
found_files.extend(sources_dir.glob(glob))
|
||||
if not found_files:
|
||||
@ -203,15 +202,15 @@ class Sources(LazyLogging):
|
||||
Sources._check_output("git", "add", *args, *[str(fn.relative_to(sources_dir)) for fn in found_files],
|
||||
cwd=sources_dir, logger=self.logger)
|
||||
|
||||
def commit(self, sources_dir: Path, message: Optional[str] = None, author: Optional[str] = None) -> None:
|
||||
def commit(self, sources_dir: Path, message: str | None = None, author: str | None = None) -> None:
|
||||
"""
|
||||
commit changes
|
||||
|
||||
Args:
|
||||
sources_dir(Path): local path to git repository
|
||||
message(Optional[str], optional): optional commit message if any. If none set, message will be generated
|
||||
message(str | None, optional): optional commit message if any. If none set, message will be generated
|
||||
according to the current timestamp (Default value = None)
|
||||
author(Optional[str], optional): optional commit author if any (Default value = None)
|
||||
author(str | None, optional): optional commit author if any (Default value = None)
|
||||
"""
|
||||
if message is None:
|
||||
message = f"Autogenerated commit at {utcnow()}"
|
||||
|
@ -18,7 +18,6 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
from pathlib import Path
|
||||
from typing import List
|
||||
|
||||
from ahriman.core.build_tools.sources import Sources
|
||||
from ahriman.core.configuration import Configuration
|
||||
@ -60,7 +59,7 @@ class Task(LazyLogging):
|
||||
self.makepkg_flags = configuration.getlist("build", "makepkg_flags", fallback=[])
|
||||
self.makechrootpkg_flags = configuration.getlist("build", "makechrootpkg_flags", fallback=[])
|
||||
|
||||
def build(self, sources_dir: Path) -> List[Path]:
|
||||
def build(self, sources_dir: Path) -> list[Path]:
|
||||
"""
|
||||
run package build
|
||||
|
||||
@ -68,7 +67,7 @@ class Task(LazyLogging):
|
||||
sources_dir(Path): path to where sources are
|
||||
|
||||
Returns:
|
||||
List[Path]: paths of produced packages
|
||||
list[Path]: paths of produced packages
|
||||
"""
|
||||
command = [self.build_command, "-r", str(self.paths.chroot)]
|
||||
command.extend(self.archbuild_flags)
|
||||
|
@ -23,8 +23,9 @@ import configparser
|
||||
import shlex
|
||||
import sys
|
||||
|
||||
from collections.abc import Callable
|
||||
from pathlib import Path
|
||||
from typing import Any, Callable, Dict, List, Optional, Tuple, Type
|
||||
from typing import Any
|
||||
|
||||
from ahriman.core.exceptions import InitializeError
|
||||
from ahriman.models.repository_paths import RepositoryPaths
|
||||
@ -35,11 +36,11 @@ class Configuration(configparser.RawConfigParser):
|
||||
extension for built-in configuration parser
|
||||
|
||||
Attributes:
|
||||
ARCHITECTURE_SPECIFIC_SECTIONS(List[str]): (class attribute) known sections which can be architecture specific.
|
||||
ARCHITECTURE_SPECIFIC_SECTIONS(list[str]): (class attribute) known sections which can be architecture specific.
|
||||
Required by dump and merging functions
|
||||
SYSTEM_CONFIGURATION_PATH(Path): (class attribute) default system configuration path distributed by package
|
||||
architecture(Optional[str]): repository architecture
|
||||
path(Optional[Path]): path to root configuration file
|
||||
architecture(str | None): repository architecture
|
||||
path(Path | None): path to root configuration file
|
||||
|
||||
Examples:
|
||||
Configuration class provides additional method in order to handle application configuration. Since this class is
|
||||
@ -63,7 +64,7 @@ class Configuration(configparser.RawConfigParser):
|
||||
|
||||
ARCHITECTURE_SPECIFIC_SECTIONS = ["alpm", "build", "sign", "web"]
|
||||
SYSTEM_CONFIGURATION_PATH = Path(sys.prefix) / "share" / "ahriman" / "settings" / "ahriman.ini"
|
||||
converters: Dict[str, Callable[[str], Any]] # typing guard
|
||||
converters: dict[str, Callable[[str], Any]] # typing guard
|
||||
|
||||
def __init__(self, allow_no_value: bool = False) -> None:
|
||||
"""
|
||||
@ -77,8 +78,8 @@ class Configuration(configparser.RawConfigParser):
|
||||
"list": shlex.split,
|
||||
"path": self._convert_path,
|
||||
})
|
||||
self.architecture: Optional[str] = None
|
||||
self.path: Optional[Path] = None
|
||||
self.architecture: str | None = None
|
||||
self.path: Path | None = None
|
||||
|
||||
@property
|
||||
def include(self) -> Path:
|
||||
@ -112,7 +113,7 @@ class Configuration(configparser.RawConfigParser):
|
||||
return RepositoryPaths(self.getpath("repository", "root"), architecture)
|
||||
|
||||
@classmethod
|
||||
def from_path(cls: Type[Configuration], path: Path, architecture: str) -> Configuration:
|
||||
def from_path(cls: type[Configuration], path: Path, architecture: str) -> Configuration:
|
||||
"""
|
||||
constructor with full object initialization
|
||||
|
||||
@ -157,12 +158,12 @@ class Configuration(configparser.RawConfigParser):
|
||||
return path
|
||||
return self.path.parent / path
|
||||
|
||||
def check_loaded(self) -> Tuple[Path, str]:
|
||||
def check_loaded(self) -> tuple[Path, str]:
|
||||
"""
|
||||
check if service was actually loaded
|
||||
|
||||
Returns:
|
||||
Tuple[Path, str]: configuration root path and architecture if loaded
|
||||
tuple[Path, str]: configuration root path and architecture if loaded
|
||||
|
||||
Raises:
|
||||
InitializeError: in case if architecture and/or path are not set
|
||||
@ -171,12 +172,12 @@ class Configuration(configparser.RawConfigParser):
|
||||
raise InitializeError("Configuration path and/or architecture are not set")
|
||||
return self.path, self.architecture
|
||||
|
||||
def dump(self) -> Dict[str, Dict[str, str]]:
|
||||
def dump(self) -> dict[str, dict[str, str]]:
|
||||
"""
|
||||
dump configuration to dictionary
|
||||
|
||||
Returns:
|
||||
Dict[str, Dict[str, str]]: configuration dump for specific architecture
|
||||
dict[str, dict[str, str]]: configuration dump for specific architecture
|
||||
"""
|
||||
return {
|
||||
section: dict(self[section])
|
||||
@ -185,11 +186,11 @@ class Configuration(configparser.RawConfigParser):
|
||||
|
||||
# pylint and mypy are too stupid to find these methods
|
||||
# pylint: disable=missing-function-docstring,multiple-statements,unused-argument
|
||||
def getlist(self, *args: Any, **kwargs: Any) -> List[str]: ... # type: ignore
|
||||
def getlist(self, *args: Any, **kwargs: Any) -> list[str]: ... # type: ignore
|
||||
|
||||
def getpath(self, *args: Any, **kwargs: Any) -> Path: ... # type: ignore
|
||||
|
||||
def gettype(self, section: str, architecture: str, *, fallback: Optional[str] = None) -> Tuple[str, str]:
|
||||
def gettype(self, section: str, architecture: str, *, fallback: str | None = None) -> tuple[str, str]:
|
||||
"""
|
||||
get type variable with fallback to old logic. Despite the fact that it has same semantics as other get* methods,
|
||||
but it has different argument list
|
||||
@ -197,11 +198,11 @@ class Configuration(configparser.RawConfigParser):
|
||||
Args:
|
||||
section(str): section name
|
||||
architecture(str): repository architecture
|
||||
fallback(Optional[str], optional): optional fallback type if any. If set, second element of the tuple will
|
||||
fallback(str | None, optional): optional fallback type if any. If set, second element of the tuple will
|
||||
be always set to this value (Default value = None)
|
||||
|
||||
Returns:
|
||||
Tuple[str, str]: section name and found type name
|
||||
tuple[str, str]: section name and found type name
|
||||
|
||||
Raises:
|
||||
configparser.NoSectionError: in case if no section found
|
||||
|
@ -17,13 +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/>.
|
||||
#
|
||||
from typing import Any, Dict
|
||||
from typing import Any
|
||||
|
||||
|
||||
__all__ = ["CONFIGURATION_SCHEMA", "ConfigurationSchema"]
|
||||
|
||||
|
||||
ConfigurationSchema = Dict[str, Dict[str, Any]]
|
||||
ConfigurationSchema = dict[str, dict[str, Any]]
|
||||
|
||||
|
||||
CONFIGURATION_SCHEMA: ConfigurationSchema = {
|
||||
|
@ -21,7 +21,7 @@ import ipaddress
|
||||
|
||||
from cerberus import TypeDefinition, Validator as RootValidator # type: ignore
|
||||
from pathlib import Path
|
||||
from typing import Any, List
|
||||
from typing import Any
|
||||
from urllib.parse import urlparse
|
||||
|
||||
from ahriman.core.configuration import Configuration
|
||||
@ -90,7 +90,7 @@ class Validator(RootValidator):
|
||||
del self
|
||||
return int(value)
|
||||
|
||||
def _normalize_coerce_list(self, value: str) -> List[str]:
|
||||
def _normalize_coerce_list(self, value: str) -> list[str]:
|
||||
"""
|
||||
extract string list from string value
|
||||
|
||||
@ -98,17 +98,17 @@ class Validator(RootValidator):
|
||||
value(str): converting value
|
||||
|
||||
Returns:
|
||||
List[str]: value converted to string list instance according to configuration rules
|
||||
list[str]: value converted to string list instance according to configuration rules
|
||||
"""
|
||||
converted: List[str] = self.configuration.converters["list"](value)
|
||||
converted: list[str] = self.configuration.converters["list"](value)
|
||||
return converted
|
||||
|
||||
def _validate_is_ip_address(self, constraint: List[str], field: str, value: str) -> None:
|
||||
def _validate_is_ip_address(self, constraint: list[str], field: str, value: str) -> None:
|
||||
"""
|
||||
check if the specified value is valid ip address
|
||||
|
||||
Args:
|
||||
constraint(List[str]): optional list of allowed special words (e.g. ``localhost``)
|
||||
constraint(list[str]): optional list of allowed special words (e.g. ``localhost``)
|
||||
field(str): field name to be checked
|
||||
value(Path): value to be checked
|
||||
|
||||
@ -123,12 +123,12 @@ class Validator(RootValidator):
|
||||
except ValueError:
|
||||
self._error(field, f"Value {value} must be valid IP address")
|
||||
|
||||
def _validate_is_url(self, constraint: List[str], field: str, value: str) -> None:
|
||||
def _validate_is_url(self, constraint: list[str], field: str, value: str) -> None:
|
||||
"""
|
||||
check if the specified value is a valid url
|
||||
|
||||
Args:
|
||||
constraint(List[str]): optional list of supported schemas. If empty, no schema validation will be performed
|
||||
constraint(list[str]): optional list of supported schemas. If empty, no schema validation will be performed
|
||||
field(str): field name to be checked
|
||||
value(str): value to be checked
|
||||
|
||||
|
@ -17,11 +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 collections.abc import Callable
|
||||
from importlib import import_module
|
||||
from pathlib import Path
|
||||
from pkgutil import iter_modules
|
||||
from sqlite3 import Connection, Cursor
|
||||
from typing import Callable, List
|
||||
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.log import LazyLogging
|
||||
@ -83,22 +83,22 @@ class Migrations(LazyLogging):
|
||||
"data migration %s at index %s has been performed",
|
||||
migration.name, migration.index)
|
||||
|
||||
def migrations(self) -> List[Migration]:
|
||||
def migrations(self) -> list[Migration]:
|
||||
"""
|
||||
extract all migrations from the current package
|
||||
idea comes from https://julienharbulot.com/python-dynamical-import.html
|
||||
|
||||
Returns:
|
||||
List[Migration]: list of found migrations
|
||||
list[Migration]: list of found migrations
|
||||
"""
|
||||
migrations: List[Migration] = []
|
||||
migrations: list[Migration] = []
|
||||
package_dir = Path(__file__).resolve().parent
|
||||
modules = [module_name for (_, module_name, _) in iter_modules([str(package_dir)])]
|
||||
|
||||
for index, module_name in enumerate(sorted(modules)):
|
||||
module = import_module(f"{__name__}.{module_name}")
|
||||
|
||||
steps: List[str] = getattr(module, "steps", [])
|
||||
steps: list[str] = getattr(module, "steps", [])
|
||||
self.logger.debug("found migration %s at index %s with steps count %s", module_name, index, len(steps))
|
||||
|
||||
migrate_data: Callable[[Connection, Configuration], None] = \
|
||||
|
@ -18,7 +18,6 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
from sqlite3 import Connection
|
||||
from typing import List, Optional
|
||||
|
||||
from ahriman.core.database.operations import Operations
|
||||
from ahriman.models.user import User
|
||||
@ -30,7 +29,7 @@ class AuthOperations(Operations):
|
||||
authorization operations
|
||||
"""
|
||||
|
||||
def user_get(self, username: str) -> Optional[User]:
|
||||
def user_get(self, username: str) -> User | None:
|
||||
"""
|
||||
get user by username
|
||||
|
||||
@ -38,25 +37,25 @@ class AuthOperations(Operations):
|
||||
username(str): username
|
||||
|
||||
Returns:
|
||||
Optional[User]: user if it was found
|
||||
User | None: user if it was found
|
||||
"""
|
||||
return next(iter(self.user_list(username, None)), None)
|
||||
|
||||
def user_list(self, username: Optional[str], access: Optional[UserAccess]) -> List[User]:
|
||||
def user_list(self, username: str | None, access: UserAccess | None) -> list[User]:
|
||||
"""
|
||||
get users by filter
|
||||
|
||||
Args:
|
||||
username(Optional[str]): optional filter by username
|
||||
access(Optional[UserAccess]): optional filter by role
|
||||
username(str | None): optional filter by username
|
||||
access(UserAccess | None): optional filter by role
|
||||
|
||||
Returns:
|
||||
List[User]: list of users who match criteria
|
||||
list[User]: list of users who match criteria
|
||||
"""
|
||||
username_filter = username.lower() if username is not None else username
|
||||
access_filter = access.value if access is not None else access
|
||||
|
||||
def run(connection: Connection) -> List[User]:
|
||||
def run(connection: Connection) -> list[User]:
|
||||
return [
|
||||
User(username=cursor["username"], password=cursor["password"], access=UserAccess(cursor["access"]))
|
||||
for cursor in connection.execute(
|
||||
|
@ -18,7 +18,6 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
from sqlite3 import Connection
|
||||
from typing import List, Optional
|
||||
|
||||
from ahriman.core.database.operations import Operations
|
||||
from ahriman.models.package import Package
|
||||
@ -29,12 +28,12 @@ class BuildOperations(Operations):
|
||||
operations for build queue functions
|
||||
"""
|
||||
|
||||
def build_queue_clear(self, package_base: Optional[str]) -> None:
|
||||
def build_queue_clear(self, package_base: str | None) -> None:
|
||||
"""
|
||||
remove packages from build queue
|
||||
|
||||
Args:
|
||||
package_base(Optional[str]): optional filter by package base
|
||||
package_base(str | None): optional filter by package base
|
||||
"""
|
||||
def run(connection: Connection) -> None:
|
||||
connection.execute(
|
||||
@ -46,14 +45,14 @@ class BuildOperations(Operations):
|
||||
|
||||
return self.with_connection(run, commit=True)
|
||||
|
||||
def build_queue_get(self) -> List[Package]:
|
||||
def build_queue_get(self) -> list[Package]:
|
||||
"""
|
||||
retrieve packages from build queue
|
||||
|
||||
Return:
|
||||
List[Package]: list of packages to be built
|
||||
list[Package]: list of packages to be built
|
||||
"""
|
||||
def run(connection: Connection) -> List[Package]:
|
||||
def run(connection: Connection) -> list[Package]:
|
||||
return [
|
||||
Package.from_json(row["properties"])
|
||||
for row in connection.execute("""select * from build_queue""")
|
||||
|
@ -18,7 +18,6 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
from sqlite3 import Connection
|
||||
from typing import List, Optional
|
||||
|
||||
from ahriman.core.database.operations import Operations
|
||||
from ahriman.core.util import pretty_datetime
|
||||
@ -40,7 +39,7 @@ class LogsOperations(Operations):
|
||||
Return:
|
||||
str: full package log
|
||||
"""
|
||||
def run(connection: Connection) -> List[str]:
|
||||
def run(connection: Connection) -> list[str]:
|
||||
return [
|
||||
f"""[{pretty_datetime(row["created"])}] {row["record"]}"""
|
||||
for row in connection.execute(
|
||||
@ -81,13 +80,13 @@ class LogsOperations(Operations):
|
||||
|
||||
return self.with_connection(run, commit=True)
|
||||
|
||||
def logs_remove(self, package_base: str, current_process_id: Optional[int]) -> None:
|
||||
def logs_remove(self, package_base: str, current_process_id: int | None) -> None:
|
||||
"""
|
||||
remove log records for the specified package
|
||||
|
||||
Args:
|
||||
package_base(str): package base to remove logs
|
||||
current_process_id(Optional[int]): current process id. If set it will remove only logs belonging to another
|
||||
current_process_id(int | None): current process id. If set it will remove only logs belonging to another
|
||||
process
|
||||
"""
|
||||
def run(connection: Connection) -> None:
|
||||
|
@ -19,8 +19,9 @@
|
||||
#
|
||||
import sqlite3
|
||||
|
||||
from collections.abc import Callable
|
||||
from pathlib import Path
|
||||
from typing import Any, Callable, Dict, Tuple, TypeVar
|
||||
from typing import Any, TypeVar
|
||||
|
||||
from ahriman.core.log import LazyLogging
|
||||
|
||||
@ -46,16 +47,16 @@ class Operations(LazyLogging):
|
||||
self.path = path
|
||||
|
||||
@staticmethod
|
||||
def factory(cursor: sqlite3.Cursor, row: Tuple[Any, ...]) -> Dict[str, Any]:
|
||||
def factory(cursor: sqlite3.Cursor, row: tuple[Any, ...]) -> dict[str, Any]:
|
||||
"""
|
||||
dictionary factory based on official documentation
|
||||
|
||||
Args:
|
||||
cursor(Cursor): cursor descriptor
|
||||
row(Tuple[Any, ...]): fetched row
|
||||
row(tuple[Any, ...]): fetched row
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: row converted to dictionary
|
||||
dict[str, Any]: row converted to dictionary
|
||||
"""
|
||||
result = {}
|
||||
for index, column in enumerate(cursor.description):
|
||||
|
@ -17,8 +17,8 @@
|
||||
# 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 collections.abc import Generator, Iterable
|
||||
from sqlite3 import Connection
|
||||
from typing import Dict, Generator, Iterable, List, Tuple
|
||||
|
||||
from ahriman.core.database.operations import Operations
|
||||
from ahriman.models.build_status import BuildStatus
|
||||
@ -148,7 +148,7 @@ class PackageOperations(Operations):
|
||||
{"package_base": package_base, "status": status.status.value, "last_updated": status.timestamp})
|
||||
|
||||
@staticmethod
|
||||
def _packages_get_select_package_bases(connection: Connection) -> Dict[str, Package]:
|
||||
def _packages_get_select_package_bases(connection: Connection) -> dict[str, Package]:
|
||||
"""
|
||||
select package bases from the table
|
||||
|
||||
@ -156,7 +156,7 @@ class PackageOperations(Operations):
|
||||
connection(Connection): database connection
|
||||
|
||||
Returns:
|
||||
Dict[str, Package]: map of the package base to its descriptor (without packages themselves)
|
||||
dict[str, Package]: map of the package base to its descriptor (without packages themselves)
|
||||
"""
|
||||
return {
|
||||
row["package_base"]: Package(
|
||||
@ -168,16 +168,16 @@ class PackageOperations(Operations):
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def _packages_get_select_packages(connection: Connection, packages: Dict[str, Package]) -> Dict[str, Package]:
|
||||
def _packages_get_select_packages(connection: Connection, packages: dict[str, Package]) -> dict[str, Package]:
|
||||
"""
|
||||
select packages from the table
|
||||
|
||||
Args:
|
||||
connection(Connection): database connection
|
||||
packages(Dict[str, Package]): packages descriptor map
|
||||
packages(dict[str, Package]): packages descriptor map
|
||||
|
||||
Returns:
|
||||
Dict[str, Package]: map of the package base to its descriptor including individual packages
|
||||
dict[str, Package]: map of the package base to its descriptor including individual packages
|
||||
"""
|
||||
for row in connection.execute("""select * from packages"""):
|
||||
if row["package_base"] not in packages:
|
||||
@ -186,7 +186,7 @@ class PackageOperations(Operations):
|
||||
return packages
|
||||
|
||||
@staticmethod
|
||||
def _packages_get_select_statuses(connection: Connection) -> Dict[str, BuildStatus]:
|
||||
def _packages_get_select_statuses(connection: Connection) -> dict[str, BuildStatus]:
|
||||
"""
|
||||
select package build statuses from the table
|
||||
|
||||
@ -194,7 +194,7 @@ class PackageOperations(Operations):
|
||||
connection(Connection): database connection
|
||||
|
||||
Returns:
|
||||
Dict[str, BuildStatus]: map of the package base to its status
|
||||
dict[str, BuildStatus]: map of the package base to its status
|
||||
"""
|
||||
return {
|
||||
row["package_base"]: BuildStatus.from_json({"status": row["status"], "timestamp": row["last_updated"]})
|
||||
@ -230,14 +230,14 @@ class PackageOperations(Operations):
|
||||
|
||||
return self.with_connection(run, commit=True)
|
||||
|
||||
def packages_get(self) -> List[Tuple[Package, BuildStatus]]:
|
||||
def packages_get(self) -> list[tuple[Package, BuildStatus]]:
|
||||
"""
|
||||
get package list and their build statuses from database
|
||||
|
||||
Return:
|
||||
List[Tuple[Package, BuildStatus]]: list of package properties and their statuses
|
||||
list[tuple[Package, BuildStatus]]: list of package properties and their statuses
|
||||
"""
|
||||
def run(connection: Connection) -> Generator[Tuple[Package, BuildStatus], None, None]:
|
||||
def run(connection: Connection) -> Generator[tuple[Package, BuildStatus], None, None]:
|
||||
packages = self._packages_get_select_package_bases(connection)
|
||||
statuses = self._packages_get_select_statuses(connection)
|
||||
for package_base, package in self._packages_get_select_packages(connection, packages).items():
|
||||
@ -256,12 +256,12 @@ class PackageOperations(Operations):
|
||||
lambda connection: self._package_update_insert_base(connection, package),
|
||||
commit=True)
|
||||
|
||||
def remotes_get(self) -> Dict[str, RemoteSource]:
|
||||
def remotes_get(self) -> dict[str, RemoteSource]:
|
||||
"""
|
||||
get packages remotes based on current settings
|
||||
|
||||
Returns:
|
||||
Dict[str, RemoteSource]: map of package base to its remote sources
|
||||
dict[str, RemoteSource]: map of package base to its remote sources
|
||||
"""
|
||||
packages = self.with_connection(self._packages_get_select_package_bases)
|
||||
return {
|
||||
|
@ -20,7 +20,6 @@
|
||||
from collections import defaultdict
|
||||
|
||||
from sqlite3 import Connection
|
||||
from typing import Dict, List, Optional, Tuple
|
||||
|
||||
from ahriman.core.database.operations import Operations
|
||||
from ahriman.models.pkgbuild_patch import PkgbuildPatch
|
||||
@ -31,7 +30,7 @@ class PatchOperations(Operations):
|
||||
operations for patches
|
||||
"""
|
||||
|
||||
def patches_get(self, package_base: str) -> List[PkgbuildPatch]:
|
||||
def patches_get(self, package_base: str) -> list[PkgbuildPatch]:
|
||||
"""
|
||||
retrieve patches for the package
|
||||
|
||||
@ -39,7 +38,7 @@ class PatchOperations(Operations):
|
||||
package_base(str): package base to search for patches
|
||||
|
||||
Returns:
|
||||
List[PkgbuildPatch]: plain text patch for the package
|
||||
list[PkgbuildPatch]: plain text patch for the package
|
||||
"""
|
||||
return self.patches_list(package_base, []).get(package_base, [])
|
||||
|
||||
@ -65,18 +64,18 @@ class PatchOperations(Operations):
|
||||
|
||||
return self.with_connection(run, commit=True)
|
||||
|
||||
def patches_list(self, package_base: Optional[str], variables: List[str]) -> Dict[str, List[PkgbuildPatch]]:
|
||||
def patches_list(self, package_base: str | None, variables: list[str]) -> dict[str, list[PkgbuildPatch]]:
|
||||
"""
|
||||
extract all patches
|
||||
|
||||
Args:
|
||||
package_base(Optional[str]): optional filter by package base
|
||||
variables(List[str]): extract patches only for specified PKGBUILD variables
|
||||
package_base(str | None): optional filter by package base
|
||||
variables(list[str]): extract patches only for specified PKGBUILD variables
|
||||
|
||||
Returns:
|
||||
Dict[str, List[PkgbuildPatch]]: map of package base to patch content
|
||||
dict[str, list[PkgbuildPatch]]: map of package base to patch content
|
||||
"""
|
||||
def run(connection: Connection) -> List[Tuple[str, PkgbuildPatch]]:
|
||||
def run(connection: Connection) -> list[tuple[str, PkgbuildPatch]]:
|
||||
return [
|
||||
(cursor["package_base"], PkgbuildPatch(cursor["variable"], cursor["patch"]))
|
||||
for cursor in connection.execute(
|
||||
@ -85,20 +84,20 @@ class PatchOperations(Operations):
|
||||
]
|
||||
|
||||
# we could use itertools & operator but why?
|
||||
patches: Dict[str, List[PkgbuildPatch]] = defaultdict(list)
|
||||
patches: dict[str, list[PkgbuildPatch]] = defaultdict(list)
|
||||
for package, patch in self.with_connection(run):
|
||||
if variables and patch.key not in variables:
|
||||
continue
|
||||
patches[package].append(patch)
|
||||
return dict(patches)
|
||||
|
||||
def patches_remove(self, package_base: str, variables: List[str]) -> None:
|
||||
def patches_remove(self, package_base: str, variables: list[str]) -> None:
|
||||
"""
|
||||
remove patch set
|
||||
|
||||
Args:
|
||||
package_base(str): package base to clear patches
|
||||
variables(List[str]): remove patches only for specified PKGBUILD variables
|
||||
variables(list[str]): remove patches only for specified PKGBUILD variables
|
||||
"""
|
||||
def run_many(connection: Connection) -> None:
|
||||
connection.executemany(
|
||||
|
@ -23,7 +23,6 @@ import json
|
||||
import sqlite3
|
||||
|
||||
from pathlib import Path
|
||||
from typing import Type
|
||||
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.database.migrations import Migrations
|
||||
@ -47,7 +46,7 @@ class SQLite(AuthOperations, BuildOperations, LogsOperations, PackageOperations,
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def load(cls: Type[SQLite], configuration: Configuration) -> SQLite:
|
||||
def load(cls: type[SQLite], configuration: Configuration) -> SQLite:
|
||||
"""
|
||||
construct instance from configuration
|
||||
|
||||
|
@ -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/>.
|
||||
#
|
||||
from typing import List
|
||||
|
||||
from ahriman.core.formatters import StringPrinter
|
||||
from ahriman.core.util import pretty_datetime
|
||||
from ahriman.models.aur_package import AURPackage
|
||||
@ -43,12 +41,12 @@ class AurPrinter(StringPrinter):
|
||||
StringPrinter.__init__(self, f"{package.name} {package.version} ({package.num_votes})")
|
||||
self.package = package
|
||||
|
||||
def properties(self) -> List[Property]:
|
||||
def properties(self) -> list[Property]:
|
||||
"""
|
||||
convert content into printable data
|
||||
|
||||
Returns:
|
||||
List[Property]: list of content properties
|
||||
list[Property]: list of content properties
|
||||
"""
|
||||
return [
|
||||
Property("Package base", self.package.package_base),
|
||||
|
@ -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/>.
|
||||
#
|
||||
from typing import Dict, List
|
||||
|
||||
from ahriman.core.formatters import StringPrinter
|
||||
from ahriman.models.property import Property
|
||||
|
||||
@ -28,9 +26,9 @@ class ConfigurationPrinter(StringPrinter):
|
||||
print content of the configuration section
|
||||
|
||||
Attributes:
|
||||
HIDE_KEYS(List[str]): (class attribute) hide values for mentioned keys. This list must be used in order to hide
|
||||
HIDE_KEYS(list[str]): (class attribute) hide values for mentioned keys. This list must be used in order to hide
|
||||
passwords from outputs
|
||||
values(Dict[str, str]): configuration values dictionary
|
||||
values(dict[str, str]): configuration values dictionary
|
||||
"""
|
||||
|
||||
HIDE_KEYS = [
|
||||
@ -42,23 +40,23 @@ class ConfigurationPrinter(StringPrinter):
|
||||
"secret_key", # aws secret key
|
||||
]
|
||||
|
||||
def __init__(self, section: str, values: Dict[str, str]) -> None:
|
||||
def __init__(self, section: str, values: dict[str, str]) -> None:
|
||||
"""
|
||||
default constructor
|
||||
|
||||
Args:
|
||||
section(str): section name
|
||||
values(Dict[str, str]): configuration values dictionary
|
||||
values(dict[str, str]): configuration values dictionary
|
||||
"""
|
||||
StringPrinter.__init__(self, f"[{section}]")
|
||||
self.values = values
|
||||
|
||||
def properties(self) -> List[Property]:
|
||||
def properties(self) -> list[Property]:
|
||||
"""
|
||||
convert content into printable data
|
||||
|
||||
Returns:
|
||||
List[Property]: list of content properties
|
||||
list[Property]: list of content properties
|
||||
"""
|
||||
return [
|
||||
Property(key, value, is_required=key not in self.HIDE_KEYS)
|
||||
|
@ -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/>.
|
||||
#
|
||||
from typing import List
|
||||
|
||||
from ahriman.core.formatters import StringPrinter
|
||||
from ahriman.models.build_status import BuildStatus
|
||||
from ahriman.models.package import Package
|
||||
@ -46,12 +44,12 @@ class PackagePrinter(StringPrinter):
|
||||
self.package = package
|
||||
self.status = status
|
||||
|
||||
def properties(self) -> List[Property]:
|
||||
def properties(self) -> list[Property]:
|
||||
"""
|
||||
convert content into printable data
|
||||
|
||||
Returns:
|
||||
List[Property]: list of content properties
|
||||
list[Property]: list of content properties
|
||||
"""
|
||||
return [
|
||||
Property("Version", self.package.version, is_required=True),
|
||||
|
@ -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/>.
|
||||
#
|
||||
from typing import List
|
||||
|
||||
from ahriman.core.formatters import StringPrinter
|
||||
from ahriman.models.pkgbuild_patch import PkgbuildPatch
|
||||
from ahriman.models.property import Property
|
||||
@ -29,26 +27,26 @@ class PatchPrinter(StringPrinter):
|
||||
print content of the PKGBUILD patch
|
||||
|
||||
Attributes:
|
||||
patches(List[PkgbuildPatch]): PKGBUILD patch object
|
||||
patches(list[PkgbuildPatch]): PKGBUILD patch object
|
||||
"""
|
||||
|
||||
def __init__(self, package_base: str, patches: List[PkgbuildPatch]) -> None:
|
||||
def __init__(self, package_base: str, patches: list[PkgbuildPatch]) -> None:
|
||||
"""
|
||||
default constructor
|
||||
|
||||
Args:
|
||||
package_base(str): package base
|
||||
patches(List[PkgbuildPatch]): PKGBUILD patch object
|
||||
patches(list[PkgbuildPatch]): PKGBUILD patch object
|
||||
"""
|
||||
StringPrinter.__init__(self, package_base)
|
||||
self.patches = patches
|
||||
|
||||
def properties(self) -> List[Property]:
|
||||
def properties(self) -> list[Property]:
|
||||
"""
|
||||
convert content into printable data
|
||||
|
||||
Returns:
|
||||
List[Property]: list of content properties
|
||||
list[Property]: list of content properties
|
||||
"""
|
||||
return [
|
||||
Property(patch.key or "Full source diff", patch.value, is_required=True)
|
||||
|
@ -17,7 +17,7 @@
|
||||
# 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 typing import Callable, List, Optional
|
||||
from collections.abc import Callable
|
||||
|
||||
from ahriman.models.property import Property
|
||||
|
||||
@ -44,19 +44,19 @@ class Printer:
|
||||
indent = "\t" * prop.indent
|
||||
log_fn(f"{indent}{prop.name}{separator}{prop.value}")
|
||||
|
||||
def properties(self) -> List[Property]:
|
||||
def properties(self) -> list[Property]:
|
||||
"""
|
||||
convert content into printable data
|
||||
|
||||
Returns:
|
||||
List[Property]: list of content properties
|
||||
list[Property]: list of content properties
|
||||
"""
|
||||
return []
|
||||
|
||||
def title(self) -> Optional[str]:
|
||||
def title(self) -> str | None:
|
||||
"""
|
||||
generate entry title from content
|
||||
|
||||
Returns:
|
||||
Optional[str]: content title if it can be generated and None otherwise
|
||||
str | None: content title if it can be generated and None otherwise
|
||||
"""
|
||||
|
@ -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/>.
|
||||
#
|
||||
from typing import Optional
|
||||
|
||||
from ahriman.core.formatters import Printer
|
||||
|
||||
|
||||
@ -39,11 +37,11 @@ class StringPrinter(Printer):
|
||||
"""
|
||||
self.content = content
|
||||
|
||||
def title(self) -> Optional[str]:
|
||||
def title(self) -> str | None:
|
||||
"""
|
||||
generate entry title from content
|
||||
|
||||
Returns:
|
||||
Optional[str]: content title if it can be generated and None otherwise
|
||||
str | None: content title if it can be generated and None otherwise
|
||||
"""
|
||||
return self.content
|
||||
|
@ -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/>.
|
||||
#
|
||||
from typing import Iterable, List
|
||||
|
||||
from ahriman.core.formatters import StringPrinter
|
||||
from ahriman.models.package import Package
|
||||
from ahriman.models.property import Property
|
||||
@ -29,25 +27,25 @@ class TreePrinter(StringPrinter):
|
||||
print content of the package tree level
|
||||
|
||||
Attributes:
|
||||
packages(Iterable[Package]): packages which belong to this level
|
||||
packages(list[Package]): packages which belong to this level
|
||||
"""
|
||||
|
||||
def __init__(self, level: int, packages: Iterable[Package]) -> None:
|
||||
def __init__(self, level: int, packages: list[Package]) -> None:
|
||||
"""
|
||||
default constructor
|
||||
|
||||
Args:
|
||||
level(int): dependencies tree level
|
||||
packages(Iterable[Package]): packages which belong to this level
|
||||
packages(list[Package]): packages which belong to this level
|
||||
"""
|
||||
StringPrinter.__init__(self, f"level {level}")
|
||||
self.packages = packages
|
||||
|
||||
def properties(self) -> List[Property]:
|
||||
def properties(self) -> list[Property]:
|
||||
"""
|
||||
convert content into printable data
|
||||
|
||||
Returns:
|
||||
List[Property]: list of content properties
|
||||
list[Property]: list of content properties
|
||||
"""
|
||||
return [Property(package.base, package.version, is_required=True) for package in self.packages]
|
||||
|
@ -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/>.
|
||||
#
|
||||
from typing import List, Optional
|
||||
|
||||
from ahriman.core.formatters import StringPrinter
|
||||
from ahriman.models.package import Package
|
||||
from ahriman.models.property import Property
|
||||
@ -30,26 +28,26 @@ class UpdatePrinter(StringPrinter):
|
||||
|
||||
Attributes:
|
||||
package(Package): remote (new) package object
|
||||
local_version(Optional[str]): local version of the package if any
|
||||
local_version(str | None): local version of the package if any
|
||||
"""
|
||||
|
||||
def __init__(self, remote: Package, local_version: Optional[str]) -> None:
|
||||
def __init__(self, remote: Package, local_version: str | None) -> None:
|
||||
"""
|
||||
default constructor
|
||||
|
||||
Args:
|
||||
remote(Package): remote (new) package object
|
||||
local_version(Optional[str]): local version of the package if any
|
||||
local_version(str | None): local version of the package if any
|
||||
"""
|
||||
StringPrinter.__init__(self, remote.base)
|
||||
self.package = remote
|
||||
self.local_version = local_version or "N/A"
|
||||
|
||||
def properties(self) -> List[Property]:
|
||||
def properties(self) -> list[Property]:
|
||||
"""
|
||||
convert content into printable data
|
||||
|
||||
Returns:
|
||||
List[Property]: list of content properties
|
||||
list[Property]: list of content properties
|
||||
"""
|
||||
return [Property(self.local_version, self.package.version, is_required=True)]
|
||||
|
@ -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/>.
|
||||
#
|
||||
from typing import List
|
||||
|
||||
from ahriman.core.formatters import StringPrinter
|
||||
from ahriman.models.property import Property
|
||||
from ahriman.models.user import User
|
||||
@ -42,11 +40,11 @@ class UserPrinter(StringPrinter):
|
||||
StringPrinter.__init__(self, user.username)
|
||||
self.user = user
|
||||
|
||||
def properties(self) -> List[Property]:
|
||||
def properties(self) -> list[Property]:
|
||||
"""
|
||||
convert content into printable data
|
||||
|
||||
Returns:
|
||||
List[Property]: list of content properties
|
||||
list[Property]: list of content properties
|
||||
"""
|
||||
return [Property("role", self.user.access.value, is_required=True)]
|
||||
|
@ -17,7 +17,8 @@
|
||||
# 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 typing import Any, Dict, Generator, List, Union
|
||||
from collections.abc import Generator
|
||||
from typing import Any
|
||||
|
||||
from ahriman.core.formatters import StringPrinter
|
||||
from ahriman.models.property import Property
|
||||
@ -29,30 +30,30 @@ class ValidationPrinter(StringPrinter):
|
||||
|
||||
Attributes:
|
||||
node(str): root level name
|
||||
errors(List[Union[str, Dict[str, Any]]]): validation errors
|
||||
errors(list[str | dict[str, Any]]): validation errors
|
||||
"""
|
||||
|
||||
def __init__(self, node: str, errors: List[Union[str, Dict[str, Any]]]) -> None:
|
||||
def __init__(self, node: str, errors: list[str | dict[str, Any]]) -> None:
|
||||
"""
|
||||
default constructor
|
||||
|
||||
Args:
|
||||
node(str): root level name
|
||||
errors(List[Union[str, Dict[str, Any]]]): validation errors
|
||||
errors(list[str | dict[str, Any]]): validation errors
|
||||
"""
|
||||
StringPrinter.__init__(self, node)
|
||||
self.node = node
|
||||
self.errors = errors
|
||||
|
||||
@staticmethod
|
||||
def get_error_messages(node: str, errors: List[Union[str, Dict[str, Any]]],
|
||||
def get_error_messages(node: str, errors: list[str | dict[str, Any]],
|
||||
current_level: int = 1) -> Generator[Property, None, None]:
|
||||
"""
|
||||
extract default error message from cerberus class
|
||||
|
||||
Args:
|
||||
node(str): current node level name
|
||||
errors(List[Union[str, Dict[str, Any]]]): current node validation errors
|
||||
errors(list[str | dict[str, Any]]): current node validation errors
|
||||
current_level(int, optional): current level number (Default value = 1)
|
||||
|
||||
Yields:
|
||||
@ -67,11 +68,11 @@ class ValidationPrinter(StringPrinter):
|
||||
else: # current node errors
|
||||
yield Property(node, error, is_required=True, indent=current_level)
|
||||
|
||||
def properties(self) -> List[Property]:
|
||||
def properties(self) -> list[Property]:
|
||||
"""
|
||||
convert content into printable data
|
||||
|
||||
Returns:
|
||||
List[Property]: list of content properties
|
||||
list[Property]: list of content properties
|
||||
"""
|
||||
return list(self.get_error_messages(self.node, self.errors))
|
||||
|
@ -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/>.
|
||||
#
|
||||
from typing import Dict, List
|
||||
|
||||
from ahriman.core.formatters import StringPrinter
|
||||
from ahriman.models.property import Property
|
||||
|
||||
@ -28,26 +26,26 @@ class VersionPrinter(StringPrinter):
|
||||
print content of the python package versions
|
||||
|
||||
Attributes:
|
||||
packages(Dict[str, str]): map of package name to its version
|
||||
packages(dict[str, str]): map of package name to its version
|
||||
"""
|
||||
|
||||
def __init__(self, title: str, packages: Dict[str, str]) -> None:
|
||||
def __init__(self, title: str, packages: dict[str, str]) -> None:
|
||||
"""
|
||||
default constructor
|
||||
|
||||
Args:
|
||||
title(str): title of the message
|
||||
packages(Dict[str, str]): map of package name to its version
|
||||
packages(dict[str, str]): map of package name to its version
|
||||
"""
|
||||
StringPrinter.__init__(self, title)
|
||||
self.packages = packages
|
||||
|
||||
def properties(self) -> List[Property]:
|
||||
def properties(self) -> list[Property]:
|
||||
"""
|
||||
convert content into printable data
|
||||
|
||||
Returns:
|
||||
List[Property]: list of content properties
|
||||
list[Property]: list of content properties
|
||||
"""
|
||||
return [
|
||||
Property(package, version, is_required=True)
|
||||
|
@ -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/>.
|
||||
#
|
||||
from typing import List, Type
|
||||
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.gitremote.remote_pull import RemotePull
|
||||
from ahriman.core.triggers import Trigger
|
||||
@ -29,7 +27,7 @@ class RemotePullTrigger(Trigger):
|
||||
trigger based on pulling PKGBUILDs before the actions
|
||||
|
||||
Attributes:
|
||||
targets(List[str]): git remote target list
|
||||
targets(list[str]): git remote target list
|
||||
"""
|
||||
|
||||
CONFIGURATION_SCHEMA = {
|
||||
@ -70,7 +68,7 @@ class RemotePullTrigger(Trigger):
|
||||
self.targets = self.configuration_sections(configuration)
|
||||
|
||||
@classmethod
|
||||
def configuration_sections(cls: Type[Trigger], configuration: Configuration) -> List[str]:
|
||||
def configuration_sections(cls: type[Trigger], configuration: Configuration) -> list[str]:
|
||||
"""
|
||||
extract configuration sections from configuration
|
||||
|
||||
@ -78,7 +76,7 @@ class RemotePullTrigger(Trigger):
|
||||
configuration(Configuration): configuration instance
|
||||
|
||||
Returns:
|
||||
List[str]: read configuration sections belong to this trigger
|
||||
list[str]: read configuration sections belong to this trigger
|
||||
"""
|
||||
return configuration.getlist("remote-pull", "target", fallback=[])
|
||||
|
||||
|
@ -19,9 +19,9 @@
|
||||
#
|
||||
import shutil
|
||||
|
||||
from collections.abc import Generator
|
||||
from pathlib import Path
|
||||
from tempfile import TemporaryDirectory
|
||||
from typing import Generator
|
||||
|
||||
from ahriman.core.build_tools.sources import Sources
|
||||
from ahriman.core.configuration import Configuration
|
||||
@ -39,7 +39,7 @@ class RemotePush(LazyLogging):
|
||||
sync PKGBUILDs to remote repository after actions
|
||||
|
||||
Attributes:
|
||||
commit_author(Optional[str]): optional commit author in form of git config (i.e. ``user <user@host>``)
|
||||
commit_author(str | None): optional commit author in form of git config (i.e. ``user <user@host>``)
|
||||
database(SQLite): database instance
|
||||
remote_source(RemoteSource): repository remote source (remote pull url and branch)
|
||||
"""
|
||||
|
@ -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/>.
|
||||
#
|
||||
from typing import Iterable, List, Type
|
||||
|
||||
from ahriman.core import context
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.database import SQLite
|
||||
@ -34,7 +32,7 @@ class RemotePushTrigger(Trigger):
|
||||
trigger for syncing PKGBUILDs to remote repository
|
||||
|
||||
Attributes:
|
||||
targets(List[str]): git remote target list
|
||||
targets(list[str]): git remote target list
|
||||
"""
|
||||
|
||||
CONFIGURATION_SCHEMA = {
|
||||
@ -78,7 +76,7 @@ class RemotePushTrigger(Trigger):
|
||||
self.targets = self.configuration_sections(configuration)
|
||||
|
||||
@classmethod
|
||||
def configuration_sections(cls: Type[Trigger], configuration: Configuration) -> List[str]:
|
||||
def configuration_sections(cls: type[Trigger], configuration: Configuration) -> list[str]:
|
||||
"""
|
||||
extract configuration sections from configuration
|
||||
|
||||
@ -86,17 +84,17 @@ class RemotePushTrigger(Trigger):
|
||||
configuration(Configuration): configuration instance
|
||||
|
||||
Returns:
|
||||
List[str]: read configuration sections belong to this trigger
|
||||
list[str]: read configuration sections belong to this trigger
|
||||
"""
|
||||
return configuration.getlist("remote-push", "target", fallback=[])
|
||||
|
||||
def on_result(self, result: Result, packages: Iterable[Package]) -> None:
|
||||
def on_result(self, result: Result, packages: list[Package]) -> None:
|
||||
"""
|
||||
trigger action which will be called after build process with process result
|
||||
|
||||
Args:
|
||||
result(Result): build result
|
||||
packages(Iterable[Package]): list of all available packages
|
||||
packages(list[Package]): list of all available packages
|
||||
|
||||
Raises:
|
||||
GitRemoteError: if database is not set in context
|
||||
|
@ -20,7 +20,8 @@
|
||||
import contextlib
|
||||
import logging
|
||||
|
||||
from typing import Any, Generator
|
||||
from collections.abc import Generator
|
||||
from typing import Any
|
||||
|
||||
|
||||
class LazyLogging:
|
||||
|
@ -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/>.
|
||||
#
|
||||
from typing import Iterable
|
||||
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.formatters import BuildPrinter
|
||||
from ahriman.core.report.report import Report
|
||||
@ -46,12 +44,12 @@ class Console(Report):
|
||||
Report.__init__(self, architecture, configuration)
|
||||
self.use_utf = configuration.getboolean(section, "use_utf", fallback=True)
|
||||
|
||||
def generate(self, packages: Iterable[Package], result: Result) -> None:
|
||||
def generate(self, packages: list[Package], result: Result) -> None:
|
||||
"""
|
||||
generate report for the specified packages
|
||||
|
||||
Args:
|
||||
packages(Iterable[Package]): list of packages to generate report
|
||||
packages(list[Package]): list of packages to generate report
|
||||
result(Result): build result
|
||||
"""
|
||||
for package in result.success:
|
||||
|
@ -21,7 +21,6 @@ import smtplib
|
||||
|
||||
from email.mime.multipart import MIMEMultipart
|
||||
from email.mime.text import MIMEText
|
||||
from typing import Dict, Iterable
|
||||
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.report.jinja_template import JinjaTemplate
|
||||
@ -40,13 +39,13 @@ class Email(Report, JinjaTemplate):
|
||||
full_template_path(Path): path to template for full package list
|
||||
host(str): SMTP host to connect
|
||||
no_empty_report(bool): skip empty report generation
|
||||
password(Optional[str]): password to authenticate via SMTP
|
||||
password(str | None): password to authenticate via SMTP
|
||||
port(int): SMTP port to connect
|
||||
receivers(List[str]): list of receivers emails
|
||||
receivers(list[str]): list of receivers emails
|
||||
sender(str): sender email address
|
||||
ssl(SmtpSSLSettings): SSL mode for SMTP connection
|
||||
template_path(Path): path to template for built packages
|
||||
user(Optional[str]): username to authenticate via SMTP
|
||||
user(str | None): username to authenticate via SMTP
|
||||
"""
|
||||
|
||||
def __init__(self, architecture: str, configuration: Configuration, section: str) -> None:
|
||||
@ -74,13 +73,13 @@ class Email(Report, JinjaTemplate):
|
||||
self.ssl = SmtpSSLSettings.from_option(configuration.get(section, "ssl", fallback="disabled"))
|
||||
self.user = configuration.get(section, "user", fallback=None)
|
||||
|
||||
def _send(self, text: str, attachment: Dict[str, str]) -> None:
|
||||
def _send(self, text: str, attachment: dict[str, str]) -> None:
|
||||
"""
|
||||
send email callback
|
||||
|
||||
Args:
|
||||
text(str): email body text
|
||||
attachment(Dict[str, str]): map of attachment filename to attachment content
|
||||
attachment(dict[str, str]): map of attachment filename to attachment content
|
||||
"""
|
||||
message = MIMEMultipart()
|
||||
message["From"] = self.sender
|
||||
@ -104,12 +103,12 @@ class Email(Report, JinjaTemplate):
|
||||
session.sendmail(self.sender, self.receivers, message.as_string())
|
||||
session.quit()
|
||||
|
||||
def generate(self, packages: Iterable[Package], result: Result) -> None:
|
||||
def generate(self, packages: list[Package], result: Result) -> None:
|
||||
"""
|
||||
generate report for the specified packages
|
||||
|
||||
Args:
|
||||
packages(Iterable[Package]): list of packages to generate report
|
||||
packages(list[Package]): list of packages to generate report
|
||||
result(Result): build result
|
||||
"""
|
||||
if self.no_empty_report and not result.success:
|
||||
|
@ -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/>.
|
||||
#
|
||||
from typing import Iterable
|
||||
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.report.jinja_template import JinjaTemplate
|
||||
from ahriman.core.report.report import Report
|
||||
@ -50,12 +48,12 @@ class HTML(Report, JinjaTemplate):
|
||||
self.report_path = configuration.getpath(section, "path")
|
||||
self.template_path = configuration.getpath(section, "template_path")
|
||||
|
||||
def generate(self, packages: Iterable[Package], result: Result) -> None:
|
||||
def generate(self, packages: list[Package], result: Result) -> None:
|
||||
"""
|
||||
generate report for the specified packages
|
||||
|
||||
Args:
|
||||
packages(Iterable[Package]): list of packages to generate report
|
||||
packages(list[Package]): list of packages to generate report
|
||||
result(Result): build result
|
||||
"""
|
||||
html = self.make_html(Result(success=packages), self.template_path)
|
||||
|
@ -19,8 +19,8 @@
|
||||
#
|
||||
import jinja2
|
||||
|
||||
from collections.abc import Callable
|
||||
from pathlib import Path
|
||||
from typing import Callable, Dict
|
||||
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.sign.gpg import GPG
|
||||
@ -56,11 +56,11 @@ class JinjaTemplate:
|
||||
* repository - repository name, string, required
|
||||
|
||||
Attributes:
|
||||
homepage(Optional[str]): homepage link if any (for footer)
|
||||
homepage(str | None): homepage link if any (for footer)
|
||||
link_path(str): prefix fo packages to download
|
||||
name(str): repository name
|
||||
default_pgp_key(Optional[str]): default PGP key
|
||||
sign_targets(Set[SignSettings]): targets to sign enabled in configuration
|
||||
default_pgp_key(str | None): default PGP key
|
||||
sign_targets(set[SignSettings]): targets to sign enabled in configuration
|
||||
"""
|
||||
|
||||
def __init__(self, section: str, configuration: Configuration) -> None:
|
||||
@ -108,7 +108,7 @@ class JinjaTemplate:
|
||||
"version": base.version
|
||||
} for base in result.success for package, properties in base.packages.items()
|
||||
]
|
||||
comparator: Callable[[Dict[str, str]], str] = lambda item: item["filename"]
|
||||
comparator: Callable[[dict[str, str]], str] = lambda item: item["filename"]
|
||||
|
||||
return template.render(
|
||||
homepage=self.homepage,
|
||||
|
@ -19,8 +19,6 @@
|
||||
#
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Iterable, Type
|
||||
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.exceptions import ReportError
|
||||
from ahriman.core.log import LazyLogging
|
||||
@ -69,7 +67,7 @@ class Report(LazyLogging):
|
||||
self.configuration = configuration
|
||||
|
||||
@classmethod
|
||||
def load(cls: Type[Report], architecture: str, configuration: Configuration, target: str) -> Report:
|
||||
def load(cls: type[Report], architecture: str, configuration: Configuration, target: str) -> Report:
|
||||
"""
|
||||
load client from settings
|
||||
|
||||
@ -97,22 +95,22 @@ class Report(LazyLogging):
|
||||
return Telegram(architecture, configuration, section)
|
||||
return cls(architecture, configuration) # should never happen
|
||||
|
||||
def generate(self, packages: Iterable[Package], result: Result) -> None:
|
||||
def generate(self, packages: list[Package], result: Result) -> None:
|
||||
"""
|
||||
generate report for the specified packages
|
||||
|
||||
Args:
|
||||
packages(Iterable[Package]): list of packages to generate report
|
||||
packages(list[Package]): list of packages to generate report
|
||||
result(Result): build result
|
||||
"""
|
||||
|
||||
def run(self, result: Result, packages: Iterable[Package]) -> None:
|
||||
def run(self, result: Result, packages: list[Package]) -> None:
|
||||
"""
|
||||
run report generation
|
||||
|
||||
Args:
|
||||
result(Result): build result
|
||||
packages(Iterable[Package]): list of packages to generate report
|
||||
packages(list[Package]): list of packages to generate report
|
||||
|
||||
Raises:
|
||||
ReportFailed: in case of any report unmatched exception
|
||||
|
@ -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/>.
|
||||
#
|
||||
from typing import Iterable, List, Type
|
||||
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.triggers import Trigger
|
||||
from ahriman.core.report.report import Report
|
||||
@ -31,7 +29,7 @@ class ReportTrigger(Trigger):
|
||||
report trigger
|
||||
|
||||
Attributes:
|
||||
targets(List[str]): report target list
|
||||
targets(list[str]): report target list
|
||||
"""
|
||||
|
||||
CONFIGURATION_SCHEMA = {
|
||||
@ -207,7 +205,7 @@ class ReportTrigger(Trigger):
|
||||
self.targets = self.configuration_sections(configuration)
|
||||
|
||||
@classmethod
|
||||
def configuration_sections(cls: Type[Trigger], configuration: Configuration) -> List[str]:
|
||||
def configuration_sections(cls: type[Trigger], configuration: Configuration) -> list[str]:
|
||||
"""
|
||||
extract configuration sections from configuration
|
||||
|
||||
@ -215,17 +213,17 @@ class ReportTrigger(Trigger):
|
||||
configuration(Configuration): configuration instance
|
||||
|
||||
Returns:
|
||||
List[str]: read configuration sections belong to this trigger
|
||||
list[str]: read configuration sections belong to this trigger
|
||||
"""
|
||||
return configuration.getlist("report", "target", fallback=[])
|
||||
|
||||
def on_result(self, result: Result, packages: Iterable[Package]) -> None:
|
||||
def on_result(self, result: Result, packages: list[Package]) -> None:
|
||||
"""
|
||||
run trigger
|
||||
|
||||
Args:
|
||||
result(Result): build result
|
||||
packages(Iterable[Package]): list of all available packages
|
||||
packages(list[Package]): list of all available packages
|
||||
"""
|
||||
for target in self.targets:
|
||||
runner = Report.load(self.architecture, self.configuration, target)
|
||||
|
@ -19,8 +19,6 @@
|
||||
#
|
||||
import requests # technically we could use python-telegram-bot, but it is just a single request, c'mon
|
||||
|
||||
from typing import Iterable
|
||||
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.report.jinja_template import JinjaTemplate
|
||||
from ahriman.core.report.report import Report
|
||||
@ -84,12 +82,12 @@ class Telegram(Report, JinjaTemplate):
|
||||
self.logger.exception("could not perform request")
|
||||
raise
|
||||
|
||||
def generate(self, packages: Iterable[Package], result: Result) -> None:
|
||||
def generate(self, packages: list[Package], result: Result) -> None:
|
||||
"""
|
||||
generate report for the specified packages
|
||||
|
||||
Args:
|
||||
packages(Iterable[Package]): list of packages to generate report
|
||||
packages(list[Package]): list of packages to generate report
|
||||
result(Result): build result
|
||||
"""
|
||||
if not result.success:
|
||||
|
@ -20,7 +20,6 @@
|
||||
import shutil
|
||||
|
||||
from pathlib import Path
|
||||
from typing import List
|
||||
|
||||
from ahriman.core.repository.repository_properties import RepositoryProperties
|
||||
|
||||
@ -69,12 +68,12 @@ class Cleaner(RepositoryProperties):
|
||||
self.logger.info("clear build queue")
|
||||
self.database.build_queue_clear(None)
|
||||
|
||||
def packages_built(self) -> List[Path]:
|
||||
def packages_built(self) -> list[Path]:
|
||||
"""
|
||||
get list of files in built packages directory
|
||||
|
||||
Returns:
|
||||
List[Path]: list of filenames from the directory
|
||||
list[Path]: list of filenames from the directory
|
||||
|
||||
Raises:
|
||||
NotImplementedError: not implemented method
|
||||
|
@ -19,9 +19,9 @@
|
||||
#
|
||||
import shutil
|
||||
|
||||
from collections.abc import Iterable
|
||||
from pathlib import Path
|
||||
from tempfile import TemporaryDirectory
|
||||
from typing import Dict, Iterable, List, Optional
|
||||
|
||||
from ahriman.core.build_tools.task import Task
|
||||
from ahriman.core.repository.cleaner import Cleaner
|
||||
@ -36,7 +36,7 @@ class Executor(Cleaner):
|
||||
trait for common repository update processes
|
||||
"""
|
||||
|
||||
def load_archives(self, packages: Iterable[Path]) -> List[Package]:
|
||||
def load_archives(self, packages: Iterable[Path]) -> list[Package]:
|
||||
"""
|
||||
load packages from list of archives
|
||||
|
||||
@ -44,19 +44,19 @@ class Executor(Cleaner):
|
||||
packages(Iterable[Path]): paths to package archives
|
||||
|
||||
Returns:
|
||||
List[Package]: list of read packages
|
||||
list[Package]: list of read packages
|
||||
|
||||
Raises:
|
||||
NotImplementedError: not implemented method
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def packages(self) -> List[Package]:
|
||||
def packages(self) -> list[Package]:
|
||||
"""
|
||||
generate list of repository packages
|
||||
|
||||
Returns:
|
||||
List[Package]: list of packages properties
|
||||
list[Package]: list of packages properties
|
||||
|
||||
Raises:
|
||||
NotImplementedError: not implemented method
|
||||
@ -122,8 +122,8 @@ class Executor(Cleaner):
|
||||
except Exception:
|
||||
self.logger.exception("could not remove %s", package)
|
||||
|
||||
packages_to_remove: Dict[str, Path] = {}
|
||||
bases_to_remove: List[str] = []
|
||||
packages_to_remove: dict[str, Path] = {}
|
||||
bases_to_remove: list[str] = []
|
||||
|
||||
# build package list based on user input
|
||||
requested = set(packages)
|
||||
@ -177,7 +177,7 @@ class Executor(Cleaner):
|
||||
shutil.move(self.paths.packages / archive.filename, self.paths.packages / safe)
|
||||
archive.filename = safe
|
||||
|
||||
def update_single(name: Optional[str], package_base: str) -> None:
|
||||
def update_single(name: str | None, package_base: str) -> None:
|
||||
if name is None:
|
||||
self.logger.warning("received empty package name for base %s", package_base)
|
||||
return # suppress type checking, it never can be none actually
|
||||
@ -191,7 +191,7 @@ class Executor(Cleaner):
|
||||
self.repo.add(package_path)
|
||||
|
||||
current_packages = self.packages()
|
||||
removed_packages: List[str] = [] # list of packages which have been removed from the base
|
||||
removed_packages: list[str] = [] # list of packages which have been removed from the base
|
||||
updates = self.load_archives(packages)
|
||||
|
||||
result = Result()
|
||||
|
@ -19,8 +19,8 @@
|
||||
#
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Iterable
|
||||
from pathlib import Path
|
||||
from typing import Dict, Iterable, List, Optional, Type
|
||||
|
||||
from ahriman.core import _Context, context
|
||||
from ahriman.core.alpm.pacman import Pacman
|
||||
@ -58,7 +58,7 @@ class Repository(Executor, UpdateHandler):
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def load(cls: Type[Repository], architecture: str, configuration: Configuration, database: SQLite, *,
|
||||
def load(cls: type[Repository], architecture: str, configuration: Configuration, database: SQLite, *,
|
||||
report: bool, unsafe: bool, refresh_pacman_database: int = 0) -> Repository:
|
||||
"""
|
||||
load instance from argument list
|
||||
@ -99,7 +99,7 @@ class Repository(Executor, UpdateHandler):
|
||||
|
||||
context.set(ctx)
|
||||
|
||||
def load_archives(self, packages: Iterable[Path]) -> List[Package]:
|
||||
def load_archives(self, packages: Iterable[Path]) -> list[Package]:
|
||||
"""
|
||||
load packages from list of archives
|
||||
|
||||
@ -107,11 +107,11 @@ class Repository(Executor, UpdateHandler):
|
||||
packages(Iterable[Path]): paths to package archives
|
||||
|
||||
Returns:
|
||||
List[Package]: list of read packages
|
||||
list[Package]: list of read packages
|
||||
"""
|
||||
sources = self.database.remotes_get()
|
||||
|
||||
result: Dict[str, Package] = {}
|
||||
result: dict[str, Package] = {}
|
||||
# we are iterating over bases, not single packages
|
||||
for full_path in packages:
|
||||
try:
|
||||
@ -130,34 +130,34 @@ class Repository(Executor, UpdateHandler):
|
||||
self.logger.exception("could not load package from %s", full_path)
|
||||
return list(result.values())
|
||||
|
||||
def packages(self) -> List[Package]:
|
||||
def packages(self) -> list[Package]:
|
||||
"""
|
||||
generate list of repository packages
|
||||
|
||||
Returns:
|
||||
List[Package]: list of packages properties
|
||||
list[Package]: list of packages properties
|
||||
"""
|
||||
return self.load_archives(filter(package_like, self.paths.repository.iterdir()))
|
||||
|
||||
def packages_built(self) -> List[Path]:
|
||||
def packages_built(self) -> list[Path]:
|
||||
"""
|
||||
get list of files in built packages directory
|
||||
|
||||
Returns:
|
||||
List[Path]: list of filenames from the directory
|
||||
list[Path]: list of filenames from the directory
|
||||
"""
|
||||
return list(filter(package_like, self.paths.packages.iterdir()))
|
||||
|
||||
def packages_depend_on(self, packages: List[Package], depends_on: Optional[Iterable[str]]) -> List[Package]:
|
||||
def packages_depend_on(self, packages: list[Package], depends_on: Iterable[str] | None) -> list[Package]:
|
||||
"""
|
||||
extract list of packages which depends on specified package
|
||||
|
||||
Args:
|
||||
packages(List[Package]): list of packages to be filtered
|
||||
depends_on(Optional[Iterable[str]]): dependencies of the packages
|
||||
packages(list[Package]): list of packages to be filtered
|
||||
depends_on(Iterable[str] | None): dependencies of the packages
|
||||
|
||||
Returns:
|
||||
List[Package]: list of repository packages which depend on specified packages
|
||||
list[Package]: list of repository packages which depend on specified packages
|
||||
"""
|
||||
if depends_on is None:
|
||||
return packages # no list provided extract everything by default
|
||||
|
@ -37,7 +37,7 @@ class RepositoryProperties(LazyLogging):
|
||||
architecture(str): repository architecture
|
||||
configuration(Configuration): configuration instance
|
||||
database(SQLite): database instance
|
||||
ignore_list(List[str]): package bases which will be ignored during auto updates
|
||||
ignore_list(list[str]): package bases which will be ignored during auto updates
|
||||
name(str): repository name
|
||||
pacman(Pacman): alpm wrapper instance
|
||||
paths(RepositoryPaths): repository paths instance
|
||||
|
@ -17,7 +17,7 @@
|
||||
# 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 typing import Iterable, List
|
||||
from collections.abc import Iterable
|
||||
|
||||
from ahriman.core.build_tools.sources import Sources
|
||||
from ahriman.core.repository.cleaner import Cleaner
|
||||
@ -30,19 +30,19 @@ class UpdateHandler(Cleaner):
|
||||
trait to get package update list
|
||||
"""
|
||||
|
||||
def packages(self) -> List[Package]:
|
||||
def packages(self) -> list[Package]:
|
||||
"""
|
||||
generate list of repository packages
|
||||
|
||||
Returns:
|
||||
List[Package]: list of packages properties
|
||||
list[Package]: list of packages properties
|
||||
|
||||
Raises:
|
||||
NotImplementedError: not implemented method
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def updates_aur(self, filter_packages: Iterable[str], *, vcs: bool) -> List[Package]:
|
||||
def updates_aur(self, filter_packages: Iterable[str], *, vcs: bool) -> list[Package]:
|
||||
"""
|
||||
check AUR for updates
|
||||
|
||||
@ -51,9 +51,9 @@ class UpdateHandler(Cleaner):
|
||||
vcs(bool): enable or disable checking of VCS packages
|
||||
|
||||
Returns:
|
||||
List[Package]: list of packages which are out-of-dated
|
||||
list[Package]: list of packages which are out-of-dated
|
||||
"""
|
||||
result: List[Package] = []
|
||||
result: list[Package] = []
|
||||
|
||||
for local in self.packages():
|
||||
with self.in_package_context(local.base):
|
||||
@ -81,7 +81,7 @@ class UpdateHandler(Cleaner):
|
||||
|
||||
return result
|
||||
|
||||
def updates_local(self, *, vcs: bool) -> List[Package]:
|
||||
def updates_local(self, *, vcs: bool) -> list[Package]:
|
||||
"""
|
||||
check local packages for updates
|
||||
|
||||
@ -89,9 +89,9 @@ class UpdateHandler(Cleaner):
|
||||
vcs(bool): enable or disable checking of VCS packages
|
||||
|
||||
Returns:
|
||||
List[Package]: list of local packages which are out-of-dated
|
||||
list[Package]: list of local packages which are out-of-dated
|
||||
"""
|
||||
result: List[Package] = []
|
||||
result: list[Package] = []
|
||||
packages = {local.base: local for local in self.packages()}
|
||||
|
||||
for cache_dir in self.paths.cache.iterdir():
|
||||
@ -114,14 +114,14 @@ class UpdateHandler(Cleaner):
|
||||
|
||||
return result
|
||||
|
||||
def updates_manual(self) -> List[Package]:
|
||||
def updates_manual(self) -> list[Package]:
|
||||
"""
|
||||
check for packages for which manual update has been requested
|
||||
|
||||
Returns:
|
||||
List[Package]: list of packages which are out-of-dated
|
||||
list[Package]: list of packages which are out-of-dated
|
||||
"""
|
||||
result: List[Package] = []
|
||||
result: list[Package] = []
|
||||
known_bases = {package.base for package in self.packages()}
|
||||
|
||||
try:
|
||||
|
@ -20,7 +20,6 @@
|
||||
import requests
|
||||
|
||||
from pathlib import Path
|
||||
from typing import List, Optional, Set, Tuple
|
||||
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.exceptions import BuildError
|
||||
@ -37,8 +36,8 @@ class GPG(LazyLogging):
|
||||
DEFAULT_TIMEOUT(int): (class attribute) HTTP request timeout in seconds
|
||||
architecture(str): repository architecture
|
||||
configuration(Configuration): configuration instance
|
||||
default_key(Optional[str]): default PGP key ID to use
|
||||
targets(Set[SignSettings]): list of targets to sign (repository, package etc)
|
||||
default_key(str | None): default PGP key ID to use
|
||||
targets(set[SignSettings]): list of targets to sign (repository, package etc)
|
||||
"""
|
||||
|
||||
_check_output = check_output
|
||||
@ -57,12 +56,12 @@ class GPG(LazyLogging):
|
||||
self.targets, self.default_key = self.sign_options(configuration)
|
||||
|
||||
@property
|
||||
def repository_sign_args(self) -> List[str]:
|
||||
def repository_sign_args(self) -> list[str]:
|
||||
"""
|
||||
get command line arguments based on settings
|
||||
|
||||
Returns:
|
||||
List[str]: command line arguments for repo-add command to sign database
|
||||
list[str]: command line arguments for repo-add command to sign database
|
||||
"""
|
||||
if SignSettings.Repository not in self.targets:
|
||||
return []
|
||||
@ -72,7 +71,7 @@ class GPG(LazyLogging):
|
||||
return ["--sign", "--key", self.default_key]
|
||||
|
||||
@staticmethod
|
||||
def sign_command(path: Path, key: str) -> List[str]:
|
||||
def sign_command(path: Path, key: str) -> list[str]:
|
||||
"""
|
||||
gpg command to run
|
||||
|
||||
@ -81,12 +80,12 @@ class GPG(LazyLogging):
|
||||
key(str): PGP key ID
|
||||
|
||||
Returns:
|
||||
List[str]: gpg command with all required arguments
|
||||
list[str]: gpg command with all required arguments
|
||||
"""
|
||||
return ["gpg", "-u", key, "-b", str(path)]
|
||||
|
||||
@staticmethod
|
||||
def sign_options(configuration: Configuration) -> Tuple[Set[SignSettings], Optional[str]]:
|
||||
def sign_options(configuration: Configuration) -> tuple[set[SignSettings], str | None]:
|
||||
"""
|
||||
extract default sign options from configuration
|
||||
|
||||
@ -94,9 +93,9 @@ class GPG(LazyLogging):
|
||||
configuration(Configuration): configuration instance
|
||||
|
||||
Returns:
|
||||
Tuple[Set[SignSettings], Optional[str]]: tuple of sign targets and default PGP key
|
||||
tuple[set[SignSettings], str | None]: tuple of sign targets and default PGP key
|
||||
"""
|
||||
targets: Set[SignSettings] = set()
|
||||
targets: set[SignSettings] = set()
|
||||
for option in configuration.getlist("sign", "target", fallback=[]):
|
||||
target = SignSettings.from_option(option)
|
||||
if target == SignSettings.Disabled:
|
||||
@ -140,7 +139,7 @@ class GPG(LazyLogging):
|
||||
key_body = self.key_download(server, key)
|
||||
GPG._check_output("gpg", "--import", input_data=key_body, logger=self.logger)
|
||||
|
||||
def process(self, path: Path, key: str) -> List[Path]:
|
||||
def process(self, path: Path, key: str) -> list[Path]:
|
||||
"""
|
||||
gpg command wrapper
|
||||
|
||||
@ -149,7 +148,7 @@ class GPG(LazyLogging):
|
||||
key(str): PGP key ID
|
||||
|
||||
Returns:
|
||||
List[Path]: list of generated files including original file
|
||||
list[Path]: list of generated files including original file
|
||||
"""
|
||||
GPG._check_output(
|
||||
*GPG.sign_command(path, key),
|
||||
@ -157,7 +156,7 @@ class GPG(LazyLogging):
|
||||
logger=self.logger)
|
||||
return [path, path.parent / f"{path.name}.sig"]
|
||||
|
||||
def process_sign_package(self, path: Path, package_base: str) -> List[Path]:
|
||||
def process_sign_package(self, path: Path, package_base: str) -> list[Path]:
|
||||
"""
|
||||
sign package if required by configuration
|
||||
|
||||
@ -166,7 +165,7 @@ class GPG(LazyLogging):
|
||||
package_base(str): package base required to check for key overrides
|
||||
|
||||
Returns:
|
||||
List[Path]: list of generated files including original file
|
||||
list[Path]: list of generated files including original file
|
||||
"""
|
||||
if SignSettings.Packages not in self.targets:
|
||||
return [path]
|
||||
@ -176,7 +175,7 @@ class GPG(LazyLogging):
|
||||
return [path]
|
||||
return self.process(path, key)
|
||||
|
||||
def process_sign_repository(self, path: Path) -> List[Path]:
|
||||
def process_sign_repository(self, path: Path) -> list[Path]:
|
||||
"""
|
||||
sign repository if required by configuration
|
||||
|
||||
@ -187,7 +186,7 @@ class GPG(LazyLogging):
|
||||
path(Path): path to repository database
|
||||
|
||||
Returns:
|
||||
List[Path]: list of generated files including original file
|
||||
list[Path]: list of generated files including original file
|
||||
"""
|
||||
if SignSettings.Repository not in self.targets:
|
||||
return [path]
|
||||
|
@ -22,9 +22,9 @@ from __future__ import annotations
|
||||
import argparse
|
||||
import uuid
|
||||
|
||||
from collections.abc import Callable, Iterable
|
||||
from multiprocessing import Process, Queue
|
||||
from threading import Lock, Thread
|
||||
from typing import Callable, Dict, Iterable, Optional, Tuple
|
||||
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.log import LazyLogging
|
||||
@ -37,10 +37,10 @@ class Spawn(Thread, LazyLogging):
|
||||
MUST NOT be used directly, the only one usage allowed is to spawn process from web services
|
||||
|
||||
Attributes:
|
||||
active(Dict[str, Process]): map of active child processes required to avoid zombies
|
||||
active(dict[str, Process]): map of active child processes required to avoid zombies
|
||||
architecture(str): repository architecture
|
||||
configuration(Configuration): configuration instance
|
||||
queue(Queue[Tuple[str, bool]]): multiprocessing queue to read updates from processes
|
||||
queue(Queue[tuple[str, bool]]): multiprocessing queue to read updates from processes
|
||||
"""
|
||||
|
||||
def __init__(self, args_parser: argparse.ArgumentParser, architecture: str, configuration: Configuration) -> None:
|
||||
@ -58,13 +58,13 @@ class Spawn(Thread, LazyLogging):
|
||||
self.configuration = configuration
|
||||
|
||||
self.lock = Lock()
|
||||
self.active: Dict[str, Process] = {}
|
||||
self.active: dict[str, Process] = {}
|
||||
# stupid pylint does not know that it is possible
|
||||
self.queue: Queue[Tuple[str, bool] | None] = Queue() # pylint: disable=unsubscriptable-object
|
||||
self.queue: Queue[tuple[str, bool] | None] = Queue() # pylint: disable=unsubscriptable-object
|
||||
|
||||
@staticmethod
|
||||
def process(callback: Callable[[argparse.Namespace, str], bool], args: argparse.Namespace, architecture: str,
|
||||
process_id: str, queue: Queue[Tuple[str, bool]]) -> None: # pylint: disable=unsubscriptable-object
|
||||
process_id: str, queue: Queue[tuple[str, bool]]) -> None: # pylint: disable=unsubscriptable-object
|
||||
"""
|
||||
helper to run external process
|
||||
|
||||
@ -73,7 +73,7 @@ class Spawn(Thread, LazyLogging):
|
||||
args(argparse.Namespace): command line arguments
|
||||
architecture(str): repository architecture
|
||||
process_id(str): process unique identifier
|
||||
queue(Queue[Tuple[str, bool]]): output queue
|
||||
queue(Queue[tuple[str, bool]]): output queue
|
||||
"""
|
||||
result = callback(args, architecture)
|
||||
queue.put((process_id, result))
|
||||
@ -113,13 +113,13 @@ class Spawn(Thread, LazyLogging):
|
||||
with self.lock:
|
||||
self.active[process_id] = process
|
||||
|
||||
def key_import(self, key: str, server: Optional[str]) -> None:
|
||||
def key_import(self, key: str, server: str | None) -> None:
|
||||
"""
|
||||
import key to service cache
|
||||
|
||||
Args:
|
||||
key(str): key to import
|
||||
server(str): PGP key server
|
||||
server(str | None): PGP key server
|
||||
"""
|
||||
kwargs = {} if server is None else {"key-server": server}
|
||||
self._spawn_process("service-key-import", key, **kwargs)
|
||||
@ -155,7 +155,7 @@ class Spawn(Thread, LazyLogging):
|
||||
"""
|
||||
self._spawn_process("package-remove", *packages)
|
||||
|
||||
def packages_update(self, ) -> None:
|
||||
def packages_update(self) -> None:
|
||||
"""
|
||||
run full repository update
|
||||
"""
|
||||
|
@ -21,8 +21,6 @@ from __future__ import annotations
|
||||
|
||||
import logging
|
||||
|
||||
from typing import List, Optional, Tuple, Type
|
||||
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.models.build_status import BuildStatus, BuildStatusEnum
|
||||
from ahriman.models.internal_status import InternalStatus
|
||||
@ -35,7 +33,7 @@ class Client:
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def load(cls: Type[Client], configuration: Configuration, *, report: bool) -> Client:
|
||||
def load(cls: type[Client], configuration: Configuration, *, report: bool) -> Client:
|
||||
"""
|
||||
load client from settings
|
||||
|
||||
@ -71,15 +69,15 @@ class Client:
|
||||
status(BuildStatusEnum): current package build status
|
||||
"""
|
||||
|
||||
def get(self, package_base: Optional[str]) -> List[Tuple[Package, BuildStatus]]:
|
||||
def get(self, package_base: str | None) -> list[tuple[Package, BuildStatus]]:
|
||||
"""
|
||||
get package status
|
||||
|
||||
Args:
|
||||
package_base(Optional[str]): package base to get
|
||||
package_base(str | None): package base to get
|
||||
|
||||
Returns:
|
||||
List[Tuple[Package, BuildStatus]]: list of current package description and status if it has been found
|
||||
list[tuple[Package, BuildStatus]]: list of current package description and status if it has been found
|
||||
"""
|
||||
del package_base
|
||||
return []
|
||||
|
@ -19,8 +19,6 @@
|
||||
#
|
||||
import os
|
||||
|
||||
from typing import Dict, List, Optional, Tuple
|
||||
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.database import SQLite
|
||||
from ahriman.core.exceptions import UnknownPackageError
|
||||
@ -38,7 +36,7 @@ class Watcher(LazyLogging):
|
||||
Attributes:
|
||||
architecture(str): repository architecture
|
||||
database(SQLite): database instance
|
||||
known(Dict[str, Tuple[Package, BuildStatus]]): list of known packages. For the most cases ``packages`` should
|
||||
known(dict[str, tuple[Package, BuildStatus]]): list of known packages. For the most cases ``packages`` should
|
||||
be used instead
|
||||
repository(Repository): repository object
|
||||
status(BuildStatus): daemon status
|
||||
@ -57,23 +55,23 @@ class Watcher(LazyLogging):
|
||||
self.database = database
|
||||
self.repository = Repository.load(architecture, configuration, database, report=False, unsafe=False)
|
||||
|
||||
self.known: Dict[str, Tuple[Package, BuildStatus]] = {}
|
||||
self.known: dict[str, tuple[Package, BuildStatus]] = {}
|
||||
self.status = BuildStatus()
|
||||
|
||||
# special variables for updating logs
|
||||
self._last_log_record_id = LogRecordId("", os.getpid())
|
||||
|
||||
@property
|
||||
def packages(self) -> List[Tuple[Package, BuildStatus]]:
|
||||
def packages(self) -> list[tuple[Package, BuildStatus]]:
|
||||
"""
|
||||
get current known packages list
|
||||
|
||||
Returns:
|
||||
List[Tuple[Package, BuildStatus]]: list of packages together with their statuses
|
||||
list[tuple[Package, BuildStatus]]: list of packages together with their statuses
|
||||
"""
|
||||
return list(self.known.values())
|
||||
|
||||
def get(self, package_base: str) -> Tuple[Package, BuildStatus]:
|
||||
def get(self, package_base: str) -> tuple[Package, BuildStatus]:
|
||||
"""
|
||||
get current package base build status
|
||||
|
||||
@ -81,7 +79,7 @@ class Watcher(LazyLogging):
|
||||
package_base(str): package base
|
||||
|
||||
Returns:
|
||||
Tuple[Package, BuildStatus]: package and its status
|
||||
tuple[Package, BuildStatus]: package and its status
|
||||
|
||||
Raises:
|
||||
UnknownPackage: if no package found
|
||||
@ -130,24 +128,24 @@ class Watcher(LazyLogging):
|
||||
self.database.package_remove(package_base)
|
||||
self.remove_logs(package_base, None)
|
||||
|
||||
def remove_logs(self, package_base: str, current_process_id: Optional[int]) -> None:
|
||||
def remove_logs(self, package_base: str, current_process_id: int | None) -> None:
|
||||
"""
|
||||
remove package related logs
|
||||
|
||||
Args:
|
||||
package_base(str): package base
|
||||
current_process_id(int): current process id
|
||||
current_process_id(int | None): current process id
|
||||
"""
|
||||
self.database.logs_remove(package_base, current_process_id)
|
||||
|
||||
def update(self, package_base: str, status: BuildStatusEnum, package: Optional[Package]) -> None:
|
||||
def update(self, package_base: str, status: BuildStatusEnum, package: Package | None) -> None:
|
||||
"""
|
||||
update package status and description
|
||||
|
||||
Args:
|
||||
package_base(str): package base to update
|
||||
status(BuildStatusEnum): new build status
|
||||
package(Optional[Package]): optional new package description. In case if not set current properties will be used
|
||||
package(Package | None): optional package description. In case if not set current properties will be used
|
||||
|
||||
Raises:
|
||||
UnknownPackage: if no package found
|
||||
|
@ -21,7 +21,7 @@ import contextlib
|
||||
import logging
|
||||
import requests
|
||||
|
||||
from typing import Generator, List, Optional, Tuple
|
||||
from collections.abc import Generator
|
||||
from urllib.parse import quote_plus as urlencode
|
||||
|
||||
from ahriman.core.configuration import Configuration
|
||||
@ -40,7 +40,7 @@ class WebClient(Client, LazyLogging):
|
||||
|
||||
Attributes:
|
||||
address(str): address of the web service
|
||||
user(Optional[User]): web service user descriptor
|
||||
user(User | None): web service user descriptor
|
||||
"""
|
||||
|
||||
def __init__(self, configuration: Configuration) -> None:
|
||||
@ -78,7 +78,7 @@ class WebClient(Client, LazyLogging):
|
||||
return f"{self.address}/api/v1/status"
|
||||
|
||||
@staticmethod
|
||||
def parse_address(configuration: Configuration) -> Tuple[str, bool]:
|
||||
def parse_address(configuration: Configuration) -> tuple[str, bool]:
|
||||
"""
|
||||
parse address from configuration
|
||||
|
||||
@ -86,7 +86,7 @@ class WebClient(Client, LazyLogging):
|
||||
configuration(Configuration): configuration instance
|
||||
|
||||
Returns:
|
||||
Tuple[str, bool]: tuple of server address and socket flag (True in case if unix socket must be used)
|
||||
tuple[str, bool]: tuple of server address and socket flag (True in case if unix socket must be used)
|
||||
"""
|
||||
if (unix_socket := configuration.get("web", "unix_socket", fallback=None)) is not None:
|
||||
# special pseudo-protocol which is used for unix sockets
|
||||
@ -190,15 +190,15 @@ class WebClient(Client, LazyLogging):
|
||||
response = self.__session.post(self._package_url(package.base), json=payload)
|
||||
response.raise_for_status()
|
||||
|
||||
def get(self, package_base: Optional[str]) -> List[Tuple[Package, BuildStatus]]:
|
||||
def get(self, package_base: str | None) -> list[tuple[Package, BuildStatus]]:
|
||||
"""
|
||||
get package status
|
||||
|
||||
Args:
|
||||
package_base(Optional[str]): package base to get
|
||||
package_base(str | None): package base to get
|
||||
|
||||
Returns:
|
||||
List[Tuple[Package, BuildStatus]]: list of current package description and status if it has been found
|
||||
list[tuple[Package, BuildStatus]]: list of current package description and status if it has been found
|
||||
"""
|
||||
with self.__execute_request():
|
||||
response = self.__session.get(self._package_url(package_base or ""))
|
||||
|
@ -21,7 +21,7 @@ from __future__ import annotations
|
||||
|
||||
import functools
|
||||
|
||||
from typing import Callable, Iterable, List
|
||||
from collections.abc import Callable, Iterable
|
||||
|
||||
from ahriman.core.util import partition
|
||||
from ahriman.models.package import Package
|
||||
@ -32,7 +32,7 @@ class Leaf:
|
||||
tree leaf implementation
|
||||
|
||||
Attributes:
|
||||
dependencies(Set[str]): list of package dependencies
|
||||
dependencies(set[str]): list of package dependencies
|
||||
package(Package): leaf package properties
|
||||
"""
|
||||
|
||||
@ -92,7 +92,7 @@ class Tree:
|
||||
dependency tree implementation
|
||||
|
||||
Attributes:
|
||||
leaves[List[Leaf]): list of tree leaves
|
||||
leaves[list[Leaf]): list of tree leaves
|
||||
|
||||
Examples:
|
||||
The most important feature here is to generate tree levels one by one which can be achieved by using class
|
||||
@ -119,17 +119,17 @@ class Tree:
|
||||
>>> tree = Tree(leaves)
|
||||
"""
|
||||
|
||||
def __init__(self, leaves: List[Leaf]) -> None:
|
||||
def __init__(self, leaves: list[Leaf]) -> None:
|
||||
"""
|
||||
default constructor
|
||||
|
||||
Args:
|
||||
leaves(List[Leaf]): leaves to build the tree
|
||||
leaves(list[Leaf]): leaves to build the tree
|
||||
"""
|
||||
self.leaves = leaves
|
||||
|
||||
@staticmethod
|
||||
def resolve(packages: Iterable[Package]) -> List[List[Package]]:
|
||||
def resolve(packages: Iterable[Package]) -> list[list[Package]]:
|
||||
"""
|
||||
resolve dependency tree
|
||||
|
||||
@ -137,20 +137,20 @@ class Tree:
|
||||
packages(Iterable[Package]): packages list
|
||||
|
||||
Returns:
|
||||
List[List[Package]]: list of packages lists based on their dependencies
|
||||
list[list[Package]]: list of packages lists based on their dependencies
|
||||
"""
|
||||
leaves = [Leaf(package) for package in packages]
|
||||
instance = Tree(leaves)
|
||||
return instance.levels()
|
||||
|
||||
def levels(self) -> List[List[Package]]:
|
||||
def levels(self) -> list[list[Package]]:
|
||||
"""
|
||||
get build levels starting from the packages which do not require any other package to build
|
||||
|
||||
Returns:
|
||||
List[List[Package]]: sorted list of packages lists based on their dependencies
|
||||
list[list[Package]]: sorted list of packages lists based on their dependencies
|
||||
"""
|
||||
unsorted: List[List[Leaf]] = []
|
||||
unsorted: list[list[Leaf]] = []
|
||||
|
||||
# build initial tree
|
||||
unprocessed = self.leaves[:]
|
||||
|
@ -19,8 +19,6 @@
|
||||
#
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Iterable, List, Optional, Type
|
||||
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.configuration.schema import ConfigurationSchema
|
||||
from ahriman.core.log import LazyLogging
|
||||
@ -34,7 +32,7 @@ class Trigger(LazyLogging):
|
||||
|
||||
Attributes:
|
||||
CONFIGURATION_SCHEMA(ConfigurationSchema): (class attribute) configuration schema template
|
||||
CONFIGURATION_SCHEMA_FALLBACK(Optional[str]): (class attribute) optional fallback option for defining
|
||||
CONFIGURATION_SCHEMA_FALLBACK(str | None): (class attribute) optional fallback option for defining
|
||||
configuration schema type used
|
||||
architecture(str): repository architecture
|
||||
configuration(Configuration): configuration instance
|
||||
@ -43,7 +41,7 @@ class Trigger(LazyLogging):
|
||||
This class must be used in order to create own extension. Basically idea is the following::
|
||||
|
||||
>>> class CustomTrigger(Trigger):
|
||||
>>> def on_result(self, result: Result, packages: Iterable[Package]) -> None:
|
||||
>>> def on_result(self, result: Result, packages: list[Package]) -> None:
|
||||
>>> perform_some_action()
|
||||
|
||||
Having this class you can pass it to ``configuration`` and it will be run on action::
|
||||
@ -58,7 +56,7 @@ class Trigger(LazyLogging):
|
||||
"""
|
||||
|
||||
CONFIGURATION_SCHEMA: ConfigurationSchema = {}
|
||||
CONFIGURATION_SCHEMA_FALLBACK: Optional[str] = None
|
||||
CONFIGURATION_SCHEMA_FALLBACK: str | None = None
|
||||
|
||||
def __init__(self, architecture: str, configuration: Configuration) -> None:
|
||||
"""
|
||||
@ -72,8 +70,8 @@ class Trigger(LazyLogging):
|
||||
self.configuration = configuration
|
||||
|
||||
@classmethod
|
||||
def configuration_schema(cls: Type[Trigger], architecture: str,
|
||||
configuration: Optional[Configuration]) -> ConfigurationSchema:
|
||||
def configuration_schema(cls: type[Trigger], architecture: str,
|
||||
configuration: Configuration | None) -> ConfigurationSchema:
|
||||
"""
|
||||
configuration schema based on supplied service configuration
|
||||
|
||||
@ -82,7 +80,7 @@ class Trigger(LazyLogging):
|
||||
|
||||
Args:
|
||||
architecture(str): repository architecture
|
||||
configuration(Optional[Configuration]): configuration instance. If set to None, the default schema
|
||||
configuration(Configuration | None): configuration instance. If set to None, the default schema
|
||||
should be returned
|
||||
|
||||
Returns:
|
||||
@ -104,7 +102,7 @@ class Trigger(LazyLogging):
|
||||
return result
|
||||
|
||||
@classmethod
|
||||
def configuration_sections(cls: Type[Trigger], configuration: Configuration) -> List[str]:
|
||||
def configuration_sections(cls: type[Trigger], configuration: Configuration) -> list[str]:
|
||||
"""
|
||||
extract configuration sections from configuration
|
||||
|
||||
@ -112,26 +110,26 @@ class Trigger(LazyLogging):
|
||||
configuration(Configuration): configuration instance
|
||||
|
||||
Returns:
|
||||
List[str]: read configuration sections belong to this trigger
|
||||
list[str]: read configuration sections belong to this trigger
|
||||
|
||||
Examples:
|
||||
This method can be used in order to extract specific configuration sections which are set by user, e.g.
|
||||
from sources::
|
||||
|
||||
>>> @staticmethod
|
||||
>>> def configuration_sections(cls: Type[Trigger], configuration: Configuration) -> List[str]:
|
||||
>>> def configuration_sections(cls: type[Trigger], configuration: Configuration) -> list[str]:
|
||||
>>> return configuration.getlist("report", "target", fallback=[])
|
||||
"""
|
||||
del configuration
|
||||
return []
|
||||
|
||||
def on_result(self, result: Result, packages: Iterable[Package]) -> None:
|
||||
def on_result(self, result: Result, packages: list[Package]) -> None:
|
||||
"""
|
||||
trigger action which will be called after build process with process result
|
||||
|
||||
Args:
|
||||
result(Result): build result
|
||||
packages(Iterable[Package]): list of all available packages
|
||||
packages(list[Package]): list of all available packages
|
||||
"""
|
||||
if (run := getattr(self, "run", None)) is not None:
|
||||
run(result, packages) # compatibility with old triggers
|
||||
|
@ -23,9 +23,9 @@ import contextlib
|
||||
import importlib
|
||||
import os
|
||||
|
||||
from collections.abc import Generator
|
||||
from pathlib import Path
|
||||
from types import ModuleType
|
||||
from typing import Generator, Iterable, List, Type
|
||||
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.exceptions import ExtensionError
|
||||
@ -40,7 +40,7 @@ class TriggerLoader(LazyLogging):
|
||||
trigger loader class
|
||||
|
||||
Attributes:
|
||||
triggers(List[Trigger]): list of loaded triggers according to the configuration
|
||||
triggers(list[Trigger]): list of loaded triggers according to the configuration
|
||||
|
||||
Examples:
|
||||
This class more likely must not be used directly, but the usual workflow is the following::
|
||||
@ -63,10 +63,10 @@ class TriggerLoader(LazyLogging):
|
||||
default constructor
|
||||
"""
|
||||
self._on_stop_requested = False
|
||||
self.triggers: List[Trigger] = []
|
||||
self.triggers: list[Trigger] = []
|
||||
|
||||
@classmethod
|
||||
def load(cls: Type[TriggerLoader], architecture: str, configuration: Configuration) -> TriggerLoader:
|
||||
def load(cls: type[TriggerLoader], architecture: str, configuration: Configuration) -> TriggerLoader:
|
||||
"""
|
||||
create instance from configuration
|
||||
|
||||
@ -86,7 +86,7 @@ class TriggerLoader(LazyLogging):
|
||||
return instance
|
||||
|
||||
@staticmethod
|
||||
def selected_triggers(configuration: Configuration) -> List[str]:
|
||||
def selected_triggers(configuration: Configuration) -> list[str]:
|
||||
"""
|
||||
read configuration and return triggers which are set by settings
|
||||
|
||||
@ -94,7 +94,7 @@ class TriggerLoader(LazyLogging):
|
||||
configuration(Configuration): configuration instance
|
||||
|
||||
Returns:
|
||||
List[str]: list of triggers according to configuration
|
||||
list[str]: list of triggers according to configuration
|
||||
"""
|
||||
return configuration.getlist("build", "triggers", fallback=[])
|
||||
|
||||
@ -176,7 +176,7 @@ class TriggerLoader(LazyLogging):
|
||||
|
||||
return trigger
|
||||
|
||||
def load_trigger_class(self, module_path: str) -> Type[Trigger]:
|
||||
def load_trigger_class(self, module_path: str) -> type[Trigger]:
|
||||
"""
|
||||
load trigger class by module path
|
||||
|
||||
@ -184,7 +184,7 @@ class TriggerLoader(LazyLogging):
|
||||
module_path(str): module import path to load
|
||||
|
||||
Returns:
|
||||
Type[Trigger]: loaded trigger type by module path
|
||||
type[Trigger]: loaded trigger type by module path
|
||||
|
||||
Raises:
|
||||
InvalidExtension: in case if module cannot be loaded from the specified module path or is not a trigger
|
||||
@ -208,13 +208,13 @@ class TriggerLoader(LazyLogging):
|
||||
self.logger.info("loaded type %s of package %s", class_name, package_or_path)
|
||||
return trigger_type
|
||||
|
||||
def on_result(self, result: Result, packages: Iterable[Package]) -> None:
|
||||
def on_result(self, result: Result, packages: list[Package]) -> None:
|
||||
"""
|
||||
run trigger with result of application run
|
||||
|
||||
Args:
|
||||
result(Result): build result
|
||||
packages(Iterable[Package]): list of all available packages
|
||||
packages(list[Package]): list of all available packages
|
||||
"""
|
||||
self.logger.debug("executing triggers on result")
|
||||
for trigger in self.triggers:
|
||||
|
@ -21,7 +21,7 @@ import mimetypes
|
||||
import requests
|
||||
|
||||
from pathlib import Path
|
||||
from typing import Any, Dict, Iterable, Optional
|
||||
from typing import Any
|
||||
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.upload.http_upload import HttpUpload
|
||||
@ -51,12 +51,12 @@ class Github(HttpUpload):
|
||||
self.github_owner = configuration.get(section, "owner")
|
||||
self.github_repository = configuration.get(section, "repository")
|
||||
|
||||
def asset_remove(self, release: Dict[str, Any], name: str) -> None:
|
||||
def asset_remove(self, release: dict[str, Any], name: str) -> None:
|
||||
"""
|
||||
remove asset from the release by name
|
||||
|
||||
Args:
|
||||
release(Dict[str, Any]): release object
|
||||
release(dict[str, Any]): release object
|
||||
name(str): asset name
|
||||
"""
|
||||
try:
|
||||
@ -65,12 +65,12 @@ class Github(HttpUpload):
|
||||
except StopIteration:
|
||||
self.logger.info("no asset %s found in release %s", name, release["name"])
|
||||
|
||||
def asset_upload(self, release: Dict[str, Any], path: Path) -> None:
|
||||
def asset_upload(self, release: dict[str, Any], path: Path) -> None:
|
||||
"""
|
||||
upload asset to the release
|
||||
|
||||
Args:
|
||||
release(Dict[str, Any]): release object
|
||||
release(dict[str, Any]): release object
|
||||
path(Path): path to local file
|
||||
"""
|
||||
exists = any(path.name == asset["name"] for asset in release["assets"])
|
||||
@ -81,7 +81,7 @@ class Github(HttpUpload):
|
||||
headers = {"Content-Type": mime} if mime is not None else {"Content-Type": "application/octet-stream"}
|
||||
self._request("POST", url, params={"name": path.name}, data=path.open("rb"), headers=headers)
|
||||
|
||||
def get_local_files(self, path: Path) -> Dict[Path, str]:
|
||||
def get_local_files(self, path: Path) -> dict[Path, str]:
|
||||
"""
|
||||
get all local files and their calculated checksums
|
||||
|
||||
@ -89,21 +89,21 @@ class Github(HttpUpload):
|
||||
path(Path): local path to sync
|
||||
|
||||
Returns:
|
||||
Dict[Path, str]: map of path objects to its checksum
|
||||
dict[Path, str]: map of path objects to its checksum
|
||||
"""
|
||||
return {
|
||||
local_file: self.calculate_hash(local_file)
|
||||
for local_file in walk(path)
|
||||
}
|
||||
|
||||
def files_remove(self, release: Dict[str, Any], local_files: Dict[Path, str], remote_files: Dict[str, str]) -> None:
|
||||
def files_remove(self, release: dict[str, Any], local_files: dict[Path, str], remote_files: dict[str, str]) -> None:
|
||||
"""
|
||||
remove files from github
|
||||
|
||||
Args:
|
||||
release(Dict[str, Any]): release object
|
||||
local_files(Dict[Path, str]): map of local file paths to its checksum
|
||||
remote_files(Dict[str, str]): map of the remote files and its checksum
|
||||
release(dict[str, Any]): release object
|
||||
local_files(dict[Path, str]): map of local file paths to its checksum
|
||||
remote_files(dict[str, str]): map of the remote files and its checksum
|
||||
"""
|
||||
local_filenames = {local_file.name for local_file in local_files}
|
||||
for remote_file in remote_files:
|
||||
@ -111,14 +111,14 @@ class Github(HttpUpload):
|
||||
continue
|
||||
self.asset_remove(release, remote_file)
|
||||
|
||||
def files_upload(self, release: Dict[str, Any], local_files: Dict[Path, str], remote_files: Dict[str, str]) -> None:
|
||||
def files_upload(self, release: dict[str, Any], local_files: dict[Path, str], remote_files: dict[str, str]) -> None:
|
||||
"""
|
||||
upload files to github
|
||||
|
||||
Args:
|
||||
release(Dict[str, Any]): release object
|
||||
local_files(Dict[Path, str]): map of local file paths to its checksum
|
||||
remote_files(Dict[str, str]): map of the remote files and its checksum
|
||||
release(dict[str, Any]): release object
|
||||
local_files(dict[Path, str]): map of local file paths to its checksum
|
||||
remote_files(dict[str, str]): map of the remote files and its checksum
|
||||
"""
|
||||
for local_file, checksum in local_files.items():
|
||||
remote_checksum = remote_files.get(local_file.name)
|
||||
@ -126,29 +126,29 @@ class Github(HttpUpload):
|
||||
continue
|
||||
self.asset_upload(release, local_file)
|
||||
|
||||
def release_create(self) -> Dict[str, Any]:
|
||||
def release_create(self) -> dict[str, Any]:
|
||||
"""
|
||||
create empty release
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: github API release object for the new release
|
||||
dict[str, Any]: github API release object for the new release
|
||||
"""
|
||||
url = f"https://api.github.com/repos/{self.github_owner}/{self.github_repository}/releases"
|
||||
response = self._request("POST", url, json={"tag_name": self.architecture, "name": self.architecture})
|
||||
release: Dict[str, Any] = response.json()
|
||||
release: dict[str, Any] = response.json()
|
||||
return release
|
||||
|
||||
def release_get(self) -> Optional[Dict[str, Any]]:
|
||||
def release_get(self) -> dict[str, Any] | None:
|
||||
"""
|
||||
get release object if any
|
||||
|
||||
Returns:
|
||||
Optional[Dict[str, Any]]: github API release object if release found and None otherwise
|
||||
dict[str, Any] | None: github API release object if release found and None otherwise
|
||||
"""
|
||||
url = f"https://api.github.com/repos/{self.github_owner}/{self.github_repository}/releases/tags/{self.architecture}"
|
||||
try:
|
||||
response = self._request("GET", url)
|
||||
release: Dict[str, Any] = response.json()
|
||||
release: dict[str, Any] = response.json()
|
||||
return release
|
||||
except requests.HTTPError as e:
|
||||
status_code = e.response.status_code if e.response is not None else None
|
||||
@ -156,23 +156,23 @@ class Github(HttpUpload):
|
||||
return None
|
||||
raise
|
||||
|
||||
def release_update(self, release: Dict[str, Any], body: str) -> None:
|
||||
def release_update(self, release: dict[str, Any], body: str) -> None:
|
||||
"""
|
||||
update release
|
||||
|
||||
Args:
|
||||
release(Dict[str, Any]): release object
|
||||
release(dict[str, Any]): release object
|
||||
body(str): new release body
|
||||
"""
|
||||
self._request("POST", release["url"], json={"body": body})
|
||||
|
||||
def sync(self, path: Path, built_packages: Iterable[Package]) -> None:
|
||||
def sync(self, path: Path, built_packages: list[Package]) -> None:
|
||||
"""
|
||||
sync data to remote server
|
||||
|
||||
Args:
|
||||
path(Path): local path to sync
|
||||
built_packages(Iterable[Package]): list of packages which has just been built
|
||||
built_packages(list[Package]): list of packages which has just been built
|
||||
"""
|
||||
release = self.release_get()
|
||||
if release is None:
|
||||
|
@ -21,7 +21,7 @@ import hashlib
|
||||
import requests
|
||||
|
||||
from pathlib import Path
|
||||
from typing import Any, Dict
|
||||
from typing import Any
|
||||
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.upload.upload import Upload
|
||||
@ -33,7 +33,7 @@ class HttpUpload(Upload):
|
||||
helper for the http based uploads
|
||||
|
||||
Attributes:
|
||||
auth(Optional[Tuple[str, str]]): HTTP auth object if set
|
||||
auth(tuple[str, str] | None): HTTP auth object if set
|
||||
timeout(int): HTTP request timeout in seconds
|
||||
"""
|
||||
|
||||
@ -68,12 +68,12 @@ class HttpUpload(Upload):
|
||||
return md5.hexdigest()
|
||||
|
||||
@staticmethod
|
||||
def get_body(local_files: Dict[Path, str]) -> str:
|
||||
def get_body(local_files: dict[Path, str]) -> str:
|
||||
"""
|
||||
generate release body from the checksums as returned from HttpUpload.get_hashes method
|
||||
|
||||
Args:
|
||||
local_files(Dict[Path, str]): map of the paths to its checksum
|
||||
local_files(dict[Path, str]): map of the paths to its checksum
|
||||
|
||||
Returns:
|
||||
str: body to be inserted into release
|
||||
@ -81,7 +81,7 @@ class HttpUpload(Upload):
|
||||
return "\n".join(f"{file.name} {md5}" for file, md5 in sorted(local_files.items()))
|
||||
|
||||
@staticmethod
|
||||
def get_hashes(body: str) -> Dict[str, str]:
|
||||
def get_hashes(body: str) -> dict[str, str]:
|
||||
"""
|
||||
get checksums of the content from the repository
|
||||
|
||||
@ -89,7 +89,7 @@ class HttpUpload(Upload):
|
||||
body(str): release string body object
|
||||
|
||||
Returns:
|
||||
Dict[str, str]: map of the filename to its checksum as it is written in body
|
||||
dict[str, str]: map of the filename to its checksum as it is written in body
|
||||
"""
|
||||
files = {}
|
||||
for line in body.splitlines():
|
||||
|
@ -18,7 +18,6 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
from pathlib import Path
|
||||
from typing import Iterable
|
||||
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.upload.upload import Upload
|
||||
@ -31,7 +30,7 @@ class Rsync(Upload):
|
||||
rsync wrapper
|
||||
|
||||
Attributes:
|
||||
command(List[str]): command arguments for sync
|
||||
command(list[str]): command arguments for sync
|
||||
remote(str): remote address to sync
|
||||
"""
|
||||
|
||||
@ -50,12 +49,12 @@ class Rsync(Upload):
|
||||
self.command = configuration.getlist(section, "command")
|
||||
self.remote = configuration.get(section, "remote")
|
||||
|
||||
def sync(self, path: Path, built_packages: Iterable[Package]) -> None:
|
||||
def sync(self, path: Path, built_packages: list[Package]) -> None:
|
||||
"""
|
||||
sync data to remote server
|
||||
|
||||
Args:
|
||||
path(Path): local path to sync
|
||||
built_packages(Iterable[Package]): list of packages which has just been built
|
||||
built_packages(list[Package]): list of packages which has just been built
|
||||
"""
|
||||
Rsync._check_output(*self.command, str(path), self.remote, logger=self.logger)
|
||||
|
@ -22,7 +22,7 @@ import hashlib
|
||||
import mimetypes
|
||||
|
||||
from pathlib import Path
|
||||
from typing import Any, Dict, Iterable
|
||||
from typing import Any
|
||||
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.upload.upload import Upload
|
||||
@ -97,27 +97,27 @@ class S3(Upload):
|
||||
return client.Bucket(configuration.get(section, "bucket"))
|
||||
|
||||
@staticmethod
|
||||
def files_remove(local_files: Dict[Path, str], remote_objects: Dict[Path, Any]) -> None:
|
||||
def files_remove(local_files: dict[Path, str], remote_objects: dict[Path, Any]) -> None:
|
||||
"""
|
||||
remove files which have been removed locally
|
||||
|
||||
Args:
|
||||
local_files(Dict[Path, str]): map of local path object to its checksum
|
||||
remote_objects(Dict[Path, Any]): map of remote path object to the remote s3 object
|
||||
local_files(dict[Path, str]): map of local path object to its checksum
|
||||
remote_objects(dict[Path, Any]): map of remote path object to the remote s3 object
|
||||
"""
|
||||
for local_file, remote_object in remote_objects.items():
|
||||
if local_file in local_files:
|
||||
continue
|
||||
remote_object.delete()
|
||||
|
||||
def files_upload(self, path: Path, local_files: Dict[Path, str], remote_objects: Dict[Path, Any]) -> None:
|
||||
def files_upload(self, path: Path, local_files: dict[Path, str], remote_objects: dict[Path, Any]) -> None:
|
||||
"""
|
||||
upload changed files to s3
|
||||
|
||||
Args:
|
||||
path(Path): local path to sync
|
||||
local_files(Dict[Path, str]): map of local path object to its checksum
|
||||
remote_objects(Dict[Path, Any]): map of remote path object to the remote s3 object
|
||||
local_files(dict[Path, str]): map of local path object to its checksum
|
||||
remote_objects(dict[Path, Any]): map of remote path object to the remote s3 object
|
||||
"""
|
||||
for local_file, checksum in local_files.items():
|
||||
remote_object = remote_objects.get(local_file)
|
||||
@ -133,7 +133,7 @@ class S3(Upload):
|
||||
|
||||
self.bucket.upload_file(Filename=str(local_path), Key=str(remote_path), ExtraArgs=extra_args)
|
||||
|
||||
def get_local_files(self, path: Path) -> Dict[Path, str]:
|
||||
def get_local_files(self, path: Path) -> dict[Path, str]:
|
||||
"""
|
||||
get all local files and their calculated checksums
|
||||
|
||||
@ -141,30 +141,30 @@ class S3(Upload):
|
||||
path(Path): local path to sync
|
||||
|
||||
Returns:
|
||||
Dict[Path, str]: map of path object to its checksum
|
||||
dict[Path, str]: map of path object to its checksum
|
||||
"""
|
||||
return {
|
||||
local_file.relative_to(path): self.calculate_etag(local_file, self.chunk_size)
|
||||
for local_file in walk(path)
|
||||
}
|
||||
|
||||
def get_remote_objects(self) -> Dict[Path, Any]:
|
||||
def get_remote_objects(self) -> dict[Path, Any]:
|
||||
"""
|
||||
get all remote objects and their checksums
|
||||
|
||||
Returns:
|
||||
Dict[Path, Any]: map of path object to the remote s3 object
|
||||
dict[Path, Any]: map of path object to the remote s3 object
|
||||
"""
|
||||
objects = self.bucket.objects.filter(Prefix=self.architecture)
|
||||
return {Path(item.key).relative_to(self.architecture): item for item in objects}
|
||||
|
||||
def sync(self, path: Path, built_packages: Iterable[Package]) -> None:
|
||||
def sync(self, path: Path, built_packages: list[Package]) -> None:
|
||||
"""
|
||||
sync data to remote server
|
||||
|
||||
Args:
|
||||
path(Path): local path to sync
|
||||
built_packages(Iterable[Package]): list of packages which has just been built
|
||||
built_packages(list[Package]): list of packages which has just been built
|
||||
"""
|
||||
remote_objects = self.get_remote_objects()
|
||||
local_files = self.get_local_files(path)
|
||||
|
@ -20,7 +20,6 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
from typing import Iterable, Type
|
||||
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.exceptions import SynchronizationError
|
||||
@ -68,7 +67,7 @@ class Upload(LazyLogging):
|
||||
self.configuration = configuration
|
||||
|
||||
@classmethod
|
||||
def load(cls: Type[Upload], architecture: str, configuration: Configuration, target: str) -> Upload:
|
||||
def load(cls: type[Upload], architecture: str, configuration: Configuration, target: str) -> Upload:
|
||||
"""
|
||||
load client from settings
|
||||
|
||||
@ -93,13 +92,13 @@ class Upload(LazyLogging):
|
||||
return Github(architecture, configuration, section)
|
||||
return cls(architecture, configuration) # should never happen
|
||||
|
||||
def run(self, path: Path, built_packages: Iterable[Package]) -> None:
|
||||
def run(self, path: Path, built_packages: list[Package]) -> None:
|
||||
"""
|
||||
run remote sync
|
||||
|
||||
Args:
|
||||
path(Path): local path to sync
|
||||
built_packages(Iterable[Package]): list of packages which has just been built
|
||||
built_packages(list[Package]): list of packages which has just been built
|
||||
|
||||
Raises:
|
||||
SyncFailed: in case of any synchronization unmatched exception
|
||||
@ -110,11 +109,11 @@ class Upload(LazyLogging):
|
||||
self.logger.exception("remote sync failed")
|
||||
raise SynchronizationError()
|
||||
|
||||
def sync(self, path: Path, built_packages: Iterable[Package]) -> None:
|
||||
def sync(self, path: Path, built_packages: list[Package]) -> None:
|
||||
"""
|
||||
sync data to remote server
|
||||
|
||||
Args:
|
||||
path(Path): local path to sync
|
||||
built_packages(Iterable[Package]): list of packages which has just been built
|
||||
built_packages(list[Package]): list of packages which has just been built
|
||||
"""
|
||||
|
@ -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/>.
|
||||
#
|
||||
from typing import Iterable, List, Type
|
||||
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.triggers import Trigger
|
||||
from ahriman.core.upload.upload import Upload
|
||||
@ -31,7 +29,7 @@ class UploadTrigger(Trigger):
|
||||
synchronization trigger
|
||||
|
||||
Attributes:
|
||||
targets(List[str]): upload target list
|
||||
targets(list[str]): upload target list
|
||||
"""
|
||||
|
||||
CONFIGURATION_SCHEMA = {
|
||||
@ -138,7 +136,7 @@ class UploadTrigger(Trigger):
|
||||
self.targets = self.configuration_sections(configuration)
|
||||
|
||||
@classmethod
|
||||
def configuration_sections(cls: Type[Trigger], configuration: Configuration) -> List[str]:
|
||||
def configuration_sections(cls: type[Trigger], configuration: Configuration) -> list[str]:
|
||||
"""
|
||||
extract configuration sections from configuration
|
||||
|
||||
@ -146,17 +144,17 @@ class UploadTrigger(Trigger):
|
||||
configuration(Configuration): configuration instance
|
||||
|
||||
Returns:
|
||||
List[str]: read configuration sections belong to this trigger
|
||||
list[str]: read configuration sections belong to this trigger
|
||||
"""
|
||||
return configuration.getlist("upload", "target", fallback=[])
|
||||
|
||||
def on_result(self, result: Result, packages: Iterable[Package]) -> None:
|
||||
def on_result(self, result: Result, packages: list[Package]) -> None:
|
||||
"""
|
||||
run trigger
|
||||
|
||||
Args:
|
||||
result(Result): build result
|
||||
packages(Iterable[Package]): list of all available packages
|
||||
packages(list[Package]): list of all available packages
|
||||
"""
|
||||
for target in self.targets:
|
||||
runner = Upload.load(self.architecture, self.configuration, target)
|
||||
|
@ -26,10 +26,11 @@ import re
|
||||
import requests
|
||||
import subprocess
|
||||
|
||||
from collections.abc import Callable, Generator, Iterable
|
||||
from enum import Enum
|
||||
from pathlib import Path
|
||||
from pwd import getpwuid
|
||||
from typing import Any, Callable, Dict, Generator, IO, Iterable, List, Optional, Tuple, Type, TypeVar, Union
|
||||
from typing import Any, IO, TypeVar
|
||||
|
||||
from ahriman.core.exceptions import OptionError, UnsafeRunError
|
||||
from ahriman.models.repository_paths import RepositoryPaths
|
||||
@ -56,20 +57,19 @@ __all__ = [
|
||||
T = TypeVar("T")
|
||||
|
||||
|
||||
def check_output(*args: str, exception: Optional[Exception] = None, cwd: Optional[Path] = None,
|
||||
input_data: Optional[str] = None, logger: Optional[logging.Logger] = None,
|
||||
user: Optional[int] = None) -> str:
|
||||
def check_output(*args: str, exception: Exception | None = None, cwd: Path | None = None, input_data: str | None = None,
|
||||
logger: logging.Logger | None = None, user: int | None = None) -> str:
|
||||
"""
|
||||
subprocess wrapper
|
||||
|
||||
Args:
|
||||
*args(str): command line arguments
|
||||
exception(Optional[Exception], optional): exception which has to be reraised instead of default subprocess
|
||||
exception(Exception | None, optional): exception which has to be reraised instead of default subprocess
|
||||
exception (Default value = None)
|
||||
cwd(Optional[Path], optional): current working directory (Default value = None)
|
||||
input_data(Optional[str], optional): data which will be written to command stdin (Default value = None)
|
||||
logger(Optional[logging.Logger], optional): logger to log command result if required (Default value = None)
|
||||
user(Optional[int], optional): run process as specified user (Default value = None)
|
||||
cwd(Path | None, optional): current working directory (Default value = None)
|
||||
input_data(str | None, optional): data which will be written to command stdin (Default value = None)
|
||||
logger(logging.Logger | None, optional): logger to log command result if required (Default value = None)
|
||||
user(int | None, optional): run process as specified user (Default value = None)
|
||||
|
||||
Returns:
|
||||
str: command output
|
||||
@ -94,9 +94,9 @@ def check_output(*args: str, exception: Optional[Exception] = None, cwd: Optiona
|
||||
|
||||
>>> check_output("false", exception=RuntimeError("An exception occurred"))
|
||||
"""
|
||||
# hack for Optional[IO[str]] handle
|
||||
# hack for IO[str] handle
|
||||
def get_io(proc: subprocess.Popen[str], channel_name: str) -> IO[str]:
|
||||
channel: Optional[IO[str]] = getattr(proc, channel_name, None)
|
||||
channel: IO[str] | None = getattr(proc, channel_name, None)
|
||||
return channel if channel is not None else io.StringIO()
|
||||
|
||||
def log(single: str) -> None:
|
||||
@ -114,7 +114,7 @@ def check_output(*args: str, exception: Optional[Exception] = None, cwd: Optiona
|
||||
input_channel.close()
|
||||
|
||||
# read stdout and append to output result
|
||||
result: List[str] = []
|
||||
result: list[str] = []
|
||||
for line in iter(get_io(process, "stdout").readline, ""):
|
||||
line = line.strip()
|
||||
if not line: # skip empty lines
|
||||
@ -162,15 +162,15 @@ def check_user(paths: RepositoryPaths, *, unsafe: bool) -> None:
|
||||
raise UnsafeRunError(current_uid, root_uid)
|
||||
|
||||
|
||||
def enum_values(enum: Type[Enum]) -> List[str]:
|
||||
def enum_values(enum: type[Enum]) -> list[str]:
|
||||
"""
|
||||
generate list of enumeration values from the source
|
||||
|
||||
Args:
|
||||
enum(Type[Enum]): source enumeration class
|
||||
enum(type[Enum]): source enumeration class
|
||||
|
||||
Returns:
|
||||
List[str]: available enumeration values as string
|
||||
list[str]: available enumeration values as string
|
||||
"""
|
||||
return [str(key.value) for key in enum] # explicit str conversion for typing
|
||||
|
||||
@ -189,16 +189,16 @@ def exception_response_text(exception: requests.exceptions.HTTPError) -> str:
|
||||
return result
|
||||
|
||||
|
||||
def filter_json(source: Dict[str, Any], known_fields: Iterable[str]) -> Dict[str, Any]:
|
||||
def filter_json(source: dict[str, Any], known_fields: Iterable[str]) -> dict[str, Any]:
|
||||
"""
|
||||
filter json object by fields used for json-to-object conversion
|
||||
|
||||
Args:
|
||||
source(Dict[str, Any]): raw json object
|
||||
source(dict[str, Any]): raw json object
|
||||
known_fields(Iterable[str]): list of fields which have to be known for the target object
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: json object without unknown and empty fields
|
||||
dict[str, Any]: json object without unknown and empty fields
|
||||
|
||||
Examples:
|
||||
This wrapper is mainly used for the dataclasses, thus the flow must be something like this::
|
||||
@ -213,12 +213,12 @@ def filter_json(source: Dict[str, Any], known_fields: Iterable[str]) -> Dict[str
|
||||
return {key: value for key, value in source.items() if key in known_fields and value is not None}
|
||||
|
||||
|
||||
def full_version(epoch: Union[str, int, None], pkgver: str, pkgrel: str) -> str:
|
||||
def full_version(epoch: str | int | None, pkgver: str, pkgrel: str) -> str:
|
||||
"""
|
||||
generate full version from components
|
||||
|
||||
Args:
|
||||
epoch(Union[str, int, None]): package epoch if any
|
||||
epoch(str | int | None): package epoch if any
|
||||
pkgver(str): package version
|
||||
pkgrel(str): package release version (arch linux specific)
|
||||
|
||||
@ -243,27 +243,27 @@ def package_like(filename: Path) -> bool:
|
||||
return ".pkg." in name and not name.endswith(".sig")
|
||||
|
||||
|
||||
def partition(source: List[T], predicate: Callable[[T], bool]) -> Tuple[List[T], List[T]]:
|
||||
def partition(source: list[T], predicate: Callable[[T], bool]) -> tuple[list[T], list[T]]:
|
||||
"""
|
||||
partition list into two based on predicate, based on # https://docs.python.org/dev/library/itertools.html#itertools-recipes
|
||||
|
||||
Args:
|
||||
source(List[T]): source list to be partitioned
|
||||
source(list[T]): source list to be partitioned
|
||||
predicate(Callable[[T], bool]): filter function
|
||||
|
||||
Returns:
|
||||
Tuple[List[T], List[T]]: two lists, first is which ``predicate`` is ``True``, second is ``False``
|
||||
tuple[list[T], list[T]]: two lists, first is which ``predicate`` is ``True``, second is ``False``
|
||||
"""
|
||||
first_iter, second_iter = itertools.tee(source)
|
||||
return list(filter(predicate, first_iter)), list(itertools.filterfalse(predicate, second_iter))
|
||||
|
||||
|
||||
def pretty_datetime(timestamp: Optional[Union[datetime.datetime, float, int]]) -> str:
|
||||
def pretty_datetime(timestamp: datetime.datetime | float | int | None) -> str:
|
||||
"""
|
||||
convert datetime object to string
|
||||
|
||||
Args:
|
||||
timestamp(Optional[Union[datetime.datetime, float, int]]): datetime to convert
|
||||
timestamp(datetime.datetime | float | int | None): datetime to convert
|
||||
|
||||
Returns:
|
||||
str: pretty printable datetime as string
|
||||
@ -275,12 +275,12 @@ def pretty_datetime(timestamp: Optional[Union[datetime.datetime, float, int]]) -
|
||||
return timestamp.strftime("%Y-%m-%d %H:%M:%S")
|
||||
|
||||
|
||||
def pretty_size(size: Optional[float], level: int = 0) -> str:
|
||||
def pretty_size(size: float | None, level: int = 0) -> str:
|
||||
"""
|
||||
convert size to string
|
||||
|
||||
Args:
|
||||
size(Optional[float]): size to convert
|
||||
size(float | None): size to convert
|
||||
level(int, optional): represents current units, 0 is B, 1 is KiB, etc (Default value = 0)
|
||||
|
||||
Returns:
|
||||
|
@ -22,9 +22,10 @@ from __future__ import annotations
|
||||
import datetime
|
||||
import inflection
|
||||
|
||||
from collections.abc import Callable
|
||||
from dataclasses import dataclass, field, fields
|
||||
from pyalpm import Package # type: ignore
|
||||
from typing import Any, Callable, Dict, List, Optional, Type
|
||||
from typing import Any
|
||||
|
||||
from ahriman.core.util import filter_json, full_version
|
||||
|
||||
@ -40,23 +41,23 @@ class AURPackage:
|
||||
package_base_id(int): package base ID
|
||||
version(str): package base version
|
||||
description(str): package base description
|
||||
url(Optional[str]): package upstream URL
|
||||
url(str | None): package upstream URL
|
||||
num_votes(int): number of votes for the package
|
||||
popularity(float): package popularity
|
||||
out_of_date(Optional[datetime.datetime]): package out of date timestamp if any
|
||||
maintainer(Optional[str]): package maintainer
|
||||
submitter(Optional[str]): package first submitter
|
||||
out_of_date(datetime.datetime | None): package out of date timestamp if any
|
||||
maintainer(str | None): package maintainer
|
||||
submitter(str | None): package first submitter
|
||||
first_submitted(datetime.datetime): timestamp of the first package submission
|
||||
last_modified(datetime.datetime): timestamp of the last package submission
|
||||
url_path(str): AUR package path
|
||||
repository(str): repository name of the package
|
||||
depends(List[str]): list of package dependencies
|
||||
make_depends(List[str]): list of package make dependencies
|
||||
opt_depends(List[str]): list of package optional dependencies
|
||||
conflicts(List[str]): conflicts list for the package
|
||||
provides(List[str]): list of packages which this package provides
|
||||
license(List[str]): list of package licenses
|
||||
keywords(List[str]): list of package keywords
|
||||
depends(list[str]): list of package dependencies
|
||||
make_depends(l[str]): list of package make dependencies
|
||||
opt_depends(list[str]): list of package optional dependencies
|
||||
conflicts(list[str]): conflicts list for the package
|
||||
provides(list[str]): list of packages which this package provides
|
||||
license(list[str]): list of package licenses
|
||||
keywords(list[str]): list of package keywords
|
||||
|
||||
Examples:
|
||||
Mainly this class must be used from class methods instead of default ``__init__``::
|
||||
@ -87,26 +88,26 @@ class AURPackage:
|
||||
last_modified: datetime.datetime
|
||||
url_path: str
|
||||
description: str = "" # despite the fact that the field is required some packages don't have it
|
||||
url: Optional[str] = None
|
||||
out_of_date: Optional[datetime.datetime] = None
|
||||
maintainer: Optional[str] = None
|
||||
submitter: Optional[str] = None
|
||||
url: str | None = None
|
||||
out_of_date: datetime.datetime | None = None
|
||||
maintainer: str | None = None
|
||||
submitter: str | None = None
|
||||
repository: str = "aur"
|
||||
depends: List[str] = field(default_factory=list)
|
||||
make_depends: List[str] = field(default_factory=list)
|
||||
opt_depends: List[str] = field(default_factory=list)
|
||||
conflicts: List[str] = field(default_factory=list)
|
||||
provides: List[str] = field(default_factory=list)
|
||||
license: List[str] = field(default_factory=list)
|
||||
keywords: List[str] = field(default_factory=list)
|
||||
depends: list[str] = field(default_factory=list)
|
||||
make_depends: list[str] = field(default_factory=list)
|
||||
opt_depends: list[str] = field(default_factory=list)
|
||||
conflicts: list[str] = field(default_factory=list)
|
||||
provides: list[str] = field(default_factory=list)
|
||||
license: list[str] = field(default_factory=list)
|
||||
keywords: list[str] = field(default_factory=list)
|
||||
|
||||
@classmethod
|
||||
def from_json(cls: Type[AURPackage], dump: Dict[str, Any]) -> AURPackage:
|
||||
def from_json(cls: type[AURPackage], dump: dict[str, Any]) -> AURPackage:
|
||||
"""
|
||||
construct package descriptor from RPC properties
|
||||
|
||||
Args:
|
||||
dump(Dict[str, Any]): json dump body
|
||||
dump(dict[str, Any]): json dump body
|
||||
|
||||
Returns:
|
||||
AURPackage: AUR package descriptor
|
||||
@ -117,7 +118,7 @@ class AURPackage:
|
||||
return cls(**filter_json(properties, known_fields))
|
||||
|
||||
@classmethod
|
||||
def from_pacman(cls: Type[AURPackage], package: Package) -> AURPackage:
|
||||
def from_pacman(cls: type[AURPackage], package: Package) -> AURPackage:
|
||||
"""
|
||||
construct package descriptor from official repository wrapper
|
||||
|
||||
@ -154,12 +155,12 @@ class AURPackage:
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def from_repo(cls: Type[AURPackage], dump: Dict[str, Any]) -> AURPackage:
|
||||
def from_repo(cls: type[AURPackage], dump: dict[str, Any]) -> AURPackage:
|
||||
"""
|
||||
construct package descriptor from official repository RPC properties
|
||||
|
||||
Args:
|
||||
dump(Dict[str, Any]): json dump body
|
||||
dump(dict[str, Any]): json dump body
|
||||
|
||||
Returns:
|
||||
AURPackage: AUR package descriptor
|
||||
@ -193,24 +194,24 @@ class AURPackage:
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def convert(descriptor: Dict[str, Any]) -> Dict[str, Any]:
|
||||
def convert(descriptor: dict[str, Any]) -> dict[str, Any]:
|
||||
"""
|
||||
covert AUR RPC key names to package keys
|
||||
|
||||
Args:
|
||||
descriptor(Dict[str, Any]): RPC package descriptor
|
||||
descriptor(dict[str, Any]): RPC package descriptor
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: package descriptor with names converted to snake case
|
||||
dict[str, Any]: package descriptor with names converted to snake case
|
||||
"""
|
||||
identity_mapper: Callable[[Any], Any] = lambda value: value
|
||||
value_mapper: Dict[str, Callable[[Any], Any]] = {
|
||||
value_mapper: dict[str, Callable[[Any], Any]] = {
|
||||
"out_of_date": lambda value: datetime.datetime.utcfromtimestamp(value) if value is not None else None,
|
||||
"first_submitted": datetime.datetime.utcfromtimestamp,
|
||||
"last_modified": datetime.datetime.utcfromtimestamp,
|
||||
}
|
||||
|
||||
result: Dict[str, Any] = {}
|
||||
result: dict[str, Any] = {}
|
||||
for api_key, api_value in descriptor.items():
|
||||
property_key = inflection.underscore(api_key)
|
||||
mapper = value_mapper.get(property_key, identity_mapper)
|
||||
|
@ -20,7 +20,6 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from enum import Enum
|
||||
from typing import Type
|
||||
|
||||
|
||||
class AuthSettings(str, Enum):
|
||||
@ -38,7 +37,7 @@ class AuthSettings(str, Enum):
|
||||
OAuth = "oauth2"
|
||||
|
||||
@classmethod
|
||||
def from_option(cls: Type[AuthSettings], value: str) -> AuthSettings:
|
||||
def from_option(cls: type[AuthSettings], value: str) -> AuthSettings:
|
||||
"""
|
||||
construct value from configuration
|
||||
|
||||
|
@ -21,7 +21,7 @@ from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass, field, fields
|
||||
from enum import Enum
|
||||
from typing import Any, Dict, Type
|
||||
from typing import Any
|
||||
|
||||
from ahriman.core.util import filter_json, pretty_datetime, utcnow
|
||||
|
||||
@ -65,12 +65,12 @@ class BuildStatus:
|
||||
object.__setattr__(self, "status", BuildStatusEnum(self.status))
|
||||
|
||||
@classmethod
|
||||
def from_json(cls: Type[BuildStatus], dump: Dict[str, Any]) -> BuildStatus:
|
||||
def from_json(cls: type[BuildStatus], dump: dict[str, Any]) -> BuildStatus:
|
||||
"""
|
||||
construct status properties from json dump
|
||||
|
||||
Args:
|
||||
dump(Dict[str, Any]): json dump body
|
||||
dump(dict[str, Any]): json dump body
|
||||
|
||||
Returns:
|
||||
BuildStatus: status properties
|
||||
@ -87,12 +87,12 @@ class BuildStatus:
|
||||
"""
|
||||
return f"{self.status.value} ({pretty_datetime(self.timestamp)})"
|
||||
|
||||
def view(self) -> Dict[str, Any]:
|
||||
def view(self) -> dict[str, Any]:
|
||||
"""
|
||||
generate json status view
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: json-friendly dictionary
|
||||
dict[str, Any]: json-friendly dictionary
|
||||
"""
|
||||
return {
|
||||
"status": self.status.value,
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user