sarj-python-lint 0.79.0__tar.gz → 0.79.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (127) hide show
  1. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/PKG-INFO +1 -1
  2. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/pyproject.toml +1 -1
  3. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/no_raw_connection_in_tests.py +47 -3
  4. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/.gitignore +0 -0
  5. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/LICENSE +0 -0
  6. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/README.md +0 -0
  7. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/__init__.py +0 -0
  8. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/__main__.py +0 -0
  9. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/_analysis_session.py +0 -0
  10. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/_filesystem.py +0 -0
  11. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/_ratchet_cli.py +0 -0
  12. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/_secret_names.py +0 -0
  13. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/_version.py +0 -0
  14. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/py.typed +0 -0
  15. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/ratchet.py +0 -0
  16. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rule_base.py +0 -0
  17. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/__init__.py +0 -0
  18. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/_ast_index.py +0 -0
  19. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/_comments.py +0 -0
  20. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/_docstrings.py +0 -0
  21. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/_fastapi.py +0 -0
  22. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/_first_party.py +0 -0
  23. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/_imports.py +0 -0
  24. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/_logging.py +0 -0
  25. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/_paths.py +0 -0
  26. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/_project_index.py +0 -0
  27. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/_prose_budget.py +0 -0
  28. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/_pytest.py +0 -0
  29. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/_registry.py +0 -0
  30. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/_sql.py +0 -0
  31. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/_suppression_comments.py +0 -0
  32. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/_test_assertions.py +0 -0
  33. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/defect_xfail_requires_explicit_strict.py +0 -0
  34. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/docstring_args_restate_signature.py +0 -0
  35. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/docstring_returns_restate_signature.py +0 -0
  36. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/fakes_in_shared_location.py +0 -0
  37. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/fastapi_explicit_openapi_contract.py +0 -0
  38. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/iac_source_coupled_test.py +0 -0
  39. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/invalid_pydantic_field_default.py +0 -0
  40. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/mock_without_spec.py +0 -0
  41. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/negative_only_http_status_assertion.py +0 -0
  42. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/no_analytical_aggregation_in_postgres_store.py +0 -0
  43. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/no_comment_cruft.py +0 -0
  44. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/no_conftest_test_module_import.py +0 -0
  45. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/no_copied_inherited_docstring.py +0 -0
  46. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/no_cors_wildcard_with_credentials.py +0 -0
  47. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/no_duplicate_dunder_all_entry.py +0 -0
  48. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/no_fastapi_on_event.py +0 -0
  49. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/no_file_level_escape_hatch_suppression.py +0 -0
  50. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/no_first_party_private_import.py +0 -0
  51. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/no_frozen_after_validator_field_write.py +0 -0
  52. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/no_generic_single_export_module.py +0 -0
  53. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/no_hidden_constructor_fallback.py +0 -0
  54. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/no_isinstance_union_chain.py +0 -0
  55. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/no_long_comment.py +0 -0
  56. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/no_nested_pydantic_field_validator.py +0 -0
  57. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/no_offset_pagination.py +0 -0
  58. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/no_optional_tenant_predicate.py +0 -0
  59. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/no_query_with_many_joins.py +0 -0
  60. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/no_random_uuid_in_sql.py +0 -0
  61. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/no_redundant_literal_description.py +0 -0
  62. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/no_repeated_string_literal.py +0 -0
  63. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/no_repeated_test_body.py +0 -0
  64. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/no_restated_comment.py +0 -0
  65. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/no_secret_in_log.py +0 -0
  66. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/no_select_star.py +0 -0
  67. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/no_sentinel_return_on_except.py +0 -0
  68. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/no_stdlib_logging.py +0 -0
  69. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/no_string_concat_in_loop.py +0 -0
  70. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/no_tautological_expect.py +0 -0
  71. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/no_typed_doc_sections.py +0 -0
  72. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/no_unique_violation_message_match.py +0 -0
  73. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/no_unnecessary_docstring.py +0 -0
  74. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/no_vague_suppression_description.py +0 -0
  75. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/opaque_parametrize_case_needs_id.py +0 -0
  76. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/over_mocked_test.py +0 -0
  77. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/phase_label_comment.py +0 -0
  78. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/prefer_class_row.py +0 -0
  79. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/prefer_collection_comprehension.py +0 -0
  80. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/prefer_constant_time_secret_compare.py +0 -0
  81. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/prefer_fstring_over_concat.py +0 -0
  82. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/prefer_immutable_module_constant.py +0 -0
  83. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/prefer_library_fake.py +0 -0
  84. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/prefer_match_assert_never.py +0 -0
  85. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/prefer_match_type_dispatch.py +0 -0
  86. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/prefer_module_level_constant.py +0 -0
  87. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/prefer_namedtuple_over_tuple_return.py +0 -0
  88. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/prefer_nominal_id_types.py +0 -0
  89. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/prefer_non_nullable_collection.py +0 -0
  90. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/prefer_one_for_required_row.py +0 -0
  91. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/prefer_or_pattern.py +0 -0
  92. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/prefer_self_documenting_constant.py +0 -0
  93. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/prefer_self_type_annotation.py +0 -0
  94. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/prefer_set_isdisjoint.py +0 -0
  95. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/prefer_str_enum.py +0 -0
  96. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/prefer_struct_over_namedtuple.py +0 -0
  97. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/prefer_timedelta_for_durations.py +0 -0
  98. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/prefer_walrus_comprehension_filter.py +0 -0
  99. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/prefer_walrus_regex_match.py +0 -0
  100. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/prefer_walrus_stream_loop.py +0 -0
  101. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/preserve_declared_nominal_id.py +0 -0
  102. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/preserve_enum_types.py +0 -0
  103. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/production_derived_test_cases.py +0 -0
  104. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/pydantic_at_boundaries.py +0 -0
  105. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/pytest_fixture_returns_bare_tuple.py +0 -0
  106. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/redundant_class_docstring.py +0 -0
  107. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/redundant_docstring.py +0 -0
  108. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/redundant_module_docstring.py +0 -0
  109. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/repeated_kwarg_heavy_call_in_test.py +0 -0
  110. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/repeated_static_call_cases.py +0 -0
  111. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/require_keyword_only_swap_prone_params.py +0 -0
  112. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/require_nodecode_for_splitting_settings_field.py +0 -0
  113. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/require_port_for_service.py +0 -0
  114. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/require_pydantic_for_external_json.py +0 -0
  115. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/require_pydantic_ordinal_lower_bound.py +0 -0
  116. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/require_validated_row_factory.py +0 -0
  117. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/restated_test_docstring.py +0 -0
  118. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/source_coupled_test.py +0 -0
  119. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/sql_requires_injected_pool_owner.py +0 -0
  120. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/stepdown.py +0 -0
  121. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/store_get_delegates_to_bulk_read.py +0 -0
  122. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/store_insert_requires_on_conflict.py +0 -0
  123. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/timestamp_order_requires_tiebreaker.py +0 -0
  124. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/trailing_value_narration.py +0 -0
  125. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/trivially_true_assertion.py +0 -0
  126. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/uncontrolled_randomness_in_test.py +0 -0
  127. {sarj_python_lint-0.79.0 → sarj_python_lint-0.79.1}/src/sarj_python_lint/rules/unused_mock_setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: sarj-python-lint
3
- Version: 0.79.0
3
+ Version: 0.79.1
4
4
  Summary: Custom Python lint rules — AST-based, pre-commit-friendly, hypermodern defaults
5
5
  Project-URL: Homepage, https://code-standards.sarj.ai/rules/python/
6
6
  Project-URL: Documentation, https://code-standards.sarj.ai/rules/python/
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "sarj-python-lint"
3
- version = "0.79.0"
3
+ version = "0.79.1"
4
4
  description = "Custom Python lint rules — AST-based, pre-commit-friendly, hypermodern defaults"
5
5
  readme = "README.md"
6
6
  authors = [{ name = "sarj-ai" }]
@@ -15,7 +15,7 @@ from sarj_python_lint.rule_base import (
15
15
  RuleExample,
16
16
  parse_or_none,
17
17
  )
18
- from sarj_python_lint.rules._paths import is_generated, is_test_path
18
+ from sarj_python_lint.rules._paths import is_generated, is_test_path, is_test_support_path
19
19
 
20
20
 
21
21
  if TYPE_CHECKING:
@@ -42,8 +42,9 @@ class NoRawConnectionInTests(Rule):
42
42
  category=RuleCategory.TESTING,
43
43
  autofix=AutofixPolicy.NONE,
44
44
  limitations=(
45
- "Only test paths are inspected.",
45
+ "Only test paths outside conftest.py and conventional shared test-support modules are inspected.",
46
46
  "A receiver is reported only when a parameter, annotated local, or constructor call proves it is a psycopg ConnectionPool or AsyncConnectionPool.",
47
+ "Pytest fixtures may use a connection internally for setup and cleanup, but fixtures that return or yield the connection remain reportable.",
47
48
  ),
48
49
  examples=(
49
50
  RuleExample(
@@ -80,7 +81,12 @@ class NoRawConnectionInTests(Rule):
80
81
 
81
82
  @override
82
83
  def check(self, path: Path, source: str) -> list[Diagnostic]:
83
- if not is_test_path(path) or is_generated(path, source):
84
+ if (
85
+ not is_test_path(path)
86
+ or path.name == "conftest.py"
87
+ or is_test_support_path(path)
88
+ or is_generated(path, source)
89
+ ):
84
90
  return []
85
91
  tree = parse_or_none(path, source)
86
92
  if tree is None:
@@ -109,6 +115,7 @@ class NoRawConnectionInTests(Rule):
109
115
  and node.func.attr == "connection"
110
116
  and isinstance(node.func.value, ast.Name)
111
117
  and node.func.value.id in pool_names
118
+ and not _is_internal_fixture_connection(scope, node)
112
119
  )
113
120
  return sorted(diagnostics, key=lambda item: (item.line, item.col))
114
121
 
@@ -152,3 +159,40 @@ def _tail(node: ast.expr | None) -> str:
152
159
  return _tail(value)
153
160
  case _:
154
161
  return ""
162
+
163
+
164
+ def _is_internal_fixture_connection(
165
+ scope: ast.Module | ast.FunctionDef | ast.AsyncFunctionDef, connection_call: ast.Call
166
+ ) -> bool:
167
+ if not isinstance(scope, (ast.FunctionDef, ast.AsyncFunctionDef)) or not _is_pytest_fixture(scope):
168
+ return False
169
+ context_item = next(
170
+ (
171
+ item
172
+ for node in _scope_nodes(scope)
173
+ if isinstance(node, (ast.With, ast.AsyncWith))
174
+ for item in node.items
175
+ if item.context_expr is connection_call
176
+ ),
177
+ None,
178
+ )
179
+ if context_item is None:
180
+ return False
181
+ if context_item.optional_vars is None:
182
+ return True
183
+ if not isinstance(context_item.optional_vars, ast.Name):
184
+ return False
185
+ bound_name = context_item.optional_vars.id
186
+ return not any(
187
+ isinstance(node, (ast.Return, ast.Yield, ast.YieldFrom))
188
+ and node.value is not None
189
+ and any(isinstance(value, ast.Name) and value.id == bound_name for value in ast.walk(node.value))
190
+ for node in _scope_nodes(scope)
191
+ )
192
+
193
+
194
+ def _is_pytest_fixture(scope: ast.FunctionDef | ast.AsyncFunctionDef) -> bool:
195
+ return any(
196
+ _tail(decorator.func if isinstance(decorator, ast.Call) else decorator) == "fixture"
197
+ for decorator in scope.decorator_list
198
+ )