From f5a4e59f46466987ce3dccd5dc3cd086b0ddc449 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nikola=20Forr=C3=B3?= Date: Thu, 26 Sep 2024 14:14:57 +0200 Subject: [PATCH] Move `count_brackets()` to `specfile.utils` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Nikola Forró --- specfile/macro_definitions.py | 31 +--------------------------- specfile/utils.py | 39 +++++++++++++++++++++++++++++++++++ tests/unit/test_utils.py | 19 ++++++++++++++++- 3 files changed, 58 insertions(+), 31 deletions(-) diff --git a/specfile/macro_definitions.py b/specfile/macro_definitions.py index 2b53c9c..cc7c775 100644 --- a/specfile/macro_definitions.py +++ b/specfile/macro_definitions.py @@ -9,7 +9,7 @@ from specfile.conditions import process_conditions from specfile.formatter import formatted from specfile.types import SupportsIndex -from specfile.utils import UserList +from specfile.utils import UserList, count_brackets if TYPE_CHECKING: from specfile.specfile import Specfile @@ -303,35 +303,6 @@ def pop(lines): else: return line - def count_brackets(s): - bc = pc = 0 - chars = list(s) - while chars: - c = chars.pop(0) - if c == "\\" and chars: - chars.pop(0) - continue - if c == "%" and chars: - c = chars.pop(0) - if c == "{": - bc += 1 - elif c == "(": - pc += 1 - continue - if c == "{" and bc > 0: - bc += 1 - continue - if c == "}" and bc > 0: - bc -= 1 - continue - if c == "(" and pc > 0: - pc += 1 - continue - if c == ")" and pc > 0: - pc -= 1 - continue - return bc, pc - md_regex = re.compile( r""" ^ diff --git a/specfile/utils.py b/specfile/utils.py index 545a75b..a628a0f 100644 --- a/specfile/utils.py +++ b/specfile/utils.py @@ -254,6 +254,45 @@ def get_filename_from_location(location: str) -> str: return location[slash + 1 :].split("=")[-1] +def count_brackets(string: str) -> Tuple[int, int]: + """ + Counts non-pair brackets in %{...} and %(...) expressions appearing in the given string. + + Args: + string: Input string. + + Returns: + The count of non-pair curly braces and the count of non-pair parentheses. + """ + bc = pc = 0 + chars = list(string) + while chars: + c = chars.pop(0) + if c == "\\" and chars: + chars.pop(0) + continue + if c == "%" and chars: + c = chars.pop(0) + if c == "{": + bc += 1 + elif c == "(": + pc += 1 + continue + if c == "{" and bc > 0: + bc += 1 + continue + if c == "}" and bc > 0: + bc -= 1 + continue + if c == "(" and pc > 0: + pc += 1 + continue + if c == ")" and pc > 0: + pc -= 1 + continue + return bc, pc + + def split_conditional_macro_expansion(value: str) -> Tuple[str, str, str]: """ Splits conditional macro expansion into its body and prefix and suffix of it. diff --git a/tests/unit/test_utils.py b/tests/unit/test_utils.py index ed79278..8f90d04 100644 --- a/tests/unit/test_utils.py +++ b/tests/unit/test_utils.py @@ -3,7 +3,7 @@ import pytest -from specfile.utils import EVR, NEVR, NEVRA, get_filename_from_location +from specfile.utils import EVR, NEVR, NEVRA, count_brackets, get_filename_from_location @pytest.mark.parametrize( @@ -32,6 +32,23 @@ def test_get_filename_from_location(location, filename): assert get_filename_from_location(location) == filename +@pytest.mark.parametrize( + "string, count", + [ + ("", (0, 0)), + ("%macro", (0, 0)), + ("%{macro}", (0, 0)), + ("%{{macro}}", (0, 0)), + ("%{{macro}", (1, 0)), + ("%{macro:", (1, 0)), + ("%(echo %{v}", (0, 1)), + ("%(echo %{v} | cut -d. -f3)", (0, 0)), + ], +) +def test_count_brackets(string, count): + assert count_brackets(string) == count + + def test_EVR_compare(): assert EVR(version="0") == EVR(version="0") assert EVR(version="0", release="1") != EVR(version="0", release="2")