mirror of
https://github.com/arcan1s/ahriman.git
synced 2025-04-24 15:27:17 +00:00
never raise keyerror instead return empty string
This commit is contained in:
parent
67d05932cd
commit
42b6637d63
@ -197,7 +197,7 @@ class Watcher(LazyLogging):
|
|||||||
proxy methods for reporter client
|
proxy methods for reporter client
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
item(str): property name:
|
item(str): property name
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Any: attribute by its name
|
Any: attribute by its name
|
||||||
|
@ -266,11 +266,7 @@ class Package(LazyLogging):
|
|||||||
)
|
)
|
||||||
for package, properties in pkgbuild.packages().items()
|
for package, properties in pkgbuild.packages().items()
|
||||||
}
|
}
|
||||||
version = full_version(
|
version = full_version(pkgbuild.epoch, pkgbuild.pkgver, pkgbuild.pkgrel)
|
||||||
pkgbuild.get_as("epoch", default=None),
|
|
||||||
pkgbuild.get_as("pkgver"),
|
|
||||||
pkgbuild.get_as("pkgrel"),
|
|
||||||
)
|
|
||||||
|
|
||||||
remote = RemoteSource(
|
remote = RemoteSource(
|
||||||
source=PackageSource.Local,
|
source=PackageSource.Local,
|
||||||
@ -439,11 +435,7 @@ class Package(LazyLogging):
|
|||||||
|
|
||||||
pkgbuild = Pkgbuild.from_file(paths.cache_for(self.base) / "PKGBUILD")
|
pkgbuild = Pkgbuild.from_file(paths.cache_for(self.base) / "PKGBUILD")
|
||||||
|
|
||||||
return full_version(
|
return full_version(pkgbuild.epoch, pkgbuild.pkgver, pkgbuild.pkgrel)
|
||||||
pkgbuild.get_as("epoch", default=None),
|
|
||||||
pkgbuild.get_as("pkgver"),
|
|
||||||
pkgbuild.get_as("pkgrel"),
|
|
||||||
)
|
|
||||||
except Exception:
|
except Exception:
|
||||||
self.logger.exception("cannot determine version of VCS package")
|
self.logger.exception("cannot determine version of VCS package")
|
||||||
finally:
|
finally:
|
||||||
|
@ -25,15 +25,11 @@ from dataclasses import dataclass
|
|||||||
from enum import StrEnum
|
from enum import StrEnum
|
||||||
from io import StringIO
|
from io import StringIO
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import IO, Self, TypeVar, cast
|
from typing import Any, IO, Self
|
||||||
|
|
||||||
from ahriman.models.pkgbuild_patch import PkgbuildPatch
|
from ahriman.models.pkgbuild_patch import PkgbuildPatch
|
||||||
|
|
||||||
|
|
||||||
T = TypeVar("T", str, list[str])
|
|
||||||
U = TypeVar("U", str, list[str], None)
|
|
||||||
|
|
||||||
|
|
||||||
class PkgbuildToken(StrEnum):
|
class PkgbuildToken(StrEnum):
|
||||||
"""
|
"""
|
||||||
well-known tokens dictionary
|
well-known tokens dictionary
|
||||||
@ -119,12 +115,12 @@ class Pkgbuild(Mapping[str, str | list[str]]):
|
|||||||
parser.commenters = ""
|
parser.commenters = ""
|
||||||
while token := parser.get_token():
|
while token := parser.get_token():
|
||||||
try:
|
try:
|
||||||
key, value = cls._parse_token(token, parser)
|
patch = cls._parse_token(token, parser)
|
||||||
fields[key] = value
|
fields[patch.key] = patch
|
||||||
except StopIteration:
|
except StopIteration:
|
||||||
break
|
break
|
||||||
|
|
||||||
return cls(fields)
|
return cls({key: value for key, value in fields.items() if key})
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _parse_array(parser: shlex.shlex) -> list[str]:
|
def _parse_array(parser: shlex.shlex) -> list[str]:
|
||||||
@ -175,7 +171,7 @@ class Pkgbuild(Mapping[str, str | list[str]]):
|
|||||||
while token := parser.get_token():
|
while token := parser.get_token():
|
||||||
match token:
|
match token:
|
||||||
case PkgbuildToken.FunctionStarts:
|
case PkgbuildToken.FunctionStarts:
|
||||||
start_position = io.tell()
|
start_position = io.tell() - 1
|
||||||
case PkgbuildToken.FunctionEnds:
|
case PkgbuildToken.FunctionEnds:
|
||||||
end_position = io.tell()
|
end_position = io.tell()
|
||||||
break
|
break
|
||||||
@ -184,13 +180,13 @@ class Pkgbuild(Mapping[str, str | list[str]]):
|
|||||||
raise ValueError("Function body wasn't found")
|
raise ValueError("Function body wasn't found")
|
||||||
|
|
||||||
# read the specified interval from source stream
|
# read the specified interval from source stream
|
||||||
io.seek(start_position - 1) # start from the previous symbol ("{")
|
io.seek(start_position - 1) # start from the previous symbol
|
||||||
content = io.read(end_position - start_position + 1)
|
content = io.read(end_position - start_position)
|
||||||
|
|
||||||
return content
|
return content
|
||||||
|
|
||||||
@staticmethod
|
@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
|
parse single token to the PKGBUILD field
|
||||||
|
|
||||||
@ -199,7 +195,7 @@ class Pkgbuild(Mapping[str, str | list[str]]):
|
|||||||
parser(shlex.shlex): shell parser instance
|
parser(shlex.shlex): shell parser instance
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
tuple[str, PkgbuildPatch]: extracted a pair of key and its value
|
PkgbuildPatch: extracted a PKGBUILD node
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
StopIteration: if iteration reaches the end of the file
|
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:
|
if (match := Pkgbuild._STRING_ASSIGNMENT.match(token)) is not None:
|
||||||
key = match.group("key")
|
key = match.group("key")
|
||||||
value = match.group("value")
|
value = match.group("value")
|
||||||
return key, PkgbuildPatch(key, value)
|
return PkgbuildPatch(key, value)
|
||||||
|
|
||||||
match parser.get_token():
|
match parser.get_token():
|
||||||
# array processing. Arrays will be sent as "key=", "(", values, ")"
|
# array processing. Arrays will be sent as "key=", "(", values, ")"
|
||||||
case PkgbuildToken.ArrayStarts if (match := Pkgbuild._ARRAY_ASSIGNMENT.match(token)) is not None:
|
case PkgbuildToken.ArrayStarts if (match := Pkgbuild._ARRAY_ASSIGNMENT.match(token)) is not None:
|
||||||
key = match.group("key")
|
key = match.group("key")
|
||||||
value = Pkgbuild._parse_array(parser)
|
value = Pkgbuild._parse_array(parser)
|
||||||
return key, PkgbuildPatch(key, value)
|
return PkgbuildPatch(key, value)
|
||||||
|
|
||||||
# functions processing. Function will be sent as "name", "()", "{", body, "}"
|
# functions processing. Function will be sent as "name", "()", "{", body, "}"
|
||||||
case PkgbuildToken.FunctionDeclaration if Pkgbuild._FUNCTION_DECLARATION.match(token):
|
case PkgbuildToken.FunctionDeclaration if Pkgbuild._FUNCTION_DECLARATION.match(token):
|
||||||
key = f"{token}{PkgbuildToken.FunctionDeclaration}"
|
key = f"{token}{PkgbuildToken.FunctionDeclaration}"
|
||||||
value = Pkgbuild._parse_function(parser)
|
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 ( )"
|
# special function case, where "(" and ")" are separated tokens, e.g. "pkgver ( )"
|
||||||
case PkgbuildToken.ArrayStarts if Pkgbuild._FUNCTION_DECLARATION.match(token):
|
case PkgbuildToken.ArrayStarts if Pkgbuild._FUNCTION_DECLARATION.match(token):
|
||||||
@ -239,27 +235,6 @@ class Pkgbuild(Mapping[str, str | list[str]]):
|
|||||||
case None:
|
case None:
|
||||||
raise StopIteration
|
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]:
|
def packages(self) -> dict[str, Self]:
|
||||||
"""
|
"""
|
||||||
extract properties from internal package functions
|
extract properties from internal package functions
|
||||||
@ -271,14 +246,29 @@ class Pkgbuild(Mapping[str, str | list[str]]):
|
|||||||
|
|
||||||
def io(package_name: str) -> IO[str]:
|
def io(package_name: str) -> IO[str]:
|
||||||
# try to read package specific function and fallback to default otherwise
|
# 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 StringIO(content)
|
||||||
|
|
||||||
return {package: self.from_io(io(package)) for package in packages}
|
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]:
|
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:
|
Args:
|
||||||
key(str): key name
|
key(str): key name
|
||||||
@ -286,7 +276,15 @@ class Pkgbuild(Mapping[str, str | list[str]]):
|
|||||||
Returns:
|
Returns:
|
||||||
str | list[str]: value by the key
|
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]:
|
def __iter__(self) -> Iterator[str]:
|
||||||
"""
|
"""
|
||||||
|
Loading…
Reference in New Issue
Block a user