Skip to content

Commit 28b2d98

Browse files
authored
Enable ruff rules on tests folder (#3969)
1 parent 8384a39 commit 28b2d98

18 files changed

+145
-28
lines changed

pyproject.toml

Lines changed: 125 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,131 @@ ignore = [
207207
]
208208
"utils/waf_rules.py" = ["N801"] # generated file
209209
# TODO : remove those ignores
210-
"tests/*" = ["ALL"]
210+
"tests/*" = [
211+
# lines with [*] can be autofixed with ruff check --fix --unsafe-fixes
212+
# though, each change must be reviewed
213+
"ANN201", # 2043 occurences [ ] missing-return-type-undocumented-public-function
214+
"N801", # 492 occurences [ ] invalid-class-name
215+
"D212", # 202 occurences [*] multi-line-summary-first-line
216+
"ARG002", # 177 occurences [ ] unused-method-argument
217+
"E501", # 159 occurences [ ] line-too-long
218+
"SIM117", # 127 occurences [ ] multiple-with-statements
219+
"F401", # 90 occurences [*] unused-import
220+
"TID252", # 77 occurences [*] relative-imports
221+
"N806", # 76 occurences [ ] non-lowercase-variable-in-function
222+
"FBT003", # 67 occurences [ ] boolean-positional-value-in-call
223+
"D403", # 61 occurences [*] first-line-capitalized
224+
"D200", # 52 occurences [*] fits-on-one-line
225+
"F405", # 43 occurences [ ] undefined-local-with-import-star-usage
226+
"TRY002", # 41 occurences [ ] raise-vanilla-class
227+
"PT018", # 39 occurences [ ] pytest-composite-assertion
228+
"N802", # 39 occurences [ ] invalid-function-name
229+
"UP006", # 35 occurences [*] non-pep585-annotation
230+
"FBT002", # 30 occurences [ ] boolean-default-value-positional-argument
231+
"SIM300", # 30 occurences [*] yoda-conditions
232+
"F541", # 30 occurences [*] f-string-missing-placeholders
233+
"F841", # 28 occurences [*] unused-variable
234+
"UP015", # 27 occurences [*] redundant-open-modes
235+
"RET502", # 25 occurences [*] implicit-return-value
236+
"D404", # 25 occurences [ ] docstring-starts-with-this
237+
"ANN401", # 24 occurences [ ] any-type
238+
"D209", # 24 occurences [*] new-line-after-last-paragraph
239+
"B007", # 23 occurences [ ] unused-loop-control-variable
240+
"DTZ005", # 23 occurences [ ] call-datetime-now-without-tzinfo
241+
"INP001", # 22 occurences [ ] implicit-namespace-package
242+
"ARG001", # 21 occurences [ ] unused-function-argument
243+
"UP031", # 17 occurences [ ] printf-string-formatting
244+
"UP032", # 17 occurences [*] f-string
245+
"ANN205", # 16 occurences [ ] missing-return-type-static-method
246+
"T201", # 15 occurences [*] print
247+
"RET505", # 15 occurences [*] superfluous-else-return
248+
"UP007", # 13 occurences [*] non-pep604-annotation
249+
"FBT001", # 12 occurences [ ] boolean-type-hint-positional-argument
250+
"SLF001", # 12 occurences [ ] private-member-access
251+
"SIM118", # 12 occurences [*] in-dict-keys
252+
"F811", # 12 occurences [*] redefined-while-unused
253+
"UP035", # 12 occurences [ ] deprecated-import
254+
"S105", # 10 occurences [ ] hardcoded-password-string
255+
"B015", # 10 occurences [ ] useless-comparison
256+
"RET503", # 9 occurences [*] implicit-return
257+
"SIM115", # 9 occurences [ ] open-file-with-context-handler
258+
"PGH004", # 9 occurences [ ] blanket-noqa
259+
"RUF001", # 9 occurences [ ] ambiguous-unicode-character-string
260+
"RUF015", # 9 occurences [*] unnecessary-iterable-allocation-for-first-element
261+
"RUF100", # 9 occurences [*] unused-noqa
262+
"SIM108", # 8 occurences [*] if-else-block-instead-of-if-exp
263+
"PTH120", # 8 occurences [ ] os-path-dirname
264+
"PGH003", # 8 occurences [ ] blanket-type-ignore
265+
"TRY301", # 8 occurences [ ] raise-within-try
266+
"ANN206", # 7 occurences [ ] missing-return-type-class-method
267+
"B011", # 7 occurences [*] assert-false
268+
"PT015", # 7 occurences [ ] pytest-assert-always-false
269+
"N815", # 7 occurences [ ] mixed-case-variable-in-class-scope
270+
"A001", # 6 occurences [ ] builtin-variable-shadowing
271+
"PT006", # 6 occurences [*] pytest-parametrize-names-wrong-type
272+
"RET504", # 6 occurences [*] unnecessary-assign
273+
"SIM114", # 6 occurences [*] if-with-same-arms
274+
"N803", # 6 occurences [ ] invalid-argument-name
275+
"E712", # 6 occurences [*] true-false-comparison
276+
"E741", # 6 occurences [ ] ambiguous-variable-name
277+
"S113", # 5 occurences [ ] request-without-timeout
278+
"PT011", # 5 occurences [ ] pytest-raises-too-broad
279+
"E731", # 5 occurences [*] lambda-assignment
280+
"RUF005", # 5 occurences [ ] collection-literal-concatenation
281+
"B006", # 4 occurences [*] mutable-argument-default
282+
"PIE794", # 4 occurences [*] duplicate-class-field-definition
283+
"PTH103", # 4 occurences [ ] os-makedirs
284+
"E711", # 4 occurences [*] none-comparison
285+
"E721", # 4 occurences [ ] type-comparison
286+
"PLR5501", # 4 occurences [*] collapsible-else-if
287+
"PLW2901", # 4 occurences [ ] redefined-loop-name
288+
"RUF003", # 4 occurences [ ] ambiguous-unicode-character-comment
289+
"RUF010", # 4 occurences [*] explicit-f-string-type-conversion
290+
"B904", # 3 occurences [ ] raise-without-from-inside-except
291+
"A002", # 3 occurences [ ] builtin-argument-shadowing
292+
"RET507", # 3 occurences [*] superfluous-else-continue
293+
"PTH112", # 3 occurences [ ] os-path-isdir
294+
"W291", # 3 occurences [*] trailing-whitespace
295+
"UP003", # 3 occurences [*] type-of-primitive
296+
"UP034", # 3 occurences [*] extraneous-parentheses
297+
"RUF017", # 3 occurences [*] quadratic-list-summation
298+
"ANN002", # 2 occurences [ ] missing-type-args
299+
"ASYNC230", # 2 occurences [ ] blocking-open-call-in-async-function
300+
"S605", # 2 occurences [ ] start-process-with-a-shell
301+
"C408", # 2 occurences [*] unnecessary-collection-call
302+
"C416", # 2 occurences [*] unnecessary-comprehension
303+
"FIX003", # 2 occurences [ ] line-contains-xxx
304+
"PIE810", # 2 occurences [*] multiple-starts-ends-with
305+
"T203", # 2 occurences [*] p-print
306+
"ARG005", # 2 occurences [ ] unused-lambda-argument
307+
"PTH100", # 2 occurences [ ] os-path-abspath
308+
"PTH109", # 2 occurences [ ] os-getcwd
309+
"E401", # 2 occurences [*] multiple-imports-on-one-line
310+
"D210", # 2 occurences [ ] surrounding-whitespace
311+
"D300", # 2 occurences [*] triple-single-quotes
312+
"FURB129", # 2 occurences [*] readlines-in-for
313+
"RUF002", # 2 occurences [ ] ambiguous-unicode-character-docstring
314+
"ASYNC251", # 1 occurences [ ] blocking-sleep-in-async-function
315+
"S108", # 1 occurences [ ] hardcoded-temp-file
316+
"S110", # 1 occurences [ ] try-except-pass
317+
"B033", # 1 occurences [*] duplicate-value
318+
"B905", # 1 occurences [*] zip-without-explicit-strict
319+
"C400", # 1 occurences [*] unnecessary-generator-list
320+
"C401", # 1 occurences [*] unnecessary-generator-set
321+
"C413", # 1 occurences [*] unnecessary-call-around-sorted
322+
"SIM105", # 1 occurences [ ] suppressible-exception
323+
"TD005", # 1 occurences [ ] missing-todo-description
324+
"PTH113", # 1 occurences [ ] os-path-isfile
325+
"F403", # 1 occurences [ ] undefined-local-with-import-star
326+
"PLC0206", # 1 occurences [ ] dict-index-missing-items
327+
"PLR0133", # 1 occurences [ ] comparison-of-constant
328+
"RUF006", # 1 occurences [ ] asyncio-dangling-task
329+
330+
# keep those rules
331+
"PLR1730", # if-stmt-min-max: not clear that it makes the code easier to read
332+
"RET506", # superfluous-else-raise: requires a slightly higher cognitive effort to understand the code
333+
"RET508", # superfluous-else-break: : requires a slightly higher cognitive effort to understand the code
334+
]
211335
"utils/build/*" = ["ALL"]
212336
"lib-injection/*" = ["ALL"]
213337
"utils/{k8s_lib_injection/*,_context/_scenarios/k8s_lib_injection.py}" = [

tests/appsec/waf/test_addresses.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -450,7 +450,7 @@ class Test_GrpcServerMethod:
450450

451451
def validate_span(self, span, appsec_data):
452452
tag = "rpc.grpc.full_method"
453-
if not tag in span["meta"]:
453+
if tag not in span["meta"]:
454454
logger.info(f"Can't find '{tag}' in span's meta")
455455
return False
456456

tests/debugger/test_debugger_pii.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -224,8 +224,6 @@ def test_pii_redaction_line_full(self):
224224
self._assert(REDACTED_KEYS, REDACTED_TYPES, line_probe=True)
225225

226226
############ old versions ############
227-
def filter(keys_to_filter):
228-
return [item for item in REDACTED_KEYS if item not in keys_to_filter]
229227

230228
def setup_pii_redaction_java_1_33(self):
231229
self._setup()

tests/debugger/test_debugger_symdb.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,7 @@ def check_scope(scope):
4242
name = scope.get("name", "")
4343
if re.search(pattern, name):
4444
scope_type = scope.get("scope_type", "")
45-
if scope_type in ["CLASS", "class", "MODULE"]:
46-
return True
47-
48-
return False
45+
return scope_type in ["CLASS", "class", "MODULE"]
4946

5047
for nested_scope in scope.get("scopes", []):
5148
if check_scope(nested_scope):

tests/fuzzer/core.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ def __call__(self, payload):
5151
return
5252

5353
if self.logger is None:
54-
self.logger = logging.Logger(__name__)
54+
self.logger = logging.getLogger(__name__)
5555
self.logger.addHandler(RotatingFileHandler(self.filename))
5656

5757
self.logger.info(json.dumps(payload))
@@ -209,7 +209,7 @@ async def _run(self):
209209
try:
210210
await self.wait_for_first_response()
211211
except Exception as e:
212-
self.logger.error(str(e))
212+
self.logger.exception("First response failed")
213213
self.loop.stop()
214214
return
215215

tests/integrations/utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ def delete_aws_resource(
171171
resource_identifier: str,
172172
resource_type: str,
173173
error_name: str,
174-
get_callable: Callable = None,
174+
get_callable: Callable | None = None,
175175
):
176176
"""
177177
Generalized function to delete AWS resources.

tests/parametric/conftest.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ def apm_test_server(request, library_env, test_id):
7777
context.scenario.parametrized_tests_metadata[request.node.nodeid] = new_env
7878

7979
new_env.update(apm_test_server_image.env)
80-
yield dataclasses.replace(
80+
return dataclasses.replace(
8181
apm_test_server_image, container_name=f"{apm_test_server_image.container_name}-{test_id}", env=new_env
8282
)
8383

@@ -507,7 +507,7 @@ def docker() -> Optional[str]:
507507
return shutil.which("docker")
508508

509509

510-
@pytest.fixture()
510+
@pytest.fixture
511511
def docker_network(test_id: str) -> Generator[str, None, None]:
512512
network = scenarios.parametric.create_docker_network(test_id)
513513

tests/parametric/test_128_bit_traceids.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -608,7 +608,7 @@ def check_128_bit_trace_id(header_trace_id, span_trace_id, dd_p_tid):
608608

609609
def validate_dd_p_tid(dd_p_tid):
610610
"""Validate that dd_p_tid is well-formed."""
611-
assert not dd_p_tid is None
611+
assert dd_p_tid is not None
612612
assert len(dd_p_tid) == 16
613613
assert dd_p_tid != ZERO16
614614
assert dd_p_tid[8:16] == ZERO8

tests/parametric/test_dynamic_configuration.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -649,7 +649,7 @@ def test_trace_sampling_rules_override_rate(self, library_env, test_agent, test_
649649
assert span["meta"]["_dd.p.dm"] == "-3"
650650

651651
# Unset RC to ensure local settings
652-
set_and_wait_rc(test_agent, config_overrides={"tracing_sampling_rules": None, "tracing_sampling_rules": None})
652+
set_and_wait_rc(test_agent, config_overrides={"tracing_sampling_rules": None})
653653
trace = get_sampled_trace(test_library, test_agent, service="other_service", name="op_name")
654654
assert_sampling_rate(trace, DEFAULT_SAMPLE_RATE)
655655

tests/parametric/test_library_tracestats.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from typing import Optional
55
from typing import List
66

7-
import numpy
7+
import numpy as np
88
import msgpack
99
import pytest
1010

@@ -385,11 +385,11 @@ def test_relative_error_TS008(self, library_env, test_agent, test_library):
385385
assert web_stats["Hits"] == 10
386386

387387
# Validate the sketches
388-
np_duration = numpy.array(durations)
388+
np_duration = np.array(durations)
389389
assert web_stats["Duration"] == sum(durations), "Stats duration should match the span duration exactly"
390390
for quantile in (0.5, 0.75, 0.95, 0.99, 1):
391391
assert web_stats["OkSummary"].get_quantile_value(quantile) == pytest.approx(
392-
numpy.quantile(np_duration, quantile),
392+
np.quantile(np_duration, quantile),
393393
rel=0.01,
394394
), "Quantile mismatch for quantile %r" % quantile
395395

tests/parametric/test_sampling_span_tags.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
UNSET = -420
1515

1616

17-
class AnyRatio(object):
17+
class AnyRatio:
1818
def __eq__(self, other):
1919
return 0 <= other <= 1
2020

tests/parametric/test_trace_sampling.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,6 @@ def test_trace_kept_in_spite_trace_sampling_rule(self, test_agent, test_library)
9191
with test_library.dd_start_span(name="web.request", service="webserver") as s1:
9292
s1.set_metric("sampling.priority", 2)
9393
s1.set_meta("resource.name", "drop-me")
94-
pass
9594
span = find_only_span(test_agent.wait_for_num_traces(1))
9695

9796
assert span["metrics"].get(SAMPLING_PRIORITY_KEY) == 2

tests/perfs/process.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from os import environ
55

66

7-
LOG_FOLDER = environ["LOG_FOLDER"] if "LOG_FOLDER" in environ else "logs"
7+
LOG_FOLDER = environ.get("LOG_FOLDER", "logs")
88
LIBS = ("golang", "dotnet", "java", "nodejs", "php", "ruby")
99

1010

tests/remote_config/test_remote_configuration.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ def rc_check_request(data, expected, caching):
159159
raise ValidationError(f"{file} should not be in cached_target_files", extra_info=content)
160160
except Exception as e:
161161
e.args += (expected.get("test_description", "No description"),)
162-
raise e
162+
raise
163163

164164

165165
@rfc("https://docs.google.com/document/d/1u_G7TOr8wJX0dOM_zUDKuRJgxoJU_hVTd5SeaMucQUs/edit#heading=h.octuyiil30ph")

tests/stats/test_stats.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
- Must have `is_trace_root` on trace root
1111
- Must set peer tags
1212
- Must have span_kind
13-
13+
1414
Config:
1515
- apm_config.peer_tags_aggregation (we should see peer service tags and aggregation by them, note only works on client or producer kind)
1616
- apm_config.compute_stats_by_span_kind (span_kind will be set and we will calc stats on these spans even when not "top level")

tests/test_config_consistency.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -496,7 +496,6 @@ def test_log_injection_enabled(self):
496496
required_fields = ["trace_id", "span_id", "service", "version", "env"]
497497
for field in required_fields:
498498
assert field in dd, f"Missing field: {field}"
499-
return
500499

501500

502501
@rfc("https://docs.google.com/document/d/1kI-gTAKghfcwI7YzKhqRv2ExUstcHqADIWA4-TZ387o/edit#heading=h.8v16cioi7qxp")

tests/test_standard_tags.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -270,8 +270,8 @@ def _setup_without_attack(self):
270270
for header, value in (self.FORWARD_HEADERS | self.FORWARD_HEADERS_VENDOR).items():
271271
self.requests_without_attack[header] = weblog.get("/waf/", headers={header: value})
272272

273-
def _test_client_ip(self, forward_headers):
274-
for header, _ in forward_headers.items():
273+
def _test_client_ip(self, forward_headers: dict[str, str]):
274+
for header in forward_headers:
275275
request = self.requests_without_attack[header]
276276
meta = self._get_root_span_meta(request)
277277
assert "http.client_ip" in meta, f"Missing http.client_ip for {header}"

tests/test_the_test/test_scrubber.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
@scenarios.test_the_test
3737
def test_log_scrubber():
3838
cmd = ["./run.sh", "MOCK_THE_TEST", FILENAME]
39-
subprocess.run(cmd, env=scrubbed_names | os.environ, text=True, capture_output=True)
39+
subprocess.run(cmd, env=scrubbed_names | os.environ, text=True, capture_output=True, check=False)
4040

4141
redacted_count = 0
4242

@@ -51,7 +51,7 @@ def test_log_scrubber():
5151
for secret in scrubbed_names.values():
5252
assert secret not in data, f"{secret} found in {file_path}"
5353

54-
# extra portection to make sure we redacted all secrets
54+
# extra protection to make sure we redacted all secrets
5555
assert redacted_count != 0, "No secrets were redacted"
5656

5757

0 commit comments

Comments
 (0)