Skip to content

Commit

Permalink
Refactor GherkinParser internals
Browse files Browse the repository at this point in the history
  • Loading branch information
elchupanebrej committed Jul 13, 2023
1 parent f983bfc commit 2d3272b
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 19 deletions.
11 changes: 6 additions & 5 deletions src/pytest_bdd/compatibility/parser.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
from pathlib import Path
from typing import TYPE_CHECKING, Callable, Protocol, Sequence, Union, runtime_checkable
from typing import TYPE_CHECKING, Callable, Optional, Protocol, Sequence, Union, runtime_checkable

from attr import attrib, attrs

from pytest_bdd.compatibility.pytest import Config
from pytest_bdd.utils import PytestBDDIdGeneratorHandler
from pytest_bdd.utils import IdGenerator, PytestBDDIdGeneratorHandler

if TYPE_CHECKING: # pragma: no cover
from pytest_bdd.model import Feature


@runtime_checkable
@attrs
class ParserProtocol(Protocol):
id_generator: Optional[IdGenerator] = attrib(default=None, kw_only=True)
# Defines which files would be parsed
glob: Callable[[Path], Sequence[Union[str, Path]]]

def __init__(self, *args, id_generator=None, **kwargs): # pragma: no cover
...

def parse(
self, config: Union[Config, PytestBDDIdGeneratorHandler], path: Path, uri: str, *args, **kwargs
) -> "Feature": # pragma: no cover
Expand Down
22 changes: 8 additions & 14 deletions src/pytest_bdd/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
from typing import Callable, List, Sequence, Set, Union, cast

from attr import attrib, attrs
from attr._make import Factory
from gherkin.ast_builder import AstBuilder
from gherkin.errors import CompositeParserException
from gherkin.parser import Parser as CucumberIOBaseParser # type: ignore[import]
Expand Down Expand Up @@ -50,34 +49,28 @@ def build_feature(self, gherkin_document_raw_dict, filename: str, id_generator)


@attrs
class GherkinParser(CucumberIOBaseParser, ASTBuilderMixin, GlobMixin, ParserProtocol):
id_generator = attrib(default=Factory(IdGenerator))

def __attrs_post_init__(self):
CucumberIOBaseParser.__init__(self, ast_builder=AstBuilder(id_generator=self.id_generator))

@classmethod
class GherkinParser(ASTBuilderMixin, GlobMixin, ParserProtocol):
def parse(
cls, config: Union[Config, PytestBDDIdGeneratorHandler], path: Path, uri: str, *args, **kwargs
self, config: Union[Config, PytestBDDIdGeneratorHandler], path: Path, uri: str, *args, **kwargs
) -> Feature:
parser = cls(id_generator=cast(PytestBDDIdGeneratorHandler, config).pytest_bdd_id_generator)
gherkin_parser = CucumberIOBaseParser(ast_builder=AstBuilder(id_generator=self.id_generator))
encoding = kwargs.pop("encoding", "utf-8")
with path.open(mode="r", encoding=encoding) as feature_file:
feature_file_data = feature_file.read()

# TODO Use hook for this
if ".md" in path.suffixes:
media_type = MediaType.text_x_cucumber_gherkin_markdown
else:
media_type = MediaType.text_x_cucumber_gherkin_plain

# TODO move out from parse
cast(Config, config).hook.pytest_bdd_message(
config=config, message=Message(source=Source(uri=uri, data=feature_file_data, media_type=media_type))
)

try:
gherkin_document_raw_dict = CucumberIOBaseParser.parse(
parser, token_scanner_or_str=feature_file_data, *args, **kwargs
)
gherkin_document_raw_dict = gherkin_parser.parse(token_scanner_or_str=feature_file_data, *args, **kwargs)
except CompositeParserException as e:
raise FeatureError(
e.args[0],
Expand All @@ -88,7 +81,8 @@ def parse(

gherkin_document_raw_dict["uri"] = uri

feature = parser.build_feature(
# TODO Move messages out of feature parsing
feature = self.build_feature(
gherkin_document_raw_dict,
filename=str(path.as_posix()),
id_generator=getattr(config, "pytest_bdd_id_generator", IdGenerator()),
Expand Down

0 comments on commit 2d3272b

Please sign in to comment.