mirror of
https://github.com/arcan1s/ahriman.git
synced 2026-10-24 12:25:01 +00:00
feat: restore iterable method in parser
This commit is contained in:
1 parent
f776b33310
commit
c38cb5f680
4 files changed
+28
-15
No files matched your search
@@ -21,7 +21,7 @@ import re
|
||||
import shlex
|
||||
import tree_sitter_bash
|
||||
|
||||
from collections.abc import Iterator
|
||||
from collections.abc import Iterable, Iterator
|
||||
from enum import StrEnum
|
||||
from tree_sitter import Language, Node, Parser
|
||||
from typing import IO, cast
|
||||
@@ -78,7 +78,7 @@ class PkgbuildNodeField(StrEnum):
|
||||
Value = "value"
|
||||
|
||||
|
||||
class PkgbuildParser:
|
||||
class PkgbuildParser(Iterable[PkgbuildPatch]):
|
||||
"""
|
||||
PKGBUILD parser implementation in python
|
||||
|
||||
@@ -97,24 +97,29 @@ class PkgbuildParser:
|
||||
original source, with their formatting preserved. Assignments inside shell statements and control-flow nodes are
|
||||
extracted without checking whether those statements would run.
|
||||
|
||||
Each iteration parses the stored source independently, starting from the beginning.
|
||||
|
||||
Examples:
|
||||
Parse package assignments::
|
||||
|
||||
>>> source = b"pkgname=example\\npkgver=1\\n"
|
||||
>>> for patch in PkgbuildParser(BytesIO(source)).parse():
|
||||
>>> for patch in PkgbuildParser(BytesIO(source)):
|
||||
... print(patch.key, patch.value)
|
||||
|
||||
Function bodies are returned as function patches::
|
||||
|
||||
>>> source = b"pkgver() { printf 1; }"
|
||||
>>> for patch in list(PkgbuildParser(BytesIO(source)).parse())
|
||||
>>> for patch in PkgbuildParser(BytesIO(source)):
|
||||
... print(patch.key, patch.value)
|
||||
"""
|
||||
|
||||
_BRACE_EXPANSION = re.compile(r"(.*)\{([^{}]+)\}(.*)")
|
||||
|
||||
def __init__(self, stream: IO[bytes]) -> None:
|
||||
""""""
|
||||
"""
|
||||
Args:
|
||||
stream(IO[bytes]): input PKGBUILD stream
|
||||
"""
|
||||
self._content = stream.read()
|
||||
|
||||
@staticmethod
|
||||
@@ -256,3 +261,12 @@ class PkgbuildParser:
|
||||
)
|
||||
|
||||
yield from self._read(tree.root_node)
|
||||
|
||||
def __iter__(self) -> Iterator[PkgbuildPatch]:
|
||||
"""
|
||||
iterate over the parsed entries
|
||||
|
||||
Returns:
|
||||
Iterator[PkgbuildPatch]: parsed entries
|
||||
"""
|
||||
return self.parse()
|
||||
@@ -80,8 +80,7 @@ class Pkgbuild(Mapping[str, Any]):
|
||||
Returns:
|
||||
Self: constructed instance of self
|
||||
"""
|
||||
parser = PkgbuildParser(stream)
|
||||
fields = {patch.key: patch for patch in parser.parse()}
|
||||
fields = {patch.key: patch for patch in PkgbuildParser(stream)}
|
||||
|
||||
# pkgbase is optional field, the pkgname must be used instead if not set
|
||||
# however, pkgname is not presented is "package()" functions which we are parsing here too,
|
||||
|
||||
@@ -71,7 +71,7 @@ def test_parse_array_exception() -> None:
|
||||
"""
|
||||
parser = PkgbuildParser(BytesIO(b"var=(first second"))
|
||||
with pytest.raises(PkgbuildParserError):
|
||||
assert list(parser.parse())
|
||||
list(parser.parse())
|
||||
|
||||
|
||||
def test_parse_function() -> None:
|
||||
@@ -119,11 +119,11 @@ def test_parse_function_exception() -> None:
|
||||
"""
|
||||
parser = PkgbuildParser(BytesIO(b"var() echo hello world } "))
|
||||
with pytest.raises(PkgbuildParserError):
|
||||
assert list(parser.parse())
|
||||
list(parser.parse())
|
||||
|
||||
parser = PkgbuildParser(BytesIO(b"var() { echo hello world"))
|
||||
with pytest.raises(PkgbuildParserError):
|
||||
assert list(parser.parse())
|
||||
list(parser.parse())
|
||||
|
||||
|
||||
def test_parse_function_inner_shell() -> None:
|
||||
|
||||
@@ -50,7 +50,7 @@ def test_from_io(pkgbuild_ahriman: Pkgbuild, mocker: MockerFixture) -> None:
|
||||
must correctly load from io
|
||||
"""
|
||||
load_mock = mocker.patch("ahriman.core.alpm.pkgbuild_parser.PkgbuildParser.parse",
|
||||
return_value=pkgbuild_ahriman.fields.values())
|
||||
return_value=iter(pkgbuild_ahriman.fields.values()))
|
||||
assert Pkgbuild.from_io(BytesIO(b"mock")) == pkgbuild_ahriman
|
||||
load_mock.assert_called_once_with()
|
||||
|
||||
@@ -60,9 +60,9 @@ def test_from_io_pkgbase(pkgbuild_ahriman: Pkgbuild, mocker: MockerFixture) -> N
|
||||
must assign missing pkgbase if pkgname is presented
|
||||
"""
|
||||
mocker.patch("ahriman.core.alpm.pkgbuild_parser.PkgbuildParser.parse", side_effect=[
|
||||
[value for key, value in pkgbuild_ahriman.fields.items() if key not in ("pkgbase",)],
|
||||
[value for key, value in pkgbuild_ahriman.fields.items() if key not in ("pkgbase", "pkgname",)],
|
||||
[value for key, value in pkgbuild_ahriman.fields.items()] + [PkgbuildPatch("pkgbase", "pkgbase")],
|
||||
iter([value for key, value in pkgbuild_ahriman.fields.items() if key not in ("pkgbase",)]),
|
||||
iter([value for key, value in pkgbuild_ahriman.fields.items() if key not in ("pkgbase", "pkgname",)]),
|
||||
iter([value for key, value in pkgbuild_ahriman.fields.items()] + [PkgbuildPatch("pkgbase", "pkgbase")]),
|
||||
])
|
||||
|
||||
assert Pkgbuild.from_io(BytesIO(b"mock"))["pkgbase"] == pkgbuild_ahriman["pkgname"]
|
||||
@@ -75,7 +75,7 @@ def test_from_io_empty(pkgbuild_ahriman: Pkgbuild, mocker: MockerFixture) -> Non
|
||||
must skip empty patches
|
||||
"""
|
||||
mocker.patch("ahriman.core.alpm.pkgbuild_parser.PkgbuildParser.parse",
|
||||
return_value=list(pkgbuild_ahriman.fields.values()) + [PkgbuildPatch("", "")])
|
||||
return_value=iter(list(pkgbuild_ahriman.fields.values()) + [PkgbuildPatch("", "")]))
|
||||
assert Pkgbuild.from_io(BytesIO(b"mock")) == pkgbuild_ahriman
|
||||
|
||||
|
||||
|
||||
Reference in new issue
Block a user