From e9264662fc26ada537b7f67ec266e7d490f66064 Mon Sep 17 00:00:00 2001 From: Kostiantyn Goloveshko Date: Thu, 19 Dec 2024 02:13:09 +0200 Subject: [PATCH] Exclude model modification by pre-commit hooks --- .pre-commit-config.yaml | 2 +- codegen/templates/python.py.erb | 7 ++- python/pyproject.toml | 1 + python/src/cucumber_messages/_messages.py | 55 ++++++----------------- python/tests/test_messages.py | 21 +++++++-- python/tests/test_model_load.py | 12 ++++- 6 files changed, 48 insertions(+), 50 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 87ea6402..84efd9d4 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -2,7 +2,7 @@ # See https://pre-commit.com/hooks.html for more hooks --- files: ^python/ -exclude: ^python/src/cucumber_messages/_messages\.py +exclude: .*python/src/cucumber_messages/_messages\.py repos: - repo: https://github.com/psf/black rev: 24.10.0 diff --git a/codegen/templates/python.py.erb b/codegen/templates/python.py.erb index d3e55351..6aee7733 100644 --- a/codegen/templates/python.py.erb +++ b/codegen/templates/python.py.erb @@ -7,12 +7,14 @@ from dataclasses import dataclass from enum import Enum from typing import Optional + <%- @enums.each do |enum| -%> class <%= enum[:name] %>(Enum): <%- enum[:values].each do |value| -%> <%= value.downcase.gsub(/[.\/+\s-]/, '_') %> = "<%= value %>" <%- end -%> + <%- end -%> <%- @schemas.each do |key, definition| -%> @dataclass @@ -41,12 +43,12 @@ class <%= class_name(key) %>: list_type = property_type.match(/list\[(.*?)\]/) inner_type = list_type[1] if inner_type =~ /^[A-Z]/ - property_type = "list['#{class_name(inner_type)}']" + property_type = "list[\"#{class_name(inner_type)}\"]" else property_type = "list[#{inner_type}]" end elsif property_type =~ /^[A-Z]/ - property_type = "'#{class_name(property_type)}'" + property_type = "\"#{class_name(property_type)}\"" end -%> <%- if property['description'] -%> @@ -62,4 +64,5 @@ class <%= class_name(key) %>: pass <%- end -%> + <%- end -%> \ No newline at end of file diff --git a/python/pyproject.toml b/python/pyproject.toml index 7ba32524..97de1563 100644 --- a/python/pyproject.toml +++ b/python/pyproject.toml @@ -58,6 +58,7 @@ test-coverage = [ [project.scripts] [tool.black] +force-exclude = ".*\\/src\\/cucumber_messages\\/_messages\\.py" line-length = 120 target-version = ["py39", "py310", "py311", "py312", "py313"] verbose = true diff --git a/python/src/cucumber_messages/_messages.py b/python/src/cucumber_messages/_messages.py index 7bcb7c4b..5b1acc61 100644 --- a/python/src/cucumber_messages/_messages.py +++ b/python/src/cucumber_messages/_messages.py @@ -61,19 +61,18 @@ class TestStepResultStatus(Enum): class Attachment: """ //// Attachments (parse errors, execution errors, screenshots, links...) - + * An attachment represents any kind of data associated with a line in a [Source](#io.cucumber.messages.Source) file. It can be used for: - + * Syntax errors during parse time * Screenshots captured and attached during execution * Logs captured and attached during execution - + It is not to be used for runtime errors raised/thrown during execution. This is captured in `TestResult`. """ - """ * The body of the attachment. If `contentEncoding` is `IDENTITY`, the attachment @@ -133,7 +132,6 @@ class Duration: The structure is pretty close of the Timestamp one. For clarity, a second type of message is used. """ - """ Non-negative fractions of a second at nanosecond resolution. Negative second values with fractions must still have non-negative nanos values @@ -150,12 +148,11 @@ class Envelope: When removing a field, replace it with reserved, rather than deleting the line. When adding a field, add it to the end and increment the number by one. See https://developers.google.com/protocol-buffers/docs/proto#updating for details - + * All the messages that are passed between different components/processes are Envelope messages. """ - attachment: Optional["Attachment"] = None gherkin_document: Optional["GherkinDocument"] = None hook: Optional["Hook"] = None @@ -182,7 +179,6 @@ class Exception: """ A simplified representation of an exception """ - """ The type of the exception that caused this result. E.g. "Error" or "org.opentest4j.AssertionFailedError" """ @@ -204,11 +200,10 @@ class GherkinDocument: The [AST](https://en.wikipedia.org/wiki/Abstract_syntax_tree) of a Gherkin document. Cucumber implementations should *not* depend on `GherkinDocument` or any of its children for execution - use [Pickle](#io.cucumber.messages.Pickle) instead. - + The only consumers of `GherkinDocument` should only be formatters that produce "rich" output, resembling the original Gherkin document. """ - """ All the comments in the Gherkin document """ @@ -241,7 +236,6 @@ class Comment: * A comment in a Gherkin document """ - """ The location of the comment """ @@ -286,7 +280,6 @@ class Feature: """ Zero or more children """ - children: list["FeatureChild"] """ The line(s) underneath the line with the `keyword` that are used as description @@ -320,7 +313,6 @@ class FeatureChild: * A child node of a `Feature` node """ - background: Optional["Background"] = None rule: Optional["Rule"] = None scenario: Optional["Scenario"] = None @@ -349,7 +341,6 @@ class RuleChild: * A child node of a `Rule` node """ - background: Optional["Background"] = None scenario: Optional["Scenario"] = None @@ -374,7 +365,6 @@ class Step: """ A step """ - """ Unique ID to be able to reference the Step from PickleStep """ @@ -401,7 +391,6 @@ class TableCell: """ A cell in a `TableRow` """ - """ The location of the cell """ @@ -417,7 +406,6 @@ class TableRow: """ A row in a table """ - """ Cells in the row """ @@ -435,7 +423,6 @@ class Tag: * A tag """ - """ Unique ID to be able to reference the Tag from PickleTag """ @@ -465,7 +452,6 @@ class Location: * Points to a line and a column in a text file """ - line: int column: Optional[int] = None @@ -477,7 +463,6 @@ class Meta: This message contains meta information about the environment. Consumers can use this for various purposes. """ - """ 386, arm, amd64 etc """ @@ -507,7 +492,6 @@ class Ci: """ CI environment """ - """ Name of the CI product, e.g. "Jenkins", "CircleCI" etc. """ @@ -529,7 +513,6 @@ class Git: Information about Git, provided by the Build/CI server as environment variables. """ - remote: str revision: str branch: Optional[str] = None @@ -541,7 +524,6 @@ class Product: """ Used to describe various properties of Meta """ - """ The product name """ @@ -575,20 +557,19 @@ class ParseError: class Pickle: """ //// Pickles - + * A `Pickle` represents a template for a `TestCase`. It is typically derived from another format, such as [GherkinDocument](#io.cucumber.messages.GherkinDocument). In the future a `Pickle` may be derived from other formats such as Markdown or Excel files. - + By making `Pickle` the main data structure Cucumber uses for execution, the implementation of Cucumber itself becomes simpler, as it doesn't have to deal with the complex structure of a [GherkinDocument](#io.cucumber.messages.GherkinDocument). - + Each `PickleStep` of a `Pickle` is matched with a `StepDefinition` to create a `TestCase` """ - """ * Points to the AST node locations of the pickle. The last one represents the unique @@ -637,7 +618,6 @@ class PickleStep: * An executable step """ - """ References the IDs of the source of the step. For Gherkin, this can be the ID of a Step, and possibly also the ID of a TableRow @@ -662,7 +642,6 @@ class PickleStepArgument: """ An optional argument """ - data_table: Optional["PickleTable"] = None doc_string: Optional["PickleDocString"] = None @@ -688,7 +667,6 @@ class PickleTag: * A tag """ - """ Points to the AST node this was created from """ @@ -700,11 +678,10 @@ class PickleTag: class Source: """ //// Source - + * A source file, typically a Gherkin document or Java/Ruby/JavaScript source code """ - """ The contents of the file """ @@ -729,7 +706,6 @@ class SourceReference: Points to a [Source](#io.cucumber.messages.Source) identified by `uri` and a [Location](#io.cucumber.messages.Location) within that file. """ - java_method: Optional["JavaMethod"] = None java_stack_trace_element: Optional["JavaStackTraceElement"] = None location: Optional["Location"] = None @@ -767,11 +743,10 @@ class StepDefinitionPattern: class TestCase: """ //// TestCases - + * A `TestCase` contains a sequence of `TestStep`s. """ - id: str """ The ID of the `Pickle` this `TestCase` is derived from. @@ -799,10 +774,9 @@ class StepMatchArgument: This is used for the following purposes: - Construct an argument to pass to a step definition (possibly through a parameter type transform) - Highlight the matched parameter in rich formatters such as the HTML formatter - + This message closely matches the `Argument` class in the `cucumber-expressions` library. """ - """ * Represents the outermost capture group of an argument. This message closely matches the @@ -824,7 +798,6 @@ class TestStep: A `TestStep` is derived from either a `PickleStep` combined with a `StepDefinition`, or from a `Hook`. """ - id: str """ Pointer to the `Hook` (if derived from a Hook) @@ -860,7 +833,6 @@ class TestCaseStarted: The first attempt should have value 0, and for each retry the value should increase by 1. """ - attempt: int """ * @@ -881,7 +853,6 @@ class TestRunFinished: """ A test run is successful if all steps are either passed or skipped, all before/after hooks passed and no other exceptions where thrown. """ - success: bool """ Timestamp when the TestRun is finished @@ -913,7 +884,6 @@ class TestRunHookStarted: """ Identifier for the hook that will be executed """ - hook_id: str """ Unique identifier for this hook execution @@ -969,7 +939,6 @@ class Timestamp: that count forward in time. Must be from 0 to 999,999,999 inclusive. """ - nanos: int """ Represents seconds of UTC time since Unix epoch @@ -983,3 +952,5 @@ class Timestamp: class UndefinedParameterType: expression: str name: str + + diff --git a/python/tests/test_messages.py b/python/tests/test_messages.py index dcd089f9..63190b7f 100644 --- a/python/tests/test_messages.py +++ b/python/tests/test_messages.py @@ -11,7 +11,12 @@ def converter(): def test_basic_attachment_serialization(converter): - data = {"body": "some body", "contentEncoding": "IDENTITY", "mediaType": "text/plain", "fileName": "myfile.txt"} + data = { + "body": "some body", + "contentEncoding": "IDENTITY", + "mediaType": "text/plain", + "fileName": "myfile.txt", + } attachment = converter.from_dict(data, Attachment) assert attachment.body == "some body" @@ -26,7 +31,11 @@ def test_basic_attachment_serialization(converter): def test_envelope_with_attachment(converter): data = { - "attachment": {"body": "some body", "contentEncoding": "BASE64", "mediaType": "text/x.cucumber.gherkin+plain"} + "attachment": { + "body": "some body", + "contentEncoding": "BASE64", + "mediaType": "text/x.cucumber.gherkin+plain", + } } envelope = converter.from_dict(data, Envelope) @@ -154,7 +163,13 @@ def test_test_step_result(converter): def test_missing_optional_fields(converter): # No optional fields set, serializer should handle defaults - data = {"attachment": {"body": "no optional fields", "contentEncoding": "IDENTITY", "mediaType": "text/plain"}} + data = { + "attachment": { + "body": "no optional fields", + "contentEncoding": "IDENTITY", + "mediaType": "text/plain", + } + } envelope = converter.from_dict(data, Envelope) assert envelope.attachment is not None diff --git a/python/tests/test_model_load.py b/python/tests/test_model_load.py index a5206776..5a801e02 100644 --- a/python/tests/test_model_load.py +++ b/python/tests/test_model_load.py @@ -17,7 +17,12 @@ def compatibility_kit_repo(tmpdir): str(repo_path), branch="main", ) - repo_tags = list(filter(lambda tag: tag is not None, map(lambda tag: getattr(tag.tag, "tag", None), repo.tags))) + repo_tags = list( + filter( + lambda tag: tag is not None, + map(lambda tag: getattr(tag.tag, "tag", None), repo.tags), + ) + ) version_pattern = re.compile(r"((.*/)?)v(\d+\.\d+\.\d+)") last_version = sorted( @@ -25,7 +30,10 @@ def compatibility_kit_repo(tmpdir): version.parse, map( lambda match: match.groups()[-1], - filter(lambda match: match is not None, map(lambda tag: re.match(version_pattern, tag), repo_tags)), + filter( + lambda match: match is not None, + map(lambda tag: re.match(version_pattern, tag), repo_tags), + ), ), ) )[-1]