Skip to content

Commit 895b39b

Browse files
committed
Ruff: Add and fix RUF015
1 parent e0de953 commit 895b39b

File tree

15 files changed

+63
-48
lines changed

15 files changed

+63
-48
lines changed

dojo/reports/widgets.py

Lines changed: 30 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
)
2020
from dojo.forms import CustomReportOptionsForm
2121
from dojo.models import Endpoint, Finding
22-
from dojo.utils import get_page_items, get_system_setting, get_words_for_field
22+
from dojo.utils import first_elem, get_page_items, get_system_setting, get_words_for_field
2323

2424
"""
2525
Widgets are content sections that can be included on reports. The report builder will allow any number of widgets
@@ -369,10 +369,12 @@ def report_widget_factory(json_data=None, request=None, user=None, finding_notes
369369
widgets = json.loads(json_data)
370370

371371
for idx, widget in enumerate(widgets):
372-
if list(widget.keys())[0] == "page-break":
373-
selected_widgets[list(widget.keys())[0] + "-" + str(idx)] = PageBreak()
372+
first_widget_keys = first_elem(widget.keys())
374373

375-
if list(widget.keys())[0] == "endpoint-list":
374+
if first_widget_keys == "page-break":
375+
selected_widgets[first_widget_keys + "-" + str(idx)] = PageBreak()
376+
377+
if first_widget_keys == "endpoint-list":
376378
endpoints = Endpoint.objects.filter(finding__active=True,
377379
finding__false_p=False,
378380
finding__duplicate=False,
@@ -384,7 +386,7 @@ def report_widget_factory(json_data=None, request=None, user=None, finding_notes
384386
endpoints = endpoints.distinct()
385387

386388
d = QueryDict(mutable=True)
387-
for item in widget.get(list(widget.keys())[0]):
389+
for item in widget.get(first_widget_keys):
388390
if item["name"] in d:
389391
d.appendlist(item["name"], item["value"])
390392
else:
@@ -398,12 +400,12 @@ def report_widget_factory(json_data=None, request=None, user=None, finding_notes
398400
endpoints = EndpointList(request=request, endpoints=endpoints, finding_notes=finding_notes,
399401
finding_images=finding_images, host=host, user_id=user_id)
400402

401-
selected_widgets[list(widget.keys())[0] + "-" + str(idx)] = endpoints
403+
selected_widgets[first_widget_keys + "-" + str(idx)] = endpoints
402404

403-
if list(widget.keys())[0] == "finding-list":
405+
if first_widget_keys == "finding-list":
404406
findings = Finding.objects.all()
405407
d = QueryDict(mutable=True)
406-
for item in widget.get(list(widget.keys())[0]):
408+
for item in widget.get(first_widget_keys):
407409
if item["name"] in d:
408410
d.appendlist(item["name"], item["value"])
409411
else:
@@ -412,47 +414,47 @@ def report_widget_factory(json_data=None, request=None, user=None, finding_notes
412414
filter_class = ReportFindingFilterWithoutObjectLookups if filter_string_matching else ReportFindingFilter
413415
findings = filter_class(d, queryset=findings)
414416
user_id = user.id if user is not None else None
415-
selected_widgets[list(widget.keys())[0] + "-" + str(idx)] = FindingList(request=request, findings=findings,
417+
selected_widgets[first_widget_keys + "-" + str(idx)] = FindingList(request=request, findings=findings,
416418
finding_notes=finding_notes,
417419
finding_images=finding_images,
418420
host=host, user_id=user_id)
419421

420-
if list(widget.keys())[0] == "custom-content":
422+
if first_widget_keys == "custom-content":
421423
wysiwyg_content = WYSIWYGContent(request=request)
422424
wysiwyg_content.heading = \
423-
next((item for item in widget.get(list(widget.keys())[0]) if item["name"] == "heading"), None)["value"]
425+
next((item for item in widget.get(first_widget_keys) if item["name"] == "heading"), None)["value"]
424426
wysiwyg_content.content = \
425-
next((item for item in widget.get(list(widget.keys())[0]) if item["name"] == "hidden_content"), None)["value"]
427+
next((item for item in widget.get(first_widget_keys) if item["name"] == "hidden_content"), None)["value"]
426428
wysiwyg_content.page_break_after = \
427-
next((item for item in widget.get(list(widget.keys())[0]) if item["name"] == "page_break_after"),
429+
next((item for item in widget.get(first_widget_keys) if item["name"] == "page_break_after"),
428430
{"value": False})["value"]
429-
selected_widgets[list(widget.keys())[0] + "-" + str(idx)] = wysiwyg_content
430-
if list(widget.keys())[0] == "report-options":
431+
selected_widgets[first_widget_keys + "-" + str(idx)] = wysiwyg_content
432+
if first_widget_keys == "report-options":
431433
options = ReportOptions(request=request)
432434
options.include_finding_notes = \
433-
next((item for item in widget.get(list(widget.keys())[0]) if item["name"] == "include_finding_notes"), None)[
435+
next((item for item in widget.get(first_widget_keys) if item["name"] == "include_finding_notes"), None)[
434436
"value"]
435437
options.include_finding_images = \
436-
next((item for item in widget.get(list(widget.keys())[0]) if item["name"] == "include_finding_images"), None)[
438+
next((item for item in widget.get(first_widget_keys) if item["name"] == "include_finding_images"), None)[
437439
"value"]
438440
options.report_type = \
439-
next((item for item in widget.get(list(widget.keys())[0]) if item["name"] == "report_type"), None)["value"]
441+
next((item for item in widget.get(first_widget_keys) if item["name"] == "report_type"), None)["value"]
440442
options.report_name = \
441-
next((item for item in widget.get(list(widget.keys())[0]) if item["name"] == "report_name"), None)["value"]
442-
selected_widgets[list(widget.keys())[0]] = options
443-
if list(widget.keys())[0] == "table-of-contents":
443+
next((item for item in widget.get(first_widget_keys) if item["name"] == "report_name"), None)["value"]
444+
selected_widgets[first_widget_keys] = options
445+
if first_widget_keys == "table-of-contents":
444446
toc = TableOfContents(request=request)
445-
toc.heading = next((item for item in widget.get(list(widget.keys())[0]) if item["name"] == "heading"), None)[
447+
toc.heading = next((item for item in widget.get(first_widget_keys) if item["name"] == "heading"), None)[
446448
"value"]
447-
selected_widgets[list(widget.keys())[0]] = toc
448-
if list(widget.keys())[0] == "cover-page":
449+
selected_widgets[first_widget_keys] = toc
450+
if first_widget_keys == "cover-page":
449451
cover_page = CoverPage(request=request)
450-
cover_page.heading = next((item for item in widget.get(list(widget.keys())[0]) if item["name"] == "heading"), None)[
452+
cover_page.heading = next((item for item in widget.get(first_widget_keys) if item["name"] == "heading"), None)[
451453
"value"]
452454
cover_page.sub_heading = \
453-
next((item for item in widget.get(list(widget.keys())[0]) if item["name"] == "sub_heading"), None)["value"]
455+
next((item for item in widget.get(first_widget_keys) if item["name"] == "sub_heading"), None)["value"]
454456
cover_page.meta_info = \
455-
next((item for item in widget.get(list(widget.keys())[0]) if item["name"] == "meta_info"), None)["value"]
456-
selected_widgets[list(widget.keys())[0]] = cover_page
457+
next((item for item in widget.get(first_widget_keys) if item["name"] == "meta_info"), None)["value"]
458+
selected_widgets[first_widget_keys] = cover_page
457459

458460
return selected_widgets

dojo/tools/api_cobalt/api_client.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import requests
22
from django.conf import settings
33

4+
from dojo.utils import first_elem
5+
46

57
class CobaltAPI:
68

@@ -90,7 +92,7 @@ def test_connection(self):
9092
orgs = filter(
9193
lambda org: org["resource"]["token"] == self.org_token, data,
9294
)
93-
org = list(orgs)[0]
95+
org = first_elem(orgs)
9496
org_name = org["resource"]["name"]
9597
return f'You have access to the "{org_name}" organization'
9698
msg = (

dojo/tools/burp_enterprise/parser.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from lxml import etree, html
55

66
from dojo.models import Endpoint, Finding
7+
from dojo.utils import first_elem
78

89
logger = logging.getLogger(__name__)
910

@@ -117,7 +118,7 @@ def _get_content(self, container: etree.Element):
117118
if stripped_text is not None:
118119
value += stripped_text + "\n"
119120
elif stripped_text.isspace():
120-
value = list(elem.itertext())[0]
121+
value = first_elem(elem.itertext())
121122
elif elem.tag == "div" or elem.tag == "span":
122123
value = elem.text_content().strip().replace("\n", "") + "\n"
123124
else:

dojo/tools/harbor_vulnerability/parser.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import json
33

44
from dojo.models import Finding
5+
from dojo.utils import first_elem
56

67

78
class HarborVulnerabilityParser:
@@ -32,7 +33,7 @@ def get_findings(self, filename, test):
3233
vulnerability = data["vulnerabilities"]
3334
# To be compatible with update in version
3435
with contextlib.suppress(KeyError, StopIteration, TypeError):
35-
vulnerability = data[next(iter(data.keys()))]["vulnerabilities"]
36+
vulnerability = data[first_elem(data.keys())]["vulnerabilities"]
3637

3738
# Early exit if empty
3839
if "vulnerability" not in locals() or vulnerability is None:

dojo/tools/sarif/parser.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
from dojo.models import Finding
1010
from dojo.tools.parser_test import ParserTest
11+
from dojo.utils import first_elem
1112

1213
logger = logging.getLogger(__name__)
1314

@@ -465,7 +466,7 @@ def get_items_from_result(result, rules, artifacts, run_date):
465466
# compare it
466467
if result.get("fingerprints"):
467468
hashes = get_fingerprints_hashes(result["fingerprints"])
468-
first_item = next(iter(hashes.items()))
469+
first_item = first_elem(hashes.items())
469470
finding.unique_id_from_tool = first_item[1]["value"]
470471
elif result.get("partialFingerprints"):
471472
# for this one we keep an order to have id that could be compared

dojo/tools/sonarqube/soprasteria_html.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import logging
22

33
from dojo.tools.sonarqube.soprasteria_helper import SonarQubeSoprasteriaHelper
4+
from dojo.utils import first_elem
45

56
logger = logging.getLogger(__name__)
67

@@ -23,13 +24,13 @@ def get_items(self, tree, test, mode):
2324
rulesDic = {}
2425
for rule in rules_table:
2526
rule_properties = list(rule.iter("td"))
26-
rule_name = list(rule_properties[0].iter("a"))[0].text.strip()
27-
rule_details = list(rule_properties[1].iter("details"))[0]
27+
rule_name = first_elem(rule_properties[0].iter("a")).text.strip()
28+
rule_details = first_elem(rule_properties[1].iter("details"))
2829
rulesDic[rule_name] = rule_details
2930

3031
for vuln in vulnerabilities_table:
3132
vuln_properties = list(vuln.iter("td"))
32-
rule_key = list(vuln_properties[0].iter("a"))[0].text
33+
rule_key = first_elem(vuln_properties[0].iter("a")).text
3334
vuln_rule_name = rule_key and rule_key.strip()
3435
vuln_severity = SonarQubeSoprasteriaHelper().convert_sonar_severity(
3536
vuln_properties[1].text and vuln_properties[1].text.strip(),

dojo/tools/trufflehog/parser.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import json
33

44
from dojo.models import Finding
5+
from dojo.utils import first_elem
56

67

78
class TruffleHogParser:
@@ -112,7 +113,7 @@ def get_findings_v3(self, data, test):
112113
source = {}
113114
source_data = {}
114115
if metadata:
115-
source = list(metadata.keys())[0]
116+
source = first_elem(metadata.keys())
116117
source_data = metadata.get(source)
117118

118119
file = source_data.get("file", "")

dojo/tools/veracode_sca/parser.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from django.utils import timezone
1010

1111
from dojo.models import Finding
12+
from dojo.utils import first_elem
1213

1314

1415
class VeracodeScaParser:
@@ -159,7 +160,7 @@ def get_findings_csv(self, file, test):
159160
issueId = row.get("Issue ID", None)
160161
if not issueId:
161162
# Workaround for possible encoding issue
162-
issueId = list(row.values())[0]
163+
issueId = first_elem(row.values())
163164
library = row.get("Library", None)
164165
if row.get("Package manager") == "MAVEN" and row.get(
165166
"Coordinate 2",

dojo/utils.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ def match_finding_to_existing_findings(finding, product=None, engagement=None, t
173173

174174
deduplicationLogger.debug(
175175
"Matching finding %i:%s to existing findings in %s %s using %s as deduplication algorithm.",
176-
finding.id, finding.title, custom_filter_type, list(custom_filter.values())[0], deduplication_algorithm,
176+
finding.id, finding.title, custom_filter_type, first_elem(custom_filter.values()), deduplication_algorithm,
177177
)
178178

179179
if deduplication_algorithm == "hash_code":
@@ -2709,3 +2709,9 @@ def generate_file_response_from_file_path(
27092709
response["Content-Disposition"] = f'attachment; filename="{full_file_name}"'
27102710
response["Content-Length"] = file_size
27112711
return response
2712+
2713+
2714+
def first_elem(x):
2715+
# This function is workaround for using of `list(...)[0]`.
2716+
# RUF015 recommends to use `next(iter(x))` but it is harder for reading in regular code
2717+
return next(iter(x))

ruff.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,6 @@ ignore = [
9494
"SIM115",
9595
"SIM117",
9696
"RUF012",
97-
"RUF015",
9897
"D205",
9998
"D211", # `one-blank-line-before-class` (D203) and `no-blank-line-before-class` (D211) are incompatible.
10099
"D212", # `multi-line-summary-first-line` (D212) and `multi-line-summary-second-line` (D213) are incompatible.

tests/Import_scanner_test.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
from selenium.webdriver.common.by import By
1414
from selenium.webdriver.support.ui import Select
1515

16+
from dojo.utils import first_elem
17+
1618
dir_path = Path(os.path.realpath(__file__)).parent
1719

1820
logger = logging.getLogger(__name__)
@@ -171,7 +173,7 @@ def test_engagement_import_scan_result(self):
171173
found_matches[index] = matches[0]
172174

173175
if len(found_matches) == 1:
174-
index = list(found_matches.keys())[0]
176+
index = first_elem(found_matches.keys())
175177
scan_map[test] = options_text[index]
176178
elif len(found_matches) > 1:
177179
index = list(found_matches.values()).index(temp_test)

unittests/tools/test_blackduck_parser.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ def test_blackduck_csv_parser_has_many_findings(self):
2222
parser = BlackduckParser()
2323
findings = parser.get_findings(testfile, Test())
2424
self.assertEqual(24, len(findings))
25-
findings = list(findings)
2625
self.assertEqual(1, len(findings[10].unsaved_vulnerability_ids))
2726
self.assertEqual("CVE-2007-3386", findings[10].unsaved_vulnerability_ids[0])
2827
self.assertEqual(findings[4].component_name, "Apache Tomcat")
@@ -34,7 +33,6 @@ def test_blackduck_csv_parser_new_format_has_many_findings(self):
3433
testfile = get_unit_tests_scans_path("blackduck") / "many_vulns_new_format.csv"
3534
parser = BlackduckParser()
3635
findings = parser.get_findings(testfile, Test())
37-
findings = list(findings)
3836
self.assertEqual(9, len(findings))
3937
self.assertEqual(findings[0].component_name, "kryo")
4038
self.assertEqual(findings[2].component_name, "jackson-databind")

unittests/tools/test_hadolint_parser.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ def test_parse_file_with_one_dockerfile(self):
1111
findings = parser.get_findings(testfile, Test())
1212
testfile.close()
1313
self.assertEqual(4, len(findings))
14-
finding = list(findings)[0]
14+
finding = findings[0]
1515
self.assertEqual(finding.line, 9)
1616
self.assertEqual(finding.file_path, "django-DefectDojo\\Dockerfile.django")
1717

unittests/tools/test_intsights_parser.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ def test_intsights_parser_with_one_critical_vuln_has_one_findings_json(
1212

1313
self.assertEqual(1, len(findings))
1414

15-
finding = list(findings)[0]
15+
finding = findings[0]
1616

1717
self.assertEqual(
1818
"5c80dbf83b4a3900078b6be6",
@@ -32,7 +32,7 @@ def test_intsights_parser_with_one_critical_vuln_has_one_findings_csv(
3232
findings = parser.get_findings(testfile, Test())
3333
self.assertEqual(1, len(findings))
3434

35-
finding = list(findings)[0]
35+
finding = findings[0]
3636

3737
self.assertEqual(
3838
"mn7xy83finmmth4ja363rci9",

unittests/tools/test_mend_parser.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ def test_parse_file_with_one_vuln_has_one_findings(self):
1616
parser = MendParser()
1717
findings = parser.get_findings(testfile, Test())
1818
self.assertEqual(1, len(findings))
19-
finding = list(findings)[0]
19+
finding = findings[0]
2020
self.assertEqual(1, len(finding.unsaved_vulnerability_ids))
2121
self.assertEqual("CVE-2019-9658", finding.unsaved_vulnerability_ids[0])
2222
self.assertEqual("CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N", finding.cvssv3)
@@ -41,7 +41,7 @@ def test_parse_file_with_one_sca_vuln_finding(self):
4141
parser = MendParser()
4242
findings = parser.get_findings(testfile, Test())
4343
self.assertEqual(1, len(findings))
44-
finding = list(findings)[0]
44+
finding = findings[0]
4545
self.assertEqual("**Locations Found**: D:\\MendRepo\\test-product\\test-project\\test-project-subcomponent\\path\\to\\the\\Java\\commons-codec-1.6_donotuse.jar", finding.steps_to_reproduce)
4646
self.assertEqual("WS-2019-0379 | commons-codec-1.6.jar", finding.title)
4747

@@ -56,7 +56,7 @@ def test_parse_file_with_one_vuln_has_one_findings_platform(self):
5656
parser = MendParser()
5757
findings = parser.get_findings(testfile, Test())
5858
self.assertEqual(1, len(findings))
59-
finding = list(findings)[0]
59+
finding = findings[0]
6060
self.assertEqual(1, len(finding.unsaved_vulnerability_ids))
6161
self.assertEqual("CVE-2024-51744", finding.unsaved_vulnerability_ids[0])
6262
self.assertEqual("CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:N/A:N", finding.cvssv3)

0 commit comments

Comments
 (0)