mirror of
				https://github.com/arcan1s/ahriman.git
				synced 2025-10-31 05:43:41 +00:00 
			
		
		
		
	never raise keyerror instead return empty string
This commit is contained in:
		| @ -199,7 +199,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