mirror of
				https://github.com/arcan1s/ahriman.git
				synced 2025-11-04 07:43:42 +00:00 
			
		
		
		
	never raise keyerror instead return empty string
This commit is contained in:
		@ -197,7 +197,7 @@ class Watcher(LazyLogging):
 | 
			
		||||
        proxy methods for reporter client
 | 
			
		||||
 | 
			
		||||
        Args:
 | 
			
		||||
            item(str): property name:
 | 
			
		||||
            item(str): property name
 | 
			
		||||
 | 
			
		||||
        Returns:
 | 
			
		||||
            Any: attribute by its name
 | 
			
		||||
 | 
			
		||||
@ -266,11 +266,7 @@ class Package(LazyLogging):
 | 
			
		||||
            )
 | 
			
		||||
            for package, properties in pkgbuild.packages().items()
 | 
			
		||||
        }
 | 
			
		||||
        version = full_version(
 | 
			
		||||
            pkgbuild.get_as("epoch", default=None),
 | 
			
		||||
            pkgbuild.get_as("pkgver"),
 | 
			
		||||
            pkgbuild.get_as("pkgrel"),
 | 
			
		||||
        )
 | 
			
		||||
        version = full_version(pkgbuild.epoch, pkgbuild.pkgver, pkgbuild.pkgrel)
 | 
			
		||||
 | 
			
		||||
        remote = RemoteSource(
 | 
			
		||||
            source=PackageSource.Local,
 | 
			
		||||
@ -439,11 +435,7 @@ class Package(LazyLogging):
 | 
			
		||||
 | 
			
		||||
            pkgbuild = Pkgbuild.from_file(paths.cache_for(self.base) / "PKGBUILD")
 | 
			
		||||
 | 
			
		||||
            return full_version(
 | 
			
		||||
                pkgbuild.get_as("epoch", default=None),
 | 
			
		||||
                pkgbuild.get_as("pkgver"),
 | 
			
		||||
                pkgbuild.get_as("pkgrel"),
 | 
			
		||||
            )
 | 
			
		||||
            return full_version(pkgbuild.epoch, pkgbuild.pkgver, pkgbuild.pkgrel)
 | 
			
		||||
        except Exception:
 | 
			
		||||
            self.logger.exception("cannot determine version of VCS package")
 | 
			
		||||
        finally:
 | 
			
		||||
 | 
			
		||||
@ -25,15 +25,11 @@ from dataclasses import dataclass
 | 
			
		||||
from enum import StrEnum
 | 
			
		||||
from io import StringIO
 | 
			
		||||
from pathlib import Path
 | 
			
		||||
from typing import IO, Self, TypeVar, cast
 | 
			
		||||
from typing import Any, IO, Self
 | 
			
		||||
 | 
			
		||||
from ahriman.models.pkgbuild_patch import PkgbuildPatch
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
T = TypeVar("T", str, list[str])
 | 
			
		||||
U = TypeVar("U", str, list[str], None)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class PkgbuildToken(StrEnum):
 | 
			
		||||
    """
 | 
			
		||||
    well-known tokens dictionary
 | 
			
		||||
@ -119,12 +115,12 @@ class Pkgbuild(Mapping[str, str | list[str]]):
 | 
			
		||||
        parser.commenters = ""
 | 
			
		||||
        while token := parser.get_token():
 | 
			
		||||
            try:
 | 
			
		||||
                key, value = cls._parse_token(token, parser)
 | 
			
		||||
                fields[key] = value
 | 
			
		||||
                patch = cls._parse_token(token, parser)
 | 
			
		||||
                fields[patch.key] = patch
 | 
			
		||||
            except StopIteration:
 | 
			
		||||
                break
 | 
			
		||||
 | 
			
		||||
        return cls(fields)
 | 
			
		||||
        return cls({key: value for key, value in fields.items() if key})
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def _parse_array(parser: shlex.shlex) -> list[str]:
 | 
			
		||||
@ -175,7 +171,7 @@ class Pkgbuild(Mapping[str, str | list[str]]):
 | 
			
		||||
        while token := parser.get_token():
 | 
			
		||||
            match token:
 | 
			
		||||
                case PkgbuildToken.FunctionStarts:
 | 
			
		||||
                    start_position = io.tell()
 | 
			
		||||
                    start_position = io.tell() - 1
 | 
			
		||||
                case PkgbuildToken.FunctionEnds:
 | 
			
		||||
                    end_position = io.tell()
 | 
			
		||||
                    break
 | 
			
		||||
@ -184,13 +180,13 @@ class Pkgbuild(Mapping[str, str | list[str]]):
 | 
			
		||||
            raise ValueError("Function body wasn't found")
 | 
			
		||||
 | 
			
		||||
        # read the specified interval from source stream
 | 
			
		||||
        io.seek(start_position - 1)  # start from the previous symbol ("{")
 | 
			
		||||
        content = io.read(end_position - start_position + 1)
 | 
			
		||||
        io.seek(start_position - 1)  # start from the previous symbol
 | 
			
		||||
        content = io.read(end_position - start_position)
 | 
			
		||||
 | 
			
		||||
        return content
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def _parse_token(token: str, parser: shlex.shlex) -> tuple[str, PkgbuildPatch]:
 | 
			
		||||
    def _parse_token(token: str, parser: shlex.shlex) -> PkgbuildPatch:
 | 
			
		||||
        """
 | 
			
		||||
        parse single token to the PKGBUILD field
 | 
			
		||||
 | 
			
		||||
@ -199,7 +195,7 @@ class Pkgbuild(Mapping[str, str | list[str]]):
 | 
			
		||||
            parser(shlex.shlex): shell parser instance
 | 
			
		||||
 | 
			
		||||
        Returns:
 | 
			
		||||
            tuple[str, PkgbuildPatch]: extracted a pair of key and its value
 | 
			
		||||
            PkgbuildPatch: extracted a PKGBUILD node
 | 
			
		||||
 | 
			
		||||
        Raises:
 | 
			
		||||
            StopIteration: if iteration reaches the end of the file
 | 
			
		||||
@ -208,20 +204,20 @@ class Pkgbuild(Mapping[str, str | list[str]]):
 | 
			
		||||
        if (match := Pkgbuild._STRING_ASSIGNMENT.match(token)) is not None:
 | 
			
		||||
            key = match.group("key")
 | 
			
		||||
            value = match.group("value")
 | 
			
		||||
            return key, PkgbuildPatch(key, value)
 | 
			
		||||
            return PkgbuildPatch(key, value)
 | 
			
		||||
 | 
			
		||||
        match parser.get_token():
 | 
			
		||||
            # array processing. Arrays will be sent as "key=", "(", values, ")"
 | 
			
		||||
            case PkgbuildToken.ArrayStarts if (match := Pkgbuild._ARRAY_ASSIGNMENT.match(token)) is not None:
 | 
			
		||||
                key = match.group("key")
 | 
			
		||||
                value = Pkgbuild._parse_array(parser)
 | 
			
		||||
                return key, PkgbuildPatch(key, value)
 | 
			
		||||
                return PkgbuildPatch(key, value)
 | 
			
		||||
 | 
			
		||||
            # functions processing. Function will be sent as "name", "()", "{", body, "}"
 | 
			
		||||
            case PkgbuildToken.FunctionDeclaration if Pkgbuild._FUNCTION_DECLARATION.match(token):
 | 
			
		||||
                key = f"{token}{PkgbuildToken.FunctionDeclaration}"
 | 
			
		||||
                value = Pkgbuild._parse_function(parser)
 | 
			
		||||
                return token, PkgbuildPatch(key, value)  # this is not mistake, assign to token without ()
 | 
			
		||||
                return PkgbuildPatch(key, value)  # this is not mistake, assign to token without ()
 | 
			
		||||
 | 
			
		||||
            # special function case, where "(" and ")" are separated tokens, e.g. "pkgver ( )"
 | 
			
		||||
            case PkgbuildToken.ArrayStarts if Pkgbuild._FUNCTION_DECLARATION.match(token):
 | 
			
		||||
@ -239,27 +235,6 @@ class Pkgbuild(Mapping[str, str | list[str]]):
 | 
			
		||||
            case None:
 | 
			
		||||
                raise StopIteration
 | 
			
		||||
 | 
			
		||||
    def get_as(self, key: str, **kwargs: T | U) -> T | U:
 | 
			
		||||
        """
 | 
			
		||||
        type guard for getting value by key
 | 
			
		||||
 | 
			
		||||
        Args:
 | 
			
		||||
            key(str): key name
 | 
			
		||||
            default(U, optional): default value to return if no key found
 | 
			
		||||
 | 
			
		||||
        Returns:
 | 
			
		||||
            T | U: value associated with key or default value if no value found and fallback is provided
 | 
			
		||||
 | 
			
		||||
        Raises:
 | 
			
		||||
            KeyError: if no key found and no default has been provided
 | 
			
		||||
        """
 | 
			
		||||
        if key not in self:
 | 
			
		||||
            if "default" in kwargs:
 | 
			
		||||
                return kwargs["default"]
 | 
			
		||||
            raise KeyError(key)
 | 
			
		||||
 | 
			
		||||
        return cast(T, self[key])
 | 
			
		||||
 | 
			
		||||
    def packages(self) -> dict[str, Self]:
 | 
			
		||||
        """
 | 
			
		||||
        extract properties from internal package functions
 | 
			
		||||
@ -271,14 +246,29 @@ class Pkgbuild(Mapping[str, str | list[str]]):
 | 
			
		||||
 | 
			
		||||
        def io(package_name: str) -> IO[str]:
 | 
			
		||||
            # try to read package specific function and fallback to default otherwise
 | 
			
		||||
            content = self.get_as(f"package_{package_name}", default=None) or self.get_as("package")
 | 
			
		||||
            # content = self.get_as(f"package_{package_name}") or self.get_as("package")
 | 
			
		||||
            content = getattr(self, f"package_{package_name}") or self.package
 | 
			
		||||
            return StringIO(content)
 | 
			
		||||
 | 
			
		||||
        return {package: self.from_io(io(package)) for package in packages}
 | 
			
		||||
 | 
			
		||||
    def __getattr__(self, item: str) -> Any:
 | 
			
		||||
        """
 | 
			
		||||
        proxy method for PKGBUILD properties
 | 
			
		||||
 | 
			
		||||
        Args:
 | 
			
		||||
            item(str): property name
 | 
			
		||||
 | 
			
		||||
        Returns:
 | 
			
		||||
            Any: attribute by its name
 | 
			
		||||
        """
 | 
			
		||||
        return self[item]
 | 
			
		||||
 | 
			
		||||
    def __getitem__(self, key: str) -> str | list[str]:
 | 
			
		||||
        """
 | 
			
		||||
        get the field of the PKGBUILD
 | 
			
		||||
        get the field of the PKGBUILD. This method tries to get exact key value if possible; if none found, it tries to
 | 
			
		||||
        fetch function with the same name. And, finally, it returns empty value if nothing found, so this function never
 | 
			
		||||
        raises an ``KeyError``.exception``
 | 
			
		||||
 | 
			
		||||
        Args:
 | 
			
		||||
            key(str): key name
 | 
			
		||||
@ -286,7 +276,15 @@ class Pkgbuild(Mapping[str, str | list[str]]):
 | 
			
		||||
        Returns:
 | 
			
		||||
            str | list[str]: value by the key
 | 
			
		||||
        """
 | 
			
		||||
        return self.fields[key].substitute(self.variables)
 | 
			
		||||
        value = self.fields.get(key)
 | 
			
		||||
        # if the key wasn't found and user didn't ask for function explicitly, we can try to get by function name
 | 
			
		||||
        if value is None and not key.endswith(PkgbuildToken.FunctionDeclaration):
 | 
			
		||||
            value = self.fields.get(f"{key}{PkgbuildToken.FunctionDeclaration}")
 | 
			
		||||
        # if we still didn't find anything, we fall back to empty value (just like shell)
 | 
			
		||||
        if value is None:
 | 
			
		||||
            value = PkgbuildPatch(key, "")
 | 
			
		||||
 | 
			
		||||
        return value.substitute(self.variables)
 | 
			
		||||
 | 
			
		||||
    def __iter__(self) -> Iterator[str]:
 | 
			
		||||
        """
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user