From 9a69541040a830af53b9c316683e2e65851bd160 Mon Sep 17 00:00:00 2001 From: Kostiantyn Goloveshko Date: Sun, 8 Dec 2024 23:50:15 +0200 Subject: [PATCH] Fixup name collision --- python/src/cucumber_messages/__init__.py | 8 ++- .../src/cucumber_messages/json_converter.py | 15 +++--- python/src/cucumber_messages/messages.py | 54 +++++++++++++++++-- python/tests/test_model_load.py | 4 +- 4 files changed, 66 insertions(+), 15 deletions(-) diff --git a/python/src/cucumber_messages/__init__.py b/python/src/cucumber_messages/__init__.py index ed77d2d0..34ac5777 100644 --- a/python/src/cucumber_messages/__init__.py +++ b/python/src/cucumber_messages/__init__.py @@ -1,5 +1,11 @@ from . import json_converter from .messages import * -ExpressionType = Type1 +# Renaming types because of confusing collision naming +HookType = Type +PickleStepType = Type1 +ExpressionType = Type2 + +del Type del Type1 +del Type2 diff --git a/python/src/cucumber_messages/json_converter.py b/python/src/cucumber_messages/json_converter.py index 206f8235..8b31c583 100644 --- a/python/src/cucumber_messages/json_converter.py +++ b/python/src/cucumber_messages/json_converter.py @@ -6,11 +6,10 @@ from dataclasses import fields, is_dataclass, Field, MISSING from datetime import datetime, date from enum import Enum -from typing import Any, Dict, List, Optional, Union, get_args, get_origin, TypeVar, Type, Tuple +from typing import Any, Dict, List, Optional, Union, get_args, get_origin, TypeVar, Type as TypingType, Tuple T = TypeVar('T') - def camel_to_snake(name: str) -> str: """Convert string from camelCase to snake_case.""" # Validate field name - must start with letter or underscore and contain only alphanumeric and underscore @@ -40,7 +39,7 @@ def __init__(self, module_scope: types.ModuleType): self.module_scope = module_scope self.type_cache = {} - def resolve_container_type(self, container_name: str) -> Type: + def resolve_container_type(self, container_name: str) -> TypingType: container_types = { 'Sequence': typing.Sequence, 'List': list, @@ -52,7 +51,7 @@ def resolve_container_type(self, container_name: str) -> Type: raise ValueError(f"Unsupported container type: {container_name}") return container_types[container_name] - def parse_generic_type(self, type_str: str) -> Tuple[Type, List[Type]]: + def parse_generic_type(self, type_str: str) -> Tuple[TypingType, List[TypingType]]: container_name = type_str[:type_str.index('[')].strip() args_str = type_str[type_str.index('[') + 1:type_str.rindex(']')] @@ -65,7 +64,7 @@ def parse_generic_type(self, type_str: str) -> Tuple[Type, List[Type]]: return container_type, arg_types - def resolve_type(self, type_str: str) -> Type: + def resolve_type(self, type_str: str) -> TypingType: if type_str in self.type_cache: return self.type_cache[type_str] @@ -84,7 +83,7 @@ def resolve_type(self, type_str: str) -> Type: self.type_cache[type_str] = resolved return resolved - def _resolve_union_type(self, type_str: str) -> Type: + def _resolve_union_type(self, type_str: str) -> TypingType: types_str = [t.strip() for t in type_str.split('|')] resolved_types = [ self.resolve_type(t) @@ -293,11 +292,11 @@ def to_dict(self) -> Dict[str, Any]: return DataclassJSONEncoder.encode(self) @classmethod - def from_json(cls: Type[T], json_str: str, module_scope: Optional[types.ModuleType] = None) -> T: + def from_json(cls: TypingType[T], json_str: str, module_scope: Optional[types.ModuleType] = None) -> T: data = json.loads(json_str) return cls.from_dict(data, module_scope) @classmethod - def from_dict(cls: Type[T], data: Dict[str, Any], module_scope: Optional[types.ModuleType] = None) -> T: + def from_dict(cls: TypingType[T], data: Dict[str, Any], module_scope: Optional[types.ModuleType] = None) -> T: decoder = DataclassJSONDecoder(module_scope or sys.modules[cls.__module__]) return decoder.decode(data, cls) \ No newline at end of file diff --git a/python/src/cucumber_messages/messages.py b/python/src/cucumber_messages/messages.py index 551c3f1b..a970923e 100644 --- a/python/src/cucumber_messages/messages.py +++ b/python/src/cucumber_messages/messages.py @@ -114,6 +114,15 @@ class Tag(JSONDataclassMixin): """ +class Type(Enum): + before_test_run = "BEFORE_TEST_RUN" + after_test_run = "AFTER_TEST_RUN" + before_test_case = "BEFORE_TEST_CASE" + after_test_case = "AFTER_TEST_CASE" + before_test_step = "BEFORE_TEST_STEP" + after_test_step = "AFTER_TEST_STEP" + + @dataclass class JavaMethod(JSONDataclassMixin): class_name: str @@ -154,7 +163,7 @@ class PickleDocString(JSONDataclassMixin): media_type: str | None = None -class Type(Enum): +class Type1(Enum): unknown = "Unknown" context = "Context" action = "Action" @@ -180,7 +189,7 @@ class PickleTag(JSONDataclassMixin): """ -class Type1(Enum): +class Type2(Enum): cucumber_expression = "CUCUMBER_EXPRESSION" regular_expression = "REGULAR_EXPRESSION" @@ -188,7 +197,7 @@ class Type1(Enum): @dataclass class StepDefinitionPattern(JSONDataclassMixin): source: str - type: Type1 + type: Type2 @dataclass @@ -295,6 +304,7 @@ class Exception(JSONDataclassMixin): @dataclass class TestRunStarted(JSONDataclassMixin): timestamp: Timestamp + id: str | None = None class Status(Enum): @@ -326,6 +336,23 @@ class TestStepStarted(JSONDataclassMixin): timestamp: Timestamp +@dataclass +class TestRunHookStarted(JSONDataclassMixin): + id: str + """ + Unique identifier for this hook execution + """ + test_run_started_id: str + """ + Identifier for the test run that this hook execution belongs to + """ + hook_id: str + """ + Identifier for the hook that will be executed + """ + timestamp: Timestamp + + @dataclass class UndefinedParameterType(JSONDataclassMixin): expression: str @@ -384,6 +411,7 @@ class Attachment(JSONDataclassMixin): reduce bandwidth of message consumers. It also makes it easier to process and download attachments separately from reports. """ + test_run_started_id: str | None = None @dataclass @@ -494,6 +522,10 @@ class TestCase(JSONDataclassMixin): The ID of the `Pickle` this `TestCase` is derived from. """ test_steps: Sequence[TestStep] + test_run_started_id: str | None = None + """ + Identifier for the test run that this test case belongs to + """ @dataclass @@ -521,6 +553,7 @@ class TestRunFinished(JSONDataclassMixin): """ Any exception thrown during the test run, if any. Does not include exceptions thrown while executing steps. """ + test_run_started_id: str | None = None @dataclass @@ -537,6 +570,16 @@ class TestStepResult(JSONDataclassMixin): """ +@dataclass +class TestRunHookFinished(JSONDataclassMixin): + test_run_hook_started_id: str + """ + Identifier for the hook execution that has finished + """ + result: TestStepResult + timestamp: Timestamp + + @dataclass class Background(JSONDataclassMixin): location: Location @@ -571,6 +614,7 @@ class Hook(JSONDataclassMixin): source_reference: SourceReference name: str | None = None tag_expression: str | None = None + type: Type | None = None @dataclass @@ -632,7 +676,7 @@ class PickleStep(JSONDataclassMixin): """ text: str argument: PickleStepArgument | None = None - type: Type | None = None + type: Type1 | None = None """ The context in which the step was specified: context (Given), action (When) or outcome (Then). @@ -767,4 +811,6 @@ class Envelope(JSONDataclassMixin): test_run_started: TestRunStarted | None = None test_step_finished: TestStepFinished | None = None test_step_started: TestStepStarted | None = None + test_run_hook_started: TestRunHookStarted | None = None + test_run_hook_finished: TestRunHookFinished | None = None undefined_parameter_type: UndefinedParameterType | None = None diff --git a/python/tests/test_model_load.py b/python/tests/test_model_load.py index 0e33906b..fec83bd1 100644 --- a/python/tests/test_model_load.py +++ b/python/tests/test_model_load.py @@ -39,7 +39,7 @@ TestStepResult, TestStepStarted, Timestamp, - Type, + PickleStepType, ) resource_path = Path(__file__).parent.absolute() / "data" @@ -118,7 +118,7 @@ uri="samples/minimal/minimal.feature", name="cukes", language="en", - steps=[PickleStep(ast_node_ids=["1"], id="3", type=Type.context, text="I have 42 cukes in my belly")], + steps=[PickleStep(ast_node_ids=["1"], id="3", type=PickleStepType.context, text="I have 42 cukes in my belly")], tags=[], ast_node_ids=["2"], ),