Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion features/steps/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
}


def pytest_collection_modifyitems(items):
def pytest_collection_modifyitems(items) -> None:
"""AI: Convert bare Examples-block tags into properly configured xfail markers."""
for item in items:
for tag, xfail_kwargs in _XFAIL_TAGS.items():
Expand Down
20 changes: 10 additions & 10 deletions features/steps/test_refactor.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ def __getattr__(self, name):
"""AI: Return the dict item named `name` as an attribute."""
return self[name]

def __setattr__(self, name, value):
def __setattr__(self, name, value) -> None:
"""AI: Set the dict item named `name` as an attribute."""
self[name] = value

Expand All @@ -36,24 +36,24 @@ def context():
encoding="utf-8",
features_base_dir=str(FEATURES_BASE_DIR),
)
def test_refactor_python_file():
def test_refactor_python_file() -> None:
"""AI: Scenario test for the 'python code' refactor-python-file.feature scenario."""


@given("'python' programming language")
def init_language_factory(context):
def init_language_factory(context) -> None:
"""AI: Initialize the AST factory for the Python programming language."""
context["factory"] = ASTFactory(PythonRstNode, "")


@given(parsers.parse("'{file}' file written in that programming language"))
def step_given_file_in_language(context, file):
def step_given_file_in_language(context, file) -> None:
"""AI: Parse the given file into an AST using the scenario's factory."""
context["atu"] = context["factory"].create(FEATURES_BASE_DIR / Path(file))


@given(parsers.parse("node '{old}' exits within that AST"))
def step_given_node_exists(context, old):
def step_given_node_exists(context, old) -> None:
"""AI: Assert that a node matching the given pattern exists in the AST."""
pattern_factory = PythonPatternFactory(context["factory"])
find = pattern_factory.create_statements(old)
Expand All @@ -62,32 +62,32 @@ def step_given_node_exists(context, old):


@given("a sequence of descendant nodes of that node")
def step_given_descendant_nodes(context):
def step_given_descendant_nodes(context) -> None:
"""AI: Assert that the matched node has descendant children."""
assert context["result"][0].nodes[0].children


@when(parsers.parse("that node is replaced by '{replacement}'"))
def step_when_node_replaced(context, replacement):
def step_when_node_replaced(context, replacement) -> None:
"""AI: Queue a replacement of the matched node with the given text."""
context["replacement"] = replacement
context["rewriter"] = ASTRewriter(context["atu"])
context["rewriter"].replace(replacement, context["result"][0].nodes)


@when("rewrites replace is performed on that sequence of descendant nodes")
def step_when_rewrites_applied(context):
def step_when_rewrites_applied(context) -> None:
"""AI: Apply the queued rewrite to the AST."""
context["rewriter"].apply()


@then("in the modified source file that node is replaced by the given text")
def step_then_replaced_in_source(context):
def step_then_replaced_in_source(context) -> None:
"""AI: Assert the replacement text appears in the rewritten source."""
assert context["replacement"] in context["rewriter"].apply_to_string()


@then("all rewrites on that sequence of descendant nodes are not performed or hidden")
def step_then_rewrites_not_performed_or_hidden(context):
def step_then_rewrites_not_performed_or_hidden(context) -> None:
"""AI: Assert the rewriter reports pending, unapplied changes."""
assert context["rewriter"].has_changed()
66 changes: 33 additions & 33 deletions features/steps/test_rewrite_semantics.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
# Scenario 0 — Scenario Outline: three representative examples.
# Universal property test: test/syntax_tree/test_rewrite_semantics_properties.py
@scenario(_FEATURE, "Replacements of the same node produce an error")
def test_replacements_of_same_node_produce_error():
def test_replacements_of_same_node_produce_error() -> None:
"""AI: Scenario test for 'Replacements of the same node produce an error'."""


Expand All @@ -50,37 +50,37 @@ def test_replacements_of_same_node_produce_error():
strict=True,
)
@scenario(_FEATURE, "Dominated change is not applied")
def test_dominated_change_not_applied():
def test_dominated_change_not_applied() -> None:
"""AI: Scenario test for 'Dominated change is not applied'."""


@scenario(_FEATURE, "Overlapping replacements produce an error")
def test_overlapping_replacements_produce_error():
def test_overlapping_replacements_produce_error() -> None:
"""AI: Scenario test for 'Overlapping replacements produce an error'."""


@scenario(_FEATURE, "Prepend of ancestor precedes prepend of descendant regardless of collection order")
def test_prepend_ordering():
def test_prepend_ordering() -> None:
"""AI: Scenario test for 'Prepend of ancestor precedes prepend of descendant regardless of collection order'."""


@scenario(_FEATURE, "Append of descendant precedes append of ancestor regardless of collection order")
def test_append_ordering():
def test_append_ordering() -> None:
"""AI: Scenario test for 'Append of descendant precedes append of ancestor regardless of collection order'."""


@scenario(_FEATURE, "Operation on first sibling precedes operation on second sibling \u2014 first sibling collected first")
def test_sibling_sib1_first():
def test_sibling_sib1_first() -> None:
"""AI: Scenario test for 'Operation on first sibling precedes operation on second sibling' (first sibling collected first)."""


@scenario(_FEATURE, "Operation on first sibling precedes operation on second sibling \u2014 second sibling collected first")
def test_sibling_sib2_first():
def test_sibling_sib2_first() -> None:
"""AI: Scenario test for 'Operation on first sibling precedes operation on second sibling' (second sibling collected first)."""


@scenario(_FEATURE, "Replacements of the same sibling range produce an error")
def test_replacements_of_same_sibling_range_produce_error():
def test_replacements_of_same_sibling_range_produce_error() -> None:
"""AI: Scenario test for 'Replacements of the same sibling range produce an error'."""


Expand All @@ -89,7 +89,7 @@ def test_replacements_of_same_sibling_range_produce_error():
strict=True,
)
@scenario(_FEATURE, "Sibling range dominates a proper subrange regardless of collection order")
def test_sibling_range_dominates_proper_subrange():
def test_sibling_range_dominates_proper_subrange() -> None:
"""AI: Scenario test for 'Sibling range dominates a proper subrange regardless of collection order'."""


Expand All @@ -98,12 +98,12 @@ def test_sibling_range_dominates_proper_subrange():
strict=True,
)
@scenario(_FEATURE, "Sibling range dominates a single contained sibling regardless of collection order")
def test_sibling_range_dominates_single_sibling():
def test_sibling_range_dominates_single_sibling() -> None:
"""AI: Scenario test for 'Sibling range dominates a single contained sibling regardless of collection order'."""


@scenario(_FEATURE, "Prepends of same node are applied in order of collection.")
def test_prepends_of_same_node_in_order():
def test_prepends_of_same_node_in_order() -> None:
"""AI: Scenario test for 'Prepends of same node are applied in order of collection.'."""


Expand All @@ -112,7 +112,7 @@ def test_prepends_of_same_node_in_order():
strict=True,
)
@scenario(_FEATURE, "Appends of same node are applied in reversed order of collection.")
def test_appends_of_same_node_in_reversed_order():
def test_appends_of_same_node_in_reversed_order() -> None:
"""AI: Scenario test for 'Appends of same node are applied in reversed order of collection.'."""


Expand All @@ -121,22 +121,22 @@ def test_appends_of_same_node_in_reversed_order():
strict=True,
)
@scenario(_FEATURE, "Surrounds of same node: before texts in collection order, after texts in reversed collection order")
def test_surrounds_of_same_node():
def test_surrounds_of_same_node() -> None:
"""AI: Scenario test for 'Surrounds of same node' before/after text ordering."""


@scenario(_FEATURE, "Surround of ancestor precedes surround of descendant at shared start location regardless of collection order")
def test_surround_ancestor_precedes_surround_descendant_start():
def test_surround_ancestor_precedes_surround_descendant_start() -> None:
"""AI: Scenario test for 'Surround of ancestor precedes surround of descendant at shared start location'."""


@scenario(_FEATURE, "Surround of descendant precedes surround of ancestor at shared end location regardless of collection order")
def test_surround_descendant_precedes_surround_ancestor_end():
def test_surround_descendant_precedes_surround_ancestor_end() -> None:
"""AI: Scenario test for 'Surround of descendant precedes surround of ancestor at shared end location'."""


@scenario(_FEATURE, "Prepend is outside surround of the same node \u2014 prepend collected first")
def test_prepend_outside_surround_prepend_first():
def test_prepend_outside_surround_prepend_first() -> None:
"""AI: Scenario test for 'Prepend is outside surround of the same node' (prepend collected first)."""


Expand All @@ -146,7 +146,7 @@ def test_prepend_outside_surround_prepend_first():
strict=True,
)
@scenario(_FEATURE, "Prepend is outside surround of the same node \u2014 surround collected first")
def test_prepend_outside_surround_surround_first():
def test_prepend_outside_surround_surround_first() -> None:
"""AI: Scenario test for 'Prepend is outside surround of the same node' (surround collected first)."""


Expand All @@ -156,17 +156,17 @@ def test_prepend_outside_surround_surround_first():
strict=True,
)
@scenario(_FEATURE, "Append is outside surround of the same node \u2014 append collected first")
def test_append_outside_surround_append_first():
def test_append_outside_surround_append_first() -> None:
"""AI: Scenario test for 'Append is outside surround of the same node' (append collected first)."""


@scenario(_FEATURE, "Append is outside surround of the same node \u2014 surround collected first")
def test_append_outside_surround_surround_first():
def test_append_outside_surround_surround_first() -> None:
"""AI: Scenario test for 'Append is outside surround of the same node' (surround collected first)."""


@scenario(_FEATURE, "Prepend appears before replacement of the same node \u2014 prepend collected first")
def test_prepend_before_replacement_prepend_first():
def test_prepend_before_replacement_prepend_first() -> None:
"""AI: Scenario test for 'Prepend appears before replacement of the same node' (prepend collected first)."""


Expand All @@ -176,17 +176,17 @@ def test_prepend_before_replacement_prepend_first():
strict=True,
)
@scenario(_FEATURE, "Prepend appears before replacement of the same node \u2014 replace collected first")
def test_prepend_before_replacement_replace_first():
def test_prepend_before_replacement_replace_first() -> None:
"""AI: Scenario test for 'Prepend appears before replacement of the same node' (replace collected first)."""


@scenario(_FEATURE, "Replacement appears before append of the same node \u2014 replace collected first")
def test_replacement_before_append_replace_first():
def test_replacement_before_append_replace_first() -> None:
"""AI: Scenario test for 'Replacement appears before append of the same node' (replace collected first)."""


@scenario(_FEATURE, "Replacement appears before append of the same node \u2014 append collected first")
def test_replacement_before_append_append_first():
def test_replacement_before_append_append_first() -> None:
"""AI: Scenario test for 'Replacement appears before append of the same node' (append collected first)."""


Expand All @@ -196,12 +196,12 @@ def test_replacement_before_append_append_first():
strict=True,
)
@scenario(_FEATURE, "Surround wraps replacement of the same node \u2014 replace collected first")
def test_surround_wraps_replacement_replace_first():
def test_surround_wraps_replacement_replace_first() -> None:
"""AI: Scenario test for 'Surround wraps replacement of the same node' (replace collected first)."""


@scenario(_FEATURE, "Surround wraps replacement of the same node \u2014 surround collected first")
def test_surround_wraps_replacement_surround_first():
def test_surround_wraps_replacement_surround_first() -> None:
"""AI: Scenario test for 'Surround wraps replacement of the same node' (surround collected first)."""


Expand All @@ -211,17 +211,17 @@ def test_surround_wraps_replacement_surround_first():
strict=True,
)
@scenario(_FEATURE, "Prepend of descendant is inside surround of ancestor at shared start location \u2014 prepend collected first")
def test_prepend_descendant_inside_surround_ancestor_start_prepend_first():
def test_prepend_descendant_inside_surround_ancestor_start_prepend_first() -> None:
"""AI: Scenario test for 'Prepend of descendant is inside surround of ancestor at shared start location' (prepend collected first)."""


@scenario(_FEATURE, "Prepend of descendant is inside surround of ancestor at shared start location \u2014 surround collected first")
def test_prepend_descendant_inside_surround_ancestor_start_surround_first():
def test_prepend_descendant_inside_surround_ancestor_start_surround_first() -> None:
"""AI: Scenario test for 'Prepend of descendant is inside surround of ancestor at shared start location' (surround collected first)."""


@scenario(_FEATURE, "Append of descendant is inside surround of ancestor at shared end location \u2014 append collected first")
def test_append_descendant_inside_surround_ancestor_end_append_first():
def test_append_descendant_inside_surround_ancestor_end_append_first() -> None:
"""AI: Scenario test for 'Append of descendant is inside surround of ancestor at shared end location' (append collected first)."""


Expand All @@ -231,12 +231,12 @@ def test_append_descendant_inside_surround_ancestor_end_append_first():
strict=True,
)
@scenario(_FEATURE, "Append of descendant is inside surround of ancestor at shared end location \u2014 surround collected first")
def test_append_descendant_inside_surround_ancestor_end_surround_first():
def test_append_descendant_inside_surround_ancestor_end_surround_first() -> None:
"""AI: Scenario test for 'Append of descendant is inside surround of ancestor at shared end location' (surround collected first)."""


@scenario(_FEATURE, "Surround of descendant is inside prepend of ancestor at shared start location \u2014 prepend collected first")
def test_surround_descendant_inside_prepend_ancestor_start_prepend_first():
def test_surround_descendant_inside_prepend_ancestor_start_prepend_first() -> None:
"""AI: Scenario test for 'Surround of descendant is inside prepend of ancestor at shared start location' (prepend collected first)."""


Expand All @@ -246,7 +246,7 @@ def test_surround_descendant_inside_prepend_ancestor_start_prepend_first():
strict=True,
)
@scenario(_FEATURE, "Surround of descendant is inside prepend of ancestor at shared start location \u2014 surround collected first")
def test_surround_descendant_inside_prepend_ancestor_start_surround_first():
def test_surround_descendant_inside_prepend_ancestor_start_surround_first() -> None:
"""AI: Scenario test for 'Surround of descendant is inside prepend of ancestor at shared start location' (surround collected first)."""


Expand All @@ -256,12 +256,12 @@ def test_surround_descendant_inside_prepend_ancestor_start_surround_first():
strict=True,
)
@scenario(_FEATURE, "Surround of descendant is inside append of ancestor at shared end location \u2014 append collected first")
def test_surround_descendant_inside_append_ancestor_end_append_first():
def test_surround_descendant_inside_append_ancestor_end_append_first() -> None:
"""AI: Scenario test for 'Surround of descendant is inside append of ancestor at shared end location' (append collected first)."""


@scenario(_FEATURE, "Surround of descendant is inside append of ancestor at shared end location \u2014 surround collected first")
def test_surround_descendant_inside_append_ancestor_end_surround_first():
def test_surround_descendant_inside_append_ancestor_end_surround_first() -> None:
"""AI: Scenario test for 'Surround of descendant is inside append of ancestor at shared end location' (surround collected first)."""


Expand Down
10 changes: 5 additions & 5 deletions features/steps/test_steps.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
class Ast:
"""AI: Hold the parsed AST state shared across BDD refactor steps."""

def __init__(self):
def __init__(self) -> None:
"""AI: Hold the parsed AST state shared across BDD refactor steps."""
self.file = ""
self.atu = None
Expand All @@ -29,7 +29,7 @@ def context():


@given(parsers.parse("'{file}' file"))
def step_given_file(context, file):
def step_given_file(context, file) -> None:
"""AI: Parse the named file into an AST and record its signature."""
context.file = str(FEATURES_DIR / file)
context.factory = PythonFactory(PythonRstNode)
Expand All @@ -39,15 +39,15 @@ def step_given_file(context, file):

@given(parsers.parse("it contains '{statement}'"))
@then(parsers.parse("it should contain '{statement}'"))
def step_given_contains(context, statement):
def step_given_contains(context, statement) -> None:
"""AI: Assert the AST signature contains the given statement."""
statement = statement.replace("\\n", "\n")
assert_that(context.signature, contains_string(statement), f"Expected '{statement}' in source")


@given("an AST extracted from that source file without errors")
@then("AST extracted from that conversion should without errors")
def step_given_ast_no_errors(context):
def step_given_ast_no_errors(context) -> None:
"""AI: Assert diagnostics can be checked without raising an exception."""
assert_that(
calling(context.atu.translation_unit.check_diagnostics),
Expand All @@ -56,6 +56,6 @@ def step_given_ast_no_errors(context):


@then(parsers.parse("it should not contain '{statement}'"))
def step_then_not_contain(context, statement):
def step_then_not_contain(context, statement) -> None:
"""AI: Assert the AST signature does not contain the given statement."""
assert_that(context.signature, not_(contains_string(statement)))
4 changes: 2 additions & 2 deletions features/steps/test_taut_refactor.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@
encoding="utf-8",
features_base_dir=str(FEATURES_BASE_DIR),
)
def test_taut_test():
def test_taut_test() -> None:
"""AI: Scenario test for the 'migrate taut to unittest without syntax errors' scenario."""


@when("I convert taut to unittest")
def step_when_convert(context):
def step_when_convert(context) -> None:
"""AI: Convert the scenario's taut test file to a Python unittest and record its output."""
converter = TautToPythonUnittest(context.file)
converter.in_memory = True
Expand Down
4 changes: 2 additions & 2 deletions features/steps/unit_to_pytest_steps.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@


@scenario("convert-unit-to-pytest.feature", "convert unittest to pytest", "utf-8", "..")
def test_convert_unit_to_pytest():
def test_convert_unit_to_pytest() -> None:
"""AI: Scenario test for the 'convert unittest to pytest' scenario."""


@when("I convert it to pytest")
def step_when_convert(context):
def step_when_convert(context) -> None:
"""AI: Convert the scenario's unittest file to pytest and re-parse it."""
converter = UnitToPytest(context.file)
converter.run()
Expand Down
Loading
Loading