mirror of
				https://github.com/arcan1s/ahriman.git
				synced 2025-10-31 13:53: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 |         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]: | ||||||
|         """ |         """ | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user