Coverage for src/debputy/lsp/lsp_debian_control_reference_data.py: 59%

335 statements  

« prev     ^ index     » next       coverage.py v7.2.7, created at 2024-04-07 12:14 +0200

1import dataclasses 

2import functools 

3import itertools 

4import re 

5import sys 

6import textwrap 

7from abc import ABC 

8from enum import Enum, auto 

9from typing import ( 

10 FrozenSet, 

11 Optional, 

12 cast, 

13 Mapping, 

14 Iterable, 

15 List, 

16 Generic, 

17 TypeVar, 

18 Union, 

19 Callable, 

20 Tuple, 

21 Any, 

22) 

23 

24from debian.debian_support import DpkgArchTable 

25from lsprotocol.types import DiagnosticSeverity, Diagnostic, DiagnosticTag, Range 

26 

27from debputy.lsp.quickfixes import ( 

28 propose_correct_text_quick_fix, 

29 propose_remove_line_quick_fix, 

30) 

31from debputy.lsp.text_util import ( 

32 normalize_dctrl_field_name, 

33 LintCapablePositionCodec, 

34 detect_possible_typo, 

35 te_range_to_lsp, 

36) 

37from debputy.lsp.vendoring._deb822_repro.parsing import ( 

38 Deb822KeyValuePairElement, 

39 LIST_SPACE_SEPARATED_INTERPRETATION, 

40 Deb822ParagraphElement, 

41 Deb822FileElement, 

42 Interpretation, 

43 LIST_COMMA_SEPARATED_INTERPRETATION, 

44 ListInterpretation, 

45 _parsed_value_render_factory, 

46 Deb822ParsedValueElement, 

47 LIST_UPLOADERS_INTERPRETATION, 

48 _parse_whitespace_list_value, 

49) 

50from debputy.lsp.vendoring._deb822_repro.tokens import ( 

51 Deb822FieldNameToken, 

52 _value_line_tokenizer, 

53 Deb822ValueToken, 

54 Deb822Token, 

55 _RE_WHITESPACE_SEPARATED_WORD_LIST, 

56 Deb822SpaceSeparatorToken, 

57) 

58from debputy.util import PKGNAME_REGEX 

59 

60try: 

61 from debputy.lsp.vendoring._deb822_repro.locatable import ( 

62 Position as TEPosition, 

63 Range as TERange, 

64 START_POSITION, 

65 ) 

66except ImportError: 

67 pass 

68 

69 

70F = TypeVar("F", bound="Deb822KnownField") 

71S = TypeVar("S", bound="StanzaMetadata") 

72 

73 

74# FIXME: should go into python3-debian 

75_RE_COMMA = re.compile("([^,]*),([^,]*)") 

76 

77 

78@_value_line_tokenizer 

79def comma_or_space_split_tokenizer(v): 

80 # type: (str) -> Iterable[Deb822Token] 

81 assert "\n" not in v 

82 for match in _RE_WHITESPACE_SEPARATED_WORD_LIST.finditer(v): 

83 space_before, word, space_after = match.groups() 

84 if space_before: 

85 yield Deb822SpaceSeparatorToken(sys.intern(space_before)) 

86 if "," in word: 

87 for m in _RE_COMMA.finditer(word): 

88 word_before, word_after = m.groups() 

89 if word_before: 

90 yield Deb822ValueToken(word_before) 

91 # ... not quite a whitespace, but it is too much pain to make it a non-whitespace token. 

92 yield Deb822SpaceSeparatorToken(",") 

93 if word_after: 

94 yield Deb822ValueToken(word_after) 

95 else: 

96 yield Deb822ValueToken(word) 

97 if space_after: 

98 yield Deb822SpaceSeparatorToken(sys.intern(space_after)) 

99 

100 

101# FIXME: should go into python3-debian 

102LIST_COMMA_OR_SPACE_SEPARATED_INTERPRETATION = ListInterpretation( 

103 comma_or_space_split_tokenizer, 

104 _parse_whitespace_list_value, 

105 Deb822ParsedValueElement, 

106 Deb822SpaceSeparatorToken, 

107 Deb822SpaceSeparatorToken, 

108 _parsed_value_render_factory, 

109) 

110 

111CustomFieldCheck = Callable[ 

112 [ 

113 "F", 

114 Deb822KeyValuePairElement, 

115 "TERange", 

116 Deb822ParagraphElement, 

117 "TEPosition", 

118 "LintCapablePositionCodec", 

119 List[str], 

120 ], 

121 Iterable[Diagnostic], 

122] 

123 

124 

125ALL_SECTIONS_WITHOUT_COMPONENT = frozenset( 

126 [ 

127 "admin", 

128 "cli-mono", 

129 "comm", 

130 "database", 

131 "debian-installer", 

132 "debug", 

133 "devel", 

134 "doc", 

135 "editors", 

136 "education", 

137 "electronics", 

138 "embedded", 

139 "fonts", 

140 "games", 

141 "gnome", 

142 "gnu-r", 

143 "gnustep", 

144 "graphics", 

145 "hamradio", 

146 "haskell", 

147 "interpreters", 

148 "introspection", 

149 "java", 

150 "javascript", 

151 "kde", 

152 "kernel", 

153 "libdevel", 

154 "libs", 

155 "lisp", 

156 "localization", 

157 "mail", 

158 "math", 

159 "metapackages", 

160 "misc", 

161 "net", 

162 "news", 

163 "ocaml", 

164 "oldlibs", 

165 "otherosfs", 

166 "perl", 

167 "php", 

168 "python", 

169 "ruby", 

170 "rust", 

171 "science", 

172 "shells", 

173 "sound", 

174 "tasks", 

175 "tex", 

176 "text", 

177 "utils", 

178 "vcs", 

179 "video", 

180 "virtual", 

181 "web", 

182 "x11", 

183 "xfce", 

184 "zope", 

185 ] 

186) 

187 

188ALL_COMPONENTS = frozenset( 

189 [ 

190 "main", 

191 "restricted", # Ubuntu 

192 "non-free", 

193 "non-free-firmware", 

194 "contrib", 

195 ] 

196) 

197 

198 

199def _fields(*fields: F) -> Mapping[str, F]: 

200 return {normalize_dctrl_field_name(f.name.lower()): f for f in fields} 

201 

202 

203@dataclasses.dataclass(slots=True, frozen=True) 

204class Keyword: 

205 value: str 

206 hover_text: Optional[str] = None 

207 is_obsolete: bool = False 

208 replaced_by: Optional[str] = None 

209 

210 

211def _allowed_values(*values: Union[str, Keyword]) -> Mapping[str, Keyword]: 

212 as_keywords = [k if isinstance(k, Keyword) else Keyword(k) for k in values] 

213 as_mapping = {k.value: k for k in as_keywords if k.value} 

214 # Simple bug check 

215 assert len(as_keywords) == len(as_mapping) 

216 return as_mapping 

217 

218 

219ALL_SECTIONS = _allowed_values( 

220 *[ 

221 s if c is None else f"{c}/{s}" 

222 for c, s in itertools.product( 

223 itertools.chain(cast("Iterable[Optional[str]]", [None]), ALL_COMPONENTS), 

224 ALL_SECTIONS_WITHOUT_COMPONENT, 

225 ) 

226 ] 

227) 

228 

229ALL_PRIORITIES = _allowed_values( 

230 Keyword( 

231 "required", 

232 hover_text=textwrap.dedent( 

233 """\ 

234 The package is necessary for the proper functioning of the system (read: dpkg needs it). 

235 

236 Applicable if dpkg *needs* this package to function and it is not a library. 

237 

238 No two packages that both have a priority of *standard* or higher may conflict with 

239 each other. 

240 """ 

241 ), 

242 ), 

243 Keyword( 

244 "important", 

245 hover_text=textwrap.dedent( 

246 """\ 

247 The *important* packages are a bare minimum of commonly-expected and necessary tools. 

248 

249 Applicable if 99% of all users in the distribution needs this package and it is not a library. 

250 

251 No two packages that both have a priority of *standard* or higher may conflict with 

252 each other. 

253 """ 

254 ), 

255 ), 

256 Keyword( 

257 "standard", 

258 hover_text=textwrap.dedent( 

259 """\ 

260 These packages provide a reasonable small but not too limited character-mode system. This is 

261 what will be installed by default (by the debian-installer) if the user does not select anything 

262 else. This does not include many large applications. 

263 

264 Applicable if your distribution installer will install this package by default on a new system 

265 and it is not a library. 

266 

267 No two packages that both have a priority of *standard* or higher may conflict with 

268 each other. 

269 """ 

270 ), 

271 ), 

272 Keyword( 

273 "optional", 

274 hover_text="This is the default priority and used by the majority of all packages" 

275 " in the Debian archive", 

276 ), 

277 Keyword( 

278 "extra", 

279 is_obsolete=True, 

280 replaced_by="optional", 

281 hover_text="Obsolete alias of `optional`.", 

282 ), 

283) 

284 

285 

286def all_architectures_and_wildcards(arch2table) -> Iterable[Union[str, Keyword]]: 

287 wildcards = set() 

288 yield Keyword( 

289 "any", 

290 hover_text=textwrap.dedent( 

291 """\ 

292 The package is an architecture dependent package and need to be compiled for each and every 

293 architecture it. 

294 

295 The name `any` refers to the fact that this is an architecture *wildcard* matching 

296 *any machine architecture* supported by dpkg. 

297 """ 

298 ), 

299 ) 

300 yield Keyword( 

301 "all", 

302 hover_text=textwrap.dedent( 

303 """\ 

304 The package is an architecture independent package. This is typically fitting for packages containing 

305 only scripts, data or documentation. 

306 

307 This name `all` refers to the fact that the package can be used for *all* architectures at the same. 

308 Though note that it is still subject to the rules of the `Multi-Arch` field. 

309 """ 

310 ), 

311 ) 

312 for arch_name, quad_tuple in arch2table.items(): 

313 yield arch_name 

314 cpu_wc = "any-" + quad_tuple.cpu_name 

315 os_wc = quad_tuple.os_name + "-any" 

316 if cpu_wc not in wildcards: 

317 yield cpu_wc 

318 wildcards.add(cpu_wc) 

319 if os_wc not in wildcards: 

320 yield os_wc 

321 wildcards.add(os_wc) 

322 # Add the remaining wildcards 

323 

324 

325@functools.lru_cache 

326def dpkg_arch_and_wildcards() -> FrozenSet[str]: 

327 dpkg_arch_table = DpkgArchTable.load_arch_table() 

328 return frozenset(all_architectures_and_wildcards(dpkg_arch_table._arch2table)) 

329 

330 

331def _extract_first_value_and_position( 

332 kvpair: Deb822KeyValuePairElement, 

333 stanza_pos: "TEPosition", 

334 position_codec: "LintCapablePositionCodec", 

335 lines: List[str], 

336) -> Tuple[Optional[str], Optional[Range]]: 

337 kvpair_pos = kvpair.position_in_parent().relative_to(stanza_pos) 

338 value_element_pos = kvpair.value_element.position_in_parent().relative_to( 

339 kvpair_pos 

340 ) 

341 for value_ref in kvpair.interpret_as( 

342 LIST_SPACE_SEPARATED_INTERPRETATION 

343 ).iter_value_references(): 

344 v = value_ref.value 

345 section_value_loc = value_ref.locatable 

346 value_range_te = section_value_loc.range_in_parent().relative_to( 

347 value_element_pos 

348 ) 

349 value_range_server_units = te_range_to_lsp(value_range_te) 

350 value_range = position_codec.range_to_client_units( 

351 lines, value_range_server_units 

352 ) 

353 return v, value_range 

354 return None, None 

355 

356 

357def _dctrl_ma_field_validation( 

358 _known_field: "F", 

359 _kvpair: Deb822KeyValuePairElement, 

360 _field_range: "TERange", 

361 stanza: Deb822ParagraphElement, 

362 stanza_position: "TEPosition", 

363 position_codec: "LintCapablePositionCodec", 

364 lines: List[str], 

365) -> Iterable[Diagnostic]: 

366 ma_kvpair = stanza.get_kvpair_element("Multi-Arch", use_get=True) 

367 arch = stanza.get("Architecture", "any") 

368 if arch == "all" and ma_kvpair is not None: 

369 ma_value, ma_value_range = _extract_first_value_and_position( 

370 ma_kvpair, 

371 stanza_position, 

372 position_codec, 

373 lines, 

374 ) 

375 if ma_value == "same": 

376 yield Diagnostic( 

377 ma_value_range, 

378 "Multi-Arch: same is not valid for Architecture: all packages. Maybe you want foreign?", 

379 severity=DiagnosticSeverity.Error, 

380 source="debputy", 

381 ) 

382 

383 

384def _udeb_only_field_validation( 

385 known_field: "F", 

386 _kvpair: Deb822KeyValuePairElement, 

387 field_range_te: "TERange", 

388 stanza: Deb822ParagraphElement, 

389 _stanza_position: "TEPosition", 

390 position_codec: "LintCapablePositionCodec", 

391 lines: List[str], 

392) -> Iterable[Diagnostic]: 

393 package_type = stanza.get("Package-Type") 

394 if package_type != "udeb": 

395 field_range_server_units = te_range_to_lsp(field_range_te) 

396 field_range = position_codec.range_to_client_units( 

397 lines, 

398 field_range_server_units, 

399 ) 

400 yield Diagnostic( 

401 field_range, 

402 f"The {known_field.name} field is only applicable to udeb packages (`Package-Type: udeb`)", 

403 severity=DiagnosticSeverity.Warning, 

404 source="debputy", 

405 ) 

406 

407 

408def _arch_not_all_only_field_validation( 

409 known_field: "F", 

410 _kvpair: Deb822KeyValuePairElement, 

411 field_range_te: "TERange", 

412 stanza: Deb822ParagraphElement, 

413 _stanza_position: "TEPosition", 

414 position_codec: "LintCapablePositionCodec", 

415 lines: List[str], 

416) -> Iterable[Diagnostic]: 

417 architecture = stanza.get("Architecture") 

418 if architecture == "all": 

419 field_range_server_units = te_range_to_lsp(field_range_te) 

420 field_range = position_codec.range_to_client_units( 

421 lines, 

422 field_range_server_units, 

423 ) 

424 yield Diagnostic( 

425 field_range, 

426 f"The {known_field.name} field is not applicable to arch:all packages (`Architecture: all`)", 

427 severity=DiagnosticSeverity.Warning, 

428 source="debputy", 

429 ) 

430 

431 

432def _each_value_match_regex_validation( 

433 regex: re.Pattern, 

434 *, 

435 diagnostic_severity: DiagnosticSeverity = DiagnosticSeverity.Error, 

436) -> CustomFieldCheck: 

437 

438 def _validator( 

439 _known_field: "F", 

440 kvpair: Deb822KeyValuePairElement, 

441 field_range_te: "TERange", 

442 _stanza: Deb822ParagraphElement, 

443 _stanza_position: "TEPosition", 

444 position_codec: "LintCapablePositionCodec", 

445 lines: List[str], 

446 ) -> Iterable[Diagnostic]: 

447 

448 value_element_pos = kvpair.value_element.position_in_parent().relative_to( 

449 field_range_te.start_pos 

450 ) 

451 for value_ref in kvpair.interpret_as( 

452 LIST_SPACE_SEPARATED_INTERPRETATION 

453 ).iter_value_references(): 

454 v = value_ref.value 

455 m = regex.fullmatch(v) 

456 if m is not None: 456 ↛ 459line 456 didn't jump to line 459, because the condition on line 456 was never false

457 continue 

458 

459 section_value_loc = value_ref.locatable 

460 value_range_te = section_value_loc.range_in_parent().relative_to( 

461 value_element_pos 

462 ) 

463 value_range_server_units = te_range_to_lsp(value_range_te) 

464 value_range = position_codec.range_to_client_units( 

465 lines, value_range_server_units 

466 ) 

467 yield Diagnostic( 

468 value_range, 

469 f'The value "{v}" does not match the regex {regex.pattern}.', 

470 severity=diagnostic_severity, 

471 source="debputy", 

472 ) 

473 

474 return _validator 

475 

476 

477def _combined_custom_field_check(*checks: CustomFieldCheck) -> CustomFieldCheck: 

478 def _validator( 

479 known_field: "F", 

480 kvpair: Deb822KeyValuePairElement, 

481 field_range_te: "TERange", 

482 stanza: Deb822ParagraphElement, 

483 stanza_position: "TEPosition", 

484 position_codec: "LintCapablePositionCodec", 

485 lines: List[str], 

486 ) -> Iterable[Diagnostic]: 

487 for check in checks: 

488 yield from check( 

489 known_field, 

490 kvpair, 

491 field_range_te, 

492 stanza, 

493 stanza_position, 

494 position_codec, 

495 lines, 

496 ) 

497 

498 return _validator 

499 

500 

501class FieldValueClass(Enum): 

502 SINGLE_VALUE = auto(), LIST_SPACE_SEPARATED_INTERPRETATION 

503 SPACE_SEPARATED_LIST = auto(), LIST_SPACE_SEPARATED_INTERPRETATION 

504 BUILD_PROFILES_LIST = auto(), None # TODO 

505 COMMA_SEPARATED_LIST = auto(), LIST_COMMA_SEPARATED_INTERPRETATION 

506 COMMA_SEPARATED_EMAIL_LIST = auto(), LIST_UPLOADERS_INTERPRETATION 

507 COMMA_OR_SPACE_SEPARATED_LIST = auto(), LIST_COMMA_OR_SPACE_SEPARATED_INTERPRETATION 

508 FREE_TEXT_FIELD = auto(), None 

509 DEP5_FILE_LIST = auto(), None # TODO 

510 

511 def interpreter(self) -> Optional[Interpretation[Any]]: 

512 return self.value[1] 

513 

514 

515@dataclasses.dataclass(slots=True, frozen=True) 

516class Deb822KnownField: 

517 name: str 

518 field_value_class: FieldValueClass 

519 warn_if_default: bool = True 

520 replaced_by: Optional[str] = None 

521 deprecated_with_no_replacement: bool = False 

522 missing_field_severity: Optional[DiagnosticSeverity] = None 

523 default_value: Optional[str] = None 

524 known_values: Optional[Mapping[str, Keyword]] = None 

525 unknown_value_diagnostic_severity: Optional[DiagnosticSeverity] = ( 

526 DiagnosticSeverity.Error 

527 ) 

528 hover_text: Optional[str] = None 

529 spellcheck_value: bool = False 

530 is_stanza_name: bool = False 

531 is_single_value_field: bool = True 

532 custom_field_check: Optional[CustomFieldCheck] = None 

533 

534 def field_diagnostics( 

535 self, 

536 kvpair: Deb822KeyValuePairElement, 

537 stanza: Deb822ParagraphElement, 

538 stanza_position: "TEPosition", 

539 position_codec: "LintCapablePositionCodec", 

540 lines: List[str], 

541 *, 

542 field_name_typo_reported: bool = False, 

543 ) -> Iterable[Diagnostic]: 

544 field_name_token = kvpair.field_token 

545 field_range_te = kvpair.range_in_parent().relative_to(stanza_position) 

546 field_position_te = field_range_te.start_pos 

547 yield from self._diagnostics_for_field_name( 

548 field_name_token, 

549 field_position_te, 

550 field_name_typo_reported, 

551 position_codec, 

552 lines, 

553 ) 

554 if self.custom_field_check is not None: 

555 yield from self.custom_field_check( 

556 self, 

557 kvpair, 

558 field_range_te, 

559 stanza, 

560 stanza_position, 

561 position_codec, 

562 lines, 

563 ) 

564 if not self.spellcheck_value: 

565 yield from self._known_value_diagnostics( 

566 kvpair, field_position_te, position_codec, lines 

567 ) 

568 

569 def _diagnostics_for_field_name( 

570 self, 

571 token: Deb822FieldNameToken, 

572 token_position: "TEPosition", 

573 typo_detected: bool, 

574 position_codec: "LintCapablePositionCodec", 

575 lines: List[str], 

576 ) -> Iterable[Diagnostic]: 

577 field_name = token.text 

578 # Defeat the case-insensitivity from python-debian 

579 field_name_cased = str(field_name) 

580 token_range_server_units = te_range_to_lsp( 

581 TERange.from_position_and_size(token_position, token.size()) 

582 ) 

583 token_range = position_codec.range_to_client_units( 

584 lines, 

585 token_range_server_units, 

586 ) 

587 if self.deprecated_with_no_replacement: 587 ↛ 588line 587 didn't jump to line 588, because the condition on line 587 was never true

588 yield Diagnostic( 

589 token_range, 

590 f"{field_name_cased} is deprecated and no longer used", 

591 severity=DiagnosticSeverity.Warning, 

592 source="debputy", 

593 tags=[DiagnosticTag.Deprecated], 

594 data=propose_remove_line_quick_fix(), 

595 ) 

596 elif self.replaced_by is not None: 596 ↛ 597line 596 didn't jump to line 597, because the condition on line 596 was never true

597 yield Diagnostic( 

598 token_range, 

599 f"{field_name_cased} is a deprecated name for {self.replaced_by}", 

600 severity=DiagnosticSeverity.Warning, 

601 source="debputy", 

602 tags=[DiagnosticTag.Deprecated], 

603 data=propose_correct_text_quick_fix(self.replaced_by), 

604 ) 

605 

606 if not typo_detected and field_name_cased != self.name: 606 ↛ 607line 606 didn't jump to line 607, because the condition on line 606 was never true

607 yield Diagnostic( 

608 token_range, 

609 f"Non-canonical spelling of {self.name}", 

610 severity=DiagnosticSeverity.Information, 

611 source="debputy", 

612 data=propose_correct_text_quick_fix(self.name), 

613 ) 

614 

615 def _known_value_diagnostics( 

616 self, 

617 kvpair: Deb822KeyValuePairElement, 

618 field_position_te: "TEPosition", 

619 position_codec: "LintCapablePositionCodec", 

620 lines: List[str], 

621 ) -> Iterable[Diagnostic]: 

622 unknown_value_severity = self.unknown_value_diagnostic_severity 

623 allowed_values = self.known_values 

624 interpreter = self.field_value_class.interpreter() 

625 if not allowed_values or interpreter is None: 

626 return 

627 hint_text = None 

628 values = kvpair.interpret_as(interpreter) 

629 value_off = kvpair.value_element.position_in_parent().relative_to( 

630 field_position_te 

631 ) 

632 first_value = True 

633 for value_ref in values.iter_value_references(): 

634 value = value_ref.value 

635 if ( 635 ↛ 639line 635 didn't jump to line 639

636 not first_value 

637 and self.field_value_class == FieldValueClass.SINGLE_VALUE 

638 ): 

639 value_loc = value_ref.locatable 

640 value_position_te = value_loc.position_in_parent().relative_to( 

641 value_off 

642 ) 

643 value_range_in_server_units = te_range_to_lsp( 

644 TERange.from_position_and_size(value_position_te, value_loc.size()) 

645 ) 

646 value_range = position_codec.range_to_client_units( 

647 lines, 

648 value_range_in_server_units, 

649 ) 

650 yield Diagnostic( 

651 value_range, 

652 f"The field {self.name} can only have exactly one value.", 

653 severity=DiagnosticSeverity.Error, 

654 source="debputy", 

655 ) 

656 # TODO: Add quickfix if the value is also invalid 

657 continue 

658 first_value = False 

659 

660 known_value = self.known_values.get(value) 

661 if known_value is None: 

662 candidates = detect_possible_typo( 

663 value, 

664 self.known_values, 

665 ) 

666 if hint_text is None: 666 ↛ 672line 666 didn't jump to line 672, because the condition on line 666 was never false

667 if len(self.known_values) < 5: 667 ↛ 668line 667 didn't jump to line 668, because the condition on line 667 was never true

668 values = ", ".join(sorted(self.known_values)) 

669 hint_text = f" Known values for this field: {values}" 

670 else: 

671 hint_text = "" 

672 fix_data = None 

673 severity = unknown_value_severity 

674 fix_text = hint_text 

675 if candidates: 675 ↛ 676line 675 didn't jump to line 676, because the condition on line 675 was never true

676 match = candidates[0] 

677 fix_text = f' It is possible that the value is a typo of "{match}".{fix_text}' 

678 fix_data = [propose_correct_text_quick_fix(m) for m in candidates] 

679 elif severity is None: 679 ↛ 680line 679 didn't jump to line 680, because the condition on line 679 was never true

680 continue 

681 if severity is None: 681 ↛ 682line 681 didn't jump to line 682, because the condition on line 681 was never true

682 severity = DiagnosticSeverity.Warning 

683 message = fix_text 

684 else: 

685 message = f'The value "{value}" is not supported in {self.name}.{fix_text}' 

686 elif known_value.is_obsolete: 686 ↛ 687line 686 didn't jump to line 687, because the condition on line 686 was never true

687 replacement = known_value.replaced_by 

688 if replacement is not None: 

689 message = f'The value "{value}" has been replaced by {replacement}' 

690 severity = DiagnosticSeverity.Warning 

691 fix_data = [propose_correct_text_quick_fix(replacement)] 

692 else: 

693 message = ( 

694 f'The value "{value}" is obsolete without a single replacement' 

695 ) 

696 severity = DiagnosticSeverity.Warning 

697 fix_data = None 

698 else: 

699 # All good 

700 continue 

701 

702 value_loc = value_ref.locatable 

703 value_position_te = value_loc.position_in_parent().relative_to(value_off) 

704 value_range_in_server_units = te_range_to_lsp( 

705 TERange.from_position_and_size(value_position_te, value_loc.size()) 

706 ) 

707 value_range = position_codec.range_to_client_units( 

708 lines, 

709 value_range_in_server_units, 

710 ) 

711 yield Diagnostic( 

712 value_range, 

713 message, 

714 severity=severity, 

715 source="debputy", 

716 data=fix_data, 

717 ) 

718 

719 

720@dataclasses.dataclass(slots=True, frozen=True) 

721class DctrlKnownField(Deb822KnownField): 

722 inherits_from_source: bool = False 

723 

724 

725SOURCE_FIELDS = _fields( 

726 DctrlKnownField( 

727 "Source", 

728 FieldValueClass.SINGLE_VALUE, 

729 custom_field_check=_each_value_match_regex_validation(PKGNAME_REGEX), 

730 missing_field_severity=DiagnosticSeverity.Error, 

731 is_stanza_name=True, 

732 hover_text=textwrap.dedent( 

733 """\ 

734 Declares the name of the source package. 

735 

736 Note this must match the name in the first entry of `debian/changelog` file. 

737 """ 

738 ), 

739 ), 

740 DctrlKnownField( 

741 "Standards-Version", 

742 FieldValueClass.SINGLE_VALUE, 

743 missing_field_severity=DiagnosticSeverity.Error, 

744 hover_text=textwrap.dedent( 

745 """\ 

746 Declares the last semantic version of the Debian Policy this package as last checked against. 

747 

748 **Example**: 

749 ``` 

750 Standards-Version: 4.5.2 

751 ``` 

752 

753 Note that the last version part of the full Policy version (the **.X** in 4.5.2**.X**) is 

754 typically omitted as it is used solely for editorial changes to the policy (e.g. typo fixes). 

755 """ 

756 ), 

757 ), 

758 DctrlKnownField( 

759 "Section", 

760 FieldValueClass.SINGLE_VALUE, 

761 known_values=ALL_SECTIONS, 

762 unknown_value_diagnostic_severity=DiagnosticSeverity.Warning, 

763 hover_text=textwrap.dedent( 

764 """\ 

765 Define the default section for packages in this source package. 

766 

767 **Example**: 

768 ``` 

769 Section: devel 

770 ``` 

771 

772 Please see <https://packages.debian.org/unstable> for more details about the sections. 

773 """ 

774 ), 

775 ), 

776 DctrlKnownField( 

777 "Priority", 

778 FieldValueClass.SINGLE_VALUE, 

779 default_value="optional", 

780 warn_if_default=False, 

781 known_values=ALL_PRIORITIES, 

782 hover_text=textwrap.dedent( 

783 """\ 

784 Define the default priority for packages in this source package. 

785 

786 The priority field describes how important the package is for the functionality of the system. 

787 

788 **Example**: 

789 ``` 

790 Priority: optional 

791 ``` 

792 

793 Unless you know you need a different value, you should choose **optional** for your packages. 

794 """ 

795 ), 

796 ), 

797 DctrlKnownField( 

798 "Maintainer", 

799 FieldValueClass.SINGLE_VALUE, 

800 missing_field_severity=DiagnosticSeverity.Error, 

801 hover_text=textwrap.dedent( 

802 """\ 

803 The maintainer of the package. 

804 

805 **Example**: 

806 ``` 

807 Maintainer: Jane Contributor <jane@janes.email-provider.org> 

808 ``` 

809 

810 Note: If a person is listed in the Maintainer field, they should *not* be listed in Uploaders field. 

811 """ 

812 ), 

813 ), 

814 DctrlKnownField( 

815 "Uploaders", 

816 FieldValueClass.COMMA_SEPARATED_EMAIL_LIST, 

817 hover_text=textwrap.dedent( 

818 """\ 

819 Comma separated list of uploaders associated with the package. 

820 

821 **Example**: 

822 ``` 

823 Uploaders: 

824 John Doe <john@doe.org>, 

825 Lisbeth Worker <lis@worker.org>, 

826 ``` 

827 

828 Formally uploaders are considered co-maintainers for the package with the party listed in the 

829 **Maintainer** field being the primary maintainer. In practice, each maintainer or maintenance 

830 team can have their own ruleset about the difference between the **Maintainer** and the 

831 **Uploaders**. As an example, the Python packaging team has a different rule set for how to 

832 react to a package depending on whether the packaging team is the **Maintainer** or in the 

833 **Uploaders** field. 

834 

835 Note: If a person is listed in the Maintainer field, they should *not* be listed in Uploaders field. 

836 """ 

837 ), 

838 ), 

839 DctrlKnownField( 

840 "Vcs-Browser", 

841 FieldValueClass.SINGLE_VALUE, 

842 hover_text=textwrap.dedent( 

843 """\ 

844 URL to the Version control system repo used for the packaging. The URL should be usable with a 

845 browser *without* requiring any login. 

846 

847 This should be used together with one of the other **Vcs-** fields. 

848 """ 

849 ), 

850 ), 

851 DctrlKnownField( 

852 "Vcs-Git", 

853 FieldValueClass.SPACE_SEPARATED_LIST, 

854 hover_text=textwrap.dedent( 

855 """\ 

856 URL to the git repo used for the packaging. The URL should be usable with `git clone` 

857 *without* requiring any login. 

858 

859 This should be used together with the **Vcs-Browser** field provided there is a web UI for the repo. 

860 

861 Note it is possible to specify a branch via the `-b` option. 

862 

863 ``` 

864 Vcs-Git: https://salsa.debian.org/some/packaging-repo -b debian/unstable 

865 ``` 

866 """ 

867 ), 

868 ), 

869 DctrlKnownField( 

870 "Vcs-Svn", 

871 FieldValueClass.SPACE_SEPARATED_LIST, # TODO: Might be a single value 

872 hover_text=textwrap.dedent( 

873 """\ 

874 URL to the git repo used for the packaging. The URL should be usable with `svn checkout` 

875 *without* requiring any login. 

876 

877 This should be used together with the **Vcs-Browser** field provided there is a web UI for the repo. 

878 ``` 

879 """ 

880 ), 

881 ), 

882 DctrlKnownField( 

883 "Vcs-Arch", 

884 FieldValueClass.SPACE_SEPARATED_LIST, # TODO: Might be a single value 

885 hover_text=textwrap.dedent( 

886 """\ 

887 URL to the git repo used for the packaging. The URL should be usable for getting a copy of the 

888 sources *without* requiring any login. 

889 

890 This should be used together with the **Vcs-Browser** field provided there is a web UI for the repo. 

891 """ 

892 ), 

893 ), 

894 DctrlKnownField( 

895 "Vcs-Cvs", 

896 FieldValueClass.SPACE_SEPARATED_LIST, # TODO: Might be a single value 

897 hover_text=textwrap.dedent( 

898 """\ 

899 URL to the git repo used for the packaging. The URL should be usable for getting a copy of the 

900 sources *without* requiring any login. 

901 

902 This should be used together with the **Vcs-Browser** field provided there is a web UI for the repo. 

903 """ 

904 ), 

905 ), 

906 DctrlKnownField( 

907 "Vcs-Darcs", 

908 FieldValueClass.SPACE_SEPARATED_LIST, # TODO: Might be a single value 

909 hover_text=textwrap.dedent( 

910 """\ 

911 URL to the git repo used for the packaging. The URL should be usable for getting a copy of the 

912 sources *without* requiring any login. 

913 

914 This should be used together with the **Vcs-Browser** field provided there is a web UI for the repo. 

915 """ 

916 ), 

917 ), 

918 DctrlKnownField( 

919 "Vcs-Hg", 

920 FieldValueClass.SPACE_SEPARATED_LIST, # TODO: Might be a single value 

921 hover_text=textwrap.dedent( 

922 """\ 

923 URL to the git repo used for the packaging. The URL should be usable for getting a copy of the 

924 sources *without* requiring any login. 

925 

926 This should be used together with the **Vcs-Browser** field provided there is a web UI for the repo. 

927 """ 

928 ), 

929 ), 

930 DctrlKnownField( 

931 "Vcs-Mtn", 

932 FieldValueClass.SPACE_SEPARATED_LIST, # TODO: Might be a single value 

933 hover_text=textwrap.dedent( 

934 """\ 

935 URL to the git repo used for the packaging. The URL should be usable for getting a copy of the 

936 sources *without* requiring any login. 

937 

938 This should be used together with the **Vcs-Browser** field provided there is a web UI for the repo. 

939 """ 

940 ), 

941 ), 

942 DctrlKnownField( 

943 "DM-Upload-Allowed", 

944 FieldValueClass.SINGLE_VALUE, 

945 deprecated_with_no_replacement=True, 

946 default_value="no", 

947 known_values=_allowed_values("yes", "no"), 

948 hover_text=textwrap.dedent( 

949 """\ 

950 Obsolete field 

951 

952 It was used to enabling Debian Maintainers to upload the package without requiring a Debian Developer 

953 to sign the package. This mechanism has been replaced by a new authorization mechanism. 

954 

955 Please see <https://lists.debian.org/debian-devel-announce/2012/09/msg00008.html> for details about the 

956 replacement. 

957 ``` 

958 """ 

959 ), 

960 ), 

961 DctrlKnownField( 

962 "Build-Depends", 

963 FieldValueClass.COMMA_SEPARATED_LIST, 

964 hover_text=textwrap.dedent( 

965 """\ 

966 All minimum build-dependencies for this source package. Needed for any target including **clean**. 

967 """ 

968 ), 

969 ), 

970 DctrlKnownField( 

971 "Build-Depends-Arch", 

972 FieldValueClass.COMMA_SEPARATED_LIST, 

973 hover_text=textwrap.dedent( 

974 """\ 

975 Build-dependencies required for building the architecture dependent binary packages of this source 

976 package. 

977 

978 These build-dependencies must be satisfied when executing the **build-arch** and **binary-arch** 

979 targets either directly or indirectly in addition to those listed in **Build-Depends**. 

980 

981 Note that these dependencies are *not* available during **clean**. 

982 """ 

983 ), 

984 ), 

985 DctrlKnownField( 

986 "Build-Depends-Indep", 

987 FieldValueClass.COMMA_SEPARATED_LIST, 

988 hover_text=textwrap.dedent( 

989 """\ 

990 Build-dependencies required for building the architecture independent binary packages of this source 

991 package. 

992 

993 These build-dependencies must be satisfied when executing the **build-indep** and **binary-indep** 

994 targets either directly or indirectly in addition to those listed in **Build-Depends**. 

995 

996 Note that these dependencies are *not* available during **clean**. 

997 """ 

998 ), 

999 ), 

1000 DctrlKnownField( 

1001 "Build-Conflicts", 

1002 FieldValueClass.COMMA_SEPARATED_LIST, 

1003 hover_text=textwrap.dedent( 

1004 """\ 

1005 Packages that must **not** be installed during **any** part of the build, including the **clean** 

1006 target **clean**. 

1007 

1008 Where possible, it is often better to configure the build so that it does not react to the package 

1009 being present in the first place. Usually this is a question of using a `--without-foo` or 

1010 `--disable-foo` or such to the build configuration. 

1011 """ 

1012 ), 

1013 ), 

1014 DctrlKnownField( 

1015 "Build-Conflicts-Arch", 

1016 FieldValueClass.COMMA_SEPARATED_LIST, 

1017 hover_text=textwrap.dedent( 

1018 """\ 

1019 Packages that must **not** be installed during the **build-arch** or **binary-arch** targets. 

1020 This also applies when these targets are run implicitly such as via the **binary** target. 

1021 

1022 Where possible, it is often better to configure the build so that it does not react to the package 

1023 being present in the first place. Usually this is a question of using a `--without-foo` or 

1024 `--disable-foo` or such to the build configuration. 

1025 """ 

1026 ), 

1027 ), 

1028 DctrlKnownField( 

1029 "Build-Conflicts-Indep", 

1030 FieldValueClass.COMMA_SEPARATED_LIST, 

1031 hover_text=textwrap.dedent( 

1032 """\ 

1033 Packages that must **not** be installed during the **build-indep** or **binary-indep** targets. 

1034 This also applies when these targets are run implicitly such as via the **binary** target. 

1035 

1036 Where possible, it is often better to configure the build so that it does not react to the package 

1037 being present in the first place. Usually this is a question of using a `--without-foo` or 

1038 `--disable-foo` or such to the build configuration. 

1039 """ 

1040 ), 

1041 ), 

1042 DctrlKnownField( 

1043 "Testsuite", 

1044 FieldValueClass.SPACE_SEPARATED_LIST, 

1045 hover_text=textwrap.dedent( 

1046 """\ 

1047 Declares that this package provides or should run install time tests via `autopkgtest`. 

1048 

1049 This field can be used to request an automatically generated autopkgtests via the **autodep8** package. 

1050 Please refer to the documentation of the **autodep8** package for which values you can put into 

1051 this field and what kind of testsuite the keywords will provide. 

1052 

1053 Declaring this field in `debian/control` is only necessary when you want additional tests beyond 

1054 those in `debian/tests/control` as **dpkg** automatically records the package provided ones from 

1055 `debian/tests/control`. 

1056 """ 

1057 ), 

1058 ), 

1059 DctrlKnownField( 

1060 "Homepage", 

1061 FieldValueClass.SINGLE_VALUE, 

1062 hover_text=textwrap.dedent( 

1063 """\ 

1064 Link to the upstream homepage for this source package. 

1065 

1066 **Example**: 

1067 ``` 

1068 Homepage: https://www.janes-tools.org/frob-cleaner 

1069 ``` 

1070 """ 

1071 ), 

1072 ), 

1073 DctrlKnownField( 

1074 "Rules-Requires-Root", 

1075 FieldValueClass.SPACE_SEPARATED_LIST, 

1076 unknown_value_diagnostic_severity=None, 

1077 known_values=_allowed_values( 

1078 Keyword( 

1079 "no", 

1080 hover_text=textwrap.dedent( 

1081 """\ 

1082 The build process will not require root or fakeroot during any step. This enables 

1083 dpkg-buildpackage, debhelper or/and `debputy` to perform several optimizations during the build. 

1084 

1085 This is the default with dpkg-build-api at version 1 or later. 

1086 """ 

1087 ), 

1088 ), 

1089 Keyword( 

1090 "binary-targets", 

1091 hover_text=textwrap.dedent( 

1092 """\ 

1093 The build process assumes that dpkg-buildpackage will run the relevant binary 

1094 target with root or fakeroot. This was the historical default behaviour. 

1095 

1096 This is the default with dpkg-build-api at version 0. 

1097 """ 

1098 ), 

1099 ), 

1100 ), 

1101 hover_text=textwrap.dedent( 

1102 """\ 

1103 Declare if and when the package build assumes it is run as root or fakeroot. 

1104 

1105 Most packages do not need to run as root or fakeroot and the legacy behaviour comes with a 

1106 performance cost. This field can be used to explicitly declare that the legacy behaviour is 

1107 unnecessary. 

1108 

1109 **Example**: 

1110 ``` 

1111 Rules-Requires-Root: no 

1112 ``` 

1113 

1114 Setting this field to `no` *can* cause the package to stop building if it requires root. 

1115 Depending on the situation, it might require some trivial or some complicated changes to fix that. 

1116 If it breaks and you cannot figure out how to fix it, then reset the field to `binary-targets` 

1117 and move on until you have time to fix it. 

1118 

1119 The default value for this field depends on the `dpkg-build-api` version. If the package 

1120 ` Build-Depends` on `dpkg-build-api (>= 1)` or later, the default is `no`. Otherwise, 

1121 the default is `binary-target` 

1122 

1123 Note it is **not** possible to require running the package as "true root". 

1124 """ 

1125 ), 

1126 ), 

1127 DctrlKnownField( 

1128 "Bugs", 

1129 FieldValueClass.SINGLE_VALUE, 

1130 hover_text=textwrap.dedent( 

1131 """\ 

1132 Provide a custom bug tracker URL 

1133 

1134 This field is *not* used by packages uploaded to Debian or most derivatives as the distro tooling 

1135 has a default bugtracker built-in. It is primarily useful for third-party provided packages such 

1136 that bug reporting tooling can redirect the user to their bug tracker. 

1137 """ 

1138 ), 

1139 ), 

1140 DctrlKnownField( 

1141 "Origin", 

1142 FieldValueClass.SINGLE_VALUE, 

1143 hover_text=textwrap.dedent( 

1144 """\ 

1145 Declare the origin of the package. 

1146 

1147 This field is *not* used by packages uploaded to Debian or most derivatives as the origin would 

1148 be the distribution. It is primarily useful for third-party provided packages as some tools will 

1149 detect this field. 

1150 """ 

1151 ), 

1152 ), 

1153 DctrlKnownField( 

1154 "X-Python-Version", 

1155 FieldValueClass.COMMA_SEPARATED_LIST, 

1156 replaced_by="X-Python3-Version", 

1157 hover_text=textwrap.dedent( 

1158 """\ 

1159 Obsolete field for declaring the supported Python2 versions 

1160 

1161 Since Python2 is no longer supported, this field is now redundant. For Python3, the field is 

1162 called **X-Python3-Version**. 

1163 """ 

1164 ), 

1165 ), 

1166 DctrlKnownField( 

1167 "X-Python3-Version", 

1168 FieldValueClass.COMMA_SEPARATED_LIST, 

1169 hover_text=textwrap.dedent( 

1170 # Too lazy to provide a better description 

1171 """\ 

1172 For declaring the supported Python3 versions 

1173 

1174 This is used by the tools from `dh-python` package. Please see the documentation of that package 

1175 for when and how to use it. 

1176 """ 

1177 ), 

1178 ), 

1179 DctrlKnownField( 

1180 "XS-Autobuild", 

1181 FieldValueClass.SINGLE_VALUE, 

1182 known_values=_allowed_values("yes"), 

1183 hover_text=textwrap.dedent( 

1184 """\ 

1185 Used for non-free packages to denote that they may be auto-build on the Debian build infrastructure 

1186 

1187 Note that adding this field **must** be combined with following the instructions at 

1188 <https://www.debian.org/doc/manuals/developers-reference/pkgs.html#non-free-buildd> 

1189 """ 

1190 ), 

1191 ), 

1192 DctrlKnownField( 

1193 "Description", 

1194 FieldValueClass.FREE_TEXT_FIELD, 

1195 spellcheck_value=True, 

1196 hover_text=textwrap.dedent( 

1197 """\ 

1198 This field contains a human-readable description of the package. However, it is not used directly. 

1199 

1200 Binary packages can reference parts of it via the `${source:Synopsis}` and the 

1201 `${source:Extended-Description}` substvars. Without any of these substvars, the `Description` field 

1202 of the `Source` stanza remains unused. 

1203 

1204 The first line immediately after the field is called the *Synopsis* and is a short "noun-phrase" 

1205 intended to provide a one-line summary of a package. The lines after the **Synopsis** is known 

1206 as the **Extended Description** and is intended as a longer summary of a package. 

1207 

1208 **Example**: 

1209 ``` 

1210 Description: documentation generator for Python projects 

1211 Sphinx is a tool for producing documentation for Python projects, using 

1212 reStructuredText as markup language. 

1213 . 

1214 Sphinx features: 

1215 * HTML, CHM, LaTeX output, 

1216 * Cross-referencing source code, 

1217 * Automatic indices, 

1218 * Code highlighting, using Pygments, 

1219 * Extensibility. Existing extensions: 

1220 - automatic testing of code snippets, 

1221 - including docstrings from Python modules. 

1222 . 

1223 Build-depend on sphinx if your package uses /usr/bin/sphinx-* 

1224 executables. Build-depend on python3-sphinx if your package uses 

1225 the Python API (for instance by calling python3 -m sphinx). 

1226 ``` 

1227 

1228 The **Synopsis** is usually displayed in cases where there is limited space such as when reviewing 

1229 the search results from `apt search foo`. It is often a good idea to imagine that the **Synopsis** 

1230 part is inserted into a sentence like "The package provides {{Synopsis-goes-here}}". The 

1231 **Extended Description** is a standalone description that should describe what the package does and 

1232 how it relates to the rest of the system (in terms of, for example, which subsystem it is which part of). 

1233 Please see <https://www.debian.org/doc/debian-policy/ch-controlfields.html#description> for more details 

1234 about the description field and suggestions for how to write it. 

1235 """ 

1236 ), 

1237 ), 

1238) 

1239 

1240 

1241BINARY_FIELDS = _fields( 

1242 DctrlKnownField( 

1243 "Package", 

1244 FieldValueClass.SINGLE_VALUE, 

1245 custom_field_check=_each_value_match_regex_validation(PKGNAME_REGEX), 

1246 is_stanza_name=True, 

1247 missing_field_severity=DiagnosticSeverity.Error, 

1248 hover_text="Declares the name of a binary package", 

1249 ), 

1250 DctrlKnownField( 

1251 "Package-Type", 

1252 FieldValueClass.SINGLE_VALUE, 

1253 default_value="deb", 

1254 known_values=_allowed_values( 

1255 Keyword("deb", hover_text="The package will be built as a regular deb."), 

1256 Keyword( 

1257 "udeb", 

1258 hover_text="The package will be built as a micro-deb (also known as a udeb). These are solely used by the debian-installer.", 

1259 ), 

1260 ), 

1261 hover_text=textwrap.dedent( 

1262 """\ 

1263 **Special-purpose only**. *This field is a special purpose field and is rarely needed.* 

1264 *You are recommended to omit unless you know you need it or someone told you to use it.* 

1265 

1266 Determines the type of package. This field can be used to declare that a given package is a different 

1267 type of package than usual. The primary case where this is known to be useful is for building 

1268 micro-debs ("udeb") to be consumed by the debian-installer. 

1269 """ 

1270 ), 

1271 ), 

1272 DctrlKnownField( 

1273 "Architecture", 

1274 FieldValueClass.SPACE_SEPARATED_LIST, 

1275 missing_field_severity=DiagnosticSeverity.Error, 

1276 unknown_value_diagnostic_severity=None, 

1277 known_values=_allowed_values(*dpkg_arch_and_wildcards()), 

1278 hover_text=textwrap.dedent( 

1279 """\ 

1280 Determines which architectures this package can be compiled for or if it is an architecture-independent 

1281 package. The value is a space-separated list of dpkg architecture names or wildcards. 

1282 

1283 **Example**: 

1284 ``` 

1285 Package: architecture-specific-package 

1286 Architecture: any 

1287 # ... 

1288 

1289 

1290 Package: data-only-package 

1291 Architecture: all 

1292 Multi-Arch: foreign 

1293 # ... 

1294 

1295 

1296 Package: linux-only-package 

1297 Architecture: linux-any 

1298 # ... 

1299 ``` 

1300 

1301 When in doubt, stick to the values **all** (for scripts, data or documentation, etc.) or **any** 

1302 (for anything that can be compiled). For official Debian packages, it is often easier to attempt the 

1303 compilation for unsupported architectures than to maintain the list of machine architectures that work. 

1304 """ 

1305 ), 

1306 ), 

1307 DctrlKnownField( 

1308 "Essential", 

1309 FieldValueClass.SINGLE_VALUE, 

1310 default_value="no", 

1311 known_values=_allowed_values( 

1312 Keyword( 

1313 "yes", 

1314 hover_text="The package is essential and uninstalling it will completely and utterly break the" 

1315 " system beyond repair.", 

1316 ), 

1317 Keyword( 

1318 "no", 

1319 hover_text=textwrap.dedent( 

1320 """\ 

1321 The package is a regular package. This is the default and recommended. 

1322 

1323 Note that declaring a package to be "Essential: no" is the same as not having the field except omitting 

1324 the field wastes fewer bytes on everyone's hard disk. 

1325 """ 

1326 ), 

1327 ), 

1328 ), 

1329 hover_text=textwrap.dedent( 

1330 """\ 

1331 **Special-purpose only**. *This field is a special purpose field and is rarely needed.* 

1332 *You are recommended to omit unless you know you need it or someone told you to use it.* 

1333 

1334 Whether the package should be considered Essential as defined by Debian Policy. 

1335 

1336 Essential packages are subject to several distinct but very important rules: 

1337 

1338 * Essential packages are considered essential for the system to work. The packaging system 

1339 (APT and dpkg) will refuse to uninstall it without some very insisting force options and warnings. 

1340 

1341 * Other packages are not required to declare explicit dependencies on essential packages as a 

1342 side-effect of the above except as to ensure a that the given essential package is upgraded 

1343 to a given minimum version. 

1344 

1345 * Once installed, essential packages function must at all time no matter where dpkg is in its 

1346 installation or upgrade process. During bootstrapping or installation, this requirement is 

1347 relaxed. 

1348 """ 

1349 ), 

1350 ), 

1351 DctrlKnownField( 

1352 "XB-Important", 

1353 FieldValueClass.SINGLE_VALUE, 

1354 replaced_by="Protected", 

1355 default_value="no", 

1356 known_values=_allowed_values( 

1357 Keyword( 

1358 "yes", 

1359 hover_text="The package is protected and attempts to uninstall it will cause strong warnings to the" 

1360 " user that they might be breaking the system.", 

1361 ), 

1362 Keyword( 

1363 "no", 

1364 hover_text=textwrap.dedent( 

1365 """\ 

1366 The package is a regular package. This is the default and recommended. 

1367 

1368 Note that declaring a package to be `XB-Important: no` is the same as not having the field 

1369 except omitting the field wastes fewer bytes on everyone's hard-disk. 

1370 """ 

1371 ), 

1372 ), 

1373 ), 

1374 ), 

1375 DctrlKnownField( 

1376 "Protected", 

1377 FieldValueClass.SINGLE_VALUE, 

1378 default_value="no", 

1379 known_values=_allowed_values( 

1380 Keyword( 

1381 "yes", 

1382 hover_text="The package is protected and attempts to uninstall it will cause strong warnings to the" 

1383 " user that they might be breaking the system.", 

1384 ), 

1385 Keyword( 

1386 "no", 

1387 hover_text=textwrap.dedent( 

1388 """\ 

1389 The package is a regular package. This is the default and recommended. 

1390 

1391 Note that declaring a package to be `Protected: no` is the same as not having the field 

1392 except omitting the field wastes fewer bytes on everyone's hard-disk. 

1393 """ 

1394 ), 

1395 ), 

1396 ), 

1397 ), 

1398 DctrlKnownField( 

1399 "Pre-Depends", 

1400 FieldValueClass.COMMA_SEPARATED_LIST, 

1401 hover_text=textwrap.dedent( 

1402 """\ 

1403 **Advanced field**. *This field covers an advanced topic. If you are new to packaging, you are* 

1404 *probably not looking for this field (except to set a **${misc:Pre-Depends}** relation. Incorrect use* 

1405 *of this field can cause issues - among other causing issues during upgrades that users cannot work* 

1406 *around without passing `--force-*` options to dpkg.* 

1407 

1408 This field is like *Depends*, except that is also forces dpkg to complete installation of the packages 

1409 named before even starting the installation of the package which declares the pre-dependency. 

1410 

1411 **Example**: 

1412 ``` 

1413 Pre-Depends: ${misc:Pre-Depends} 

1414 ``` 

1415 

1416 Note this is a very strong dependency and not all packages support being a pre-dependency because it 

1417 puts additional requirements on the package being depended on. Use of **${misc:Pre-Depends}** is 

1418 pre-approved and recommended. Essential packages are known to support being in **Pre-Depends**. 

1419 However, careless use of **Pre-Depends** for essential packages can still cause dependency resolvers 

1420 problems. 

1421 """ 

1422 ), 

1423 ), 

1424 DctrlKnownField( 

1425 "Depends", 

1426 FieldValueClass.COMMA_SEPARATED_LIST, 

1427 hover_text=textwrap.dedent( 

1428 """\ 

1429 Lists the packages that must be installed, before this package is installed. 

1430 

1431 **Example**: 

1432 ``` 

1433 Package: foo 

1434 Architecture: any 

1435 Depends: ${misc:Depends}, 

1436 ${shlibs:Depends}, 

1437 libfoo1 (= ${binary:Version}), 

1438 foo-data (= ${source:Version}), 

1439 ``` 

1440 

1441 This field declares an absolute dependency. Before installing the package, **dpkg** will require 

1442 all dependencies to be in state `configured` first. Though, if there is a circular dependency between 

1443 two or more packages, **dpkg** will break that circle at an arbitrary point where necessary based on 

1444 built-in heuristics. 

1445 

1446 This field should be used if the depended-on package is required for the depending package to provide a 

1447 *significant amount of functionality* or when it is used in the **postinst** or **prerm** maintainer 

1448 scripts. 

1449 """ 

1450 ), 

1451 ), 

1452 DctrlKnownField( 

1453 "Recommends", 

1454 FieldValueClass.COMMA_SEPARATED_LIST, 

1455 hover_text=textwrap.dedent( 

1456 """\ 

1457 Lists the packages that *should* be installed when this package is installed in all but 

1458 *unusual installations*. 

1459 

1460 **Example**: 

1461 ``` 

1462 Recommends: foo-optional 

1463 ``` 

1464 

1465 By default, APT will attempt to install recommends unless they cannot be installed or the user 

1466 has configured APT skip recommends. Notably, during automated package builds for the Debian 

1467 archive, **Recommends** are **not** installed. 

1468 

1469 As implied, the package must have some core functionality that works **without** the 

1470 **Recommends** being satisfied as they are not guaranteed to be there. If the package cannot 

1471 provide any functionality without a given package, that package should be in **Depends**. 

1472 """ 

1473 ), 

1474 ), 

1475 DctrlKnownField( 

1476 "Suggests", 

1477 FieldValueClass.COMMA_SEPARATED_LIST, 

1478 hover_text=textwrap.dedent( 

1479 """\ 

1480 Lists the packages that may make this package more useful but not installing them is perfectly 

1481 reasonable as well. Suggests can also be useful for add-ons that only make sense in particular 

1482 corner cases like supporting a non-standard file format. 

1483 

1484 **Example**: 

1485 ``` 

1486 Suggests: bar 

1487 ``` 

1488 """ 

1489 ), 

1490 ), 

1491 DctrlKnownField( 

1492 "Enhances", 

1493 FieldValueClass.COMMA_SEPARATED_LIST, 

1494 hover_text=textwrap.dedent( 

1495 """\ 

1496 This field is similar to Suggests but works in the opposite direction. It is used to declare that 

1497 this package can enhance the functionality of another package. 

1498 

1499 **Example**: 

1500 ``` 

1501 Package: foo 

1502 Provide: debputy-plugin-foo 

1503 Enhances: debputy 

1504 ``` 

1505 """ 

1506 ), 

1507 ), 

1508 DctrlKnownField( 

1509 "Provides", 

1510 FieldValueClass.COMMA_SEPARATED_LIST, 

1511 hover_text=textwrap.dedent( 

1512 """\ 

1513 Declare this package also provide one or more other packages. This means that this package can 

1514 substitute for the provided package in some relations. 

1515 

1516 **Example**: 

1517 ``` 

1518 Package: foo 

1519 ... 

1520 

1521 Package: foo-plus 

1522 Provides: foo (= ${source:Upstream-Version}) 

1523 ``` 

1524 

1525 If the provides relation is versioned, it must use a "strictly equals" version. If it does not 

1526 declare a version, then it *cannot* be used to satisfy a dependency with a version restriction. 

1527 Consider the following example: 

1528 

1529 **Archive scenario**: (This is *not* a `debian/control` file, despite the resemblance) 

1530 ``` 

1531 Package foo 

1532 Depends: bar (>= 1.0) 

1533 

1534 Package: bar 

1535 Version: 0.9 

1536 

1537 Package: bar-plus 

1538 Provides: bar (= 1.0) 

1539 

1540 Package: bar-clone 

1541 Provides: bar 

1542 ``` 

1543 

1544 In this archive scenario, the `bar-plus` package will satisfy the dependency of `foo` as the 

1545 only one. The `bar` package fails because the version is only *0.9* and `bar-clone` because 

1546 the provides is unversioned, but the dependency clause is versioned. 

1547 """ 

1548 ), 

1549 ), 

1550 DctrlKnownField( 

1551 "Conflicts", 

1552 FieldValueClass.COMMA_SEPARATED_LIST, 

1553 hover_text=textwrap.dedent( 

1554 """\ 

1555 **Warning**: *You may be looking for Breaks instead of Conflicts*. 

1556 

1557 This package cannot be installed together with the packages listed in the Conflicts field. This 

1558 is a *bigger hammer* than **Breaks** and is used sparingly. Notably, if you want to do a versioned 

1559 **Conflicts** then you *almost certainly* want **Breaks** instead. 

1560 

1561 **Example**: 

1562 ``` 

1563 Conflicts: bar 

1564 ``` 

1565 

1566 Please check the description of the **Breaks** field for when you would use **Breaks** vs. 

1567 **Conflicts**. 

1568 

1569 Note if a package conflicts with itself (indirectly or via **Provides**), then it is using a 

1570 special rule for **Conflicts**. See section 

1571 7.6.2 "[Replacing whole packages, forcing their removal]" in the Debian Policy Manual. 

1572 

1573 [Replacing whole packages, forcing their removal]: https://www.debian.org/doc/debian-policy/ch-relationships.html#replacing-whole-packages-forcing-their-removal 

1574 """ 

1575 ), 

1576 ), 

1577 DctrlKnownField( 

1578 "Breaks", 

1579 FieldValueClass.COMMA_SEPARATED_LIST, 

1580 hover_text=textwrap.dedent( 

1581 """\ 

1582 This package cannot be installed together with the packages listed in the `Breaks` field. 

1583 

1584 This is often use to declare versioned issues such as "This package does not work with foo if 

1585 it is version 1.0 or less". In comparison, `Conflicts` is generally used to declare that 

1586 "This package does not work at all as long as foo is installed". 

1587 

1588 **Example**: 

1589 ``` 

1590 Breaks: bar (<= 1.0~) 

1591 ```` 

1592 

1593 **Breaks vs. Conflicts**: 

1594 

1595 * I moved files from **foo** to **bar** in version X, what should I do? 

1596 

1597 Add `Breaks: foo (<< X~)` + `Replaces: foo (<< X~)` to **bar** 

1598 

1599 * Upgrading **bar** while **foo** is version X or less causes problems **foo** or **bar** to break. 

1600 How do I solve this? 

1601 

1602 Add `Breaks: foo (<< X~)` to **bar** 

1603 

1604 * The **foo** and **bar** packages provide the same functionality (interface) but different 

1605 implementations and there can be at most one of them. What should I do? 

1606 

1607 See section 7.6.2 [Replacing whole packages, forcing their removal] in the Debian Policy Manual. 

1608 

1609 * How to handle when **foo** and **bar** packages are unrelated but happen to provide the same binary? 

1610 

1611 Attempt to resolve the name conflict by renaming the clashing files in question on either (or both) sides. 

1612 

1613 Note the use of *~* in version numbers in the answers are generally used to ensure this works correctly in 

1614 case of a backports (in the Debian archive), where the package is rebuilt with the "~bpo" suffix in its 

1615 version. 

1616 

1617 [Replacing whole packages, forcing their removal]: https://www.debian.org/doc/debian-policy/ch-relationships.html#replacing-whole-packages-forcing-their-removal 

1618 """ 

1619 ), 

1620 ), 

1621 DctrlKnownField( 

1622 "Replaces", 

1623 FieldValueClass.COMMA_SEPARATED_LIST, 

1624 hover_text=textwrap.dedent( 

1625 """\ 

1626 This package either replaces another package or overwrites files that used to be provided by 

1627 another package. 

1628 

1629 **Attention**: The `Replaces` field is **always** used with either `Breaks` or `Conflicts` field. 

1630 

1631 **Example**: 

1632 ``` 

1633 Package: foo 

1634 ... 

1635 

1636 # The foo package was split to move data files into foo-data in version 1.2-3 

1637 Package: foo-data 

1638 Replaces: foo (<< 1.2-3~) 

1639 Breaks: foo (<< 1.2-3~) 

1640 ``` 

1641 

1642 Please check the description of the `Breaks` field for when you would use `Breaks` vs. `Conflicts`. 

1643 It also covers common uses of `Replaces`. 

1644 """ 

1645 ), 

1646 ), 

1647 DctrlKnownField( 

1648 "Build-Profiles", 

1649 FieldValueClass.BUILD_PROFILES_LIST, 

1650 hover_text=textwrap.dedent( 

1651 """\ 

1652 **Advanced field**. *This field covers an advanced topic. If you are new to packaging, you are* 

1653 *advised to leave it at its default until you have a working basic package or lots of time to understand* 

1654 *this topic.* 

1655 

1656 Declare that the package will only built when the given build-profiles are satisfied. 

1657 

1658 This field is primarily used in combination with build profiles inside the build dependency related fields 

1659 to reduce the number of build dependencies required during bootstrapping of a new architecture. 

1660 

1661 **Example**: 

1662 ``` 

1663 Package: foo 

1664 ... 

1665 

1666 Package: foo-udeb 

1667 Package-Type: udeb 

1668 # Skip building foo-udeb when the build profile "noudeb" is set (e.g., via dpkg-buildpackage -Pnoudeb) 

1669 Build-Profiles: <!noudeb> 

1670 ``` 

1671 

1672 Note that there is an official list of "common" build profiles with predefined purposes along with rules 

1673 for how and when the can be used. This list can be found at 

1674 <https://wiki.debian.org/BuildProfileSpec#Registered_profile_names>. 

1675 """ 

1676 ), 

1677 ), 

1678 DctrlKnownField( 

1679 "Section", 

1680 FieldValueClass.SINGLE_VALUE, 

1681 missing_field_severity=DiagnosticSeverity.Error, 

1682 inherits_from_source=True, 

1683 known_values=ALL_SECTIONS, 

1684 unknown_value_diagnostic_severity=DiagnosticSeverity.Warning, 

1685 hover_text=textwrap.dedent( 

1686 """\ 

1687 Define the section for this package. 

1688 

1689 **Example**: 

1690 ``` 

1691 Section: devel 

1692 ``` 

1693 

1694 Please see <https://packages.debian.org/unstable> for more details about the sections. 

1695 """ 

1696 ), 

1697 ), 

1698 DctrlKnownField( 

1699 "Priority", 

1700 FieldValueClass.SINGLE_VALUE, 

1701 default_value="optional", 

1702 warn_if_default=False, 

1703 missing_field_severity=DiagnosticSeverity.Error, 

1704 inherits_from_source=True, 

1705 known_values=ALL_PRIORITIES, 

1706 hover_text=textwrap.dedent( 

1707 """\ 

1708 Define the priority this package. 

1709 

1710 The priority field describes how important the package is for the functionality of the system. 

1711 

1712 **Example**: 

1713 ``` 

1714 Priority: optional 

1715 ``` 

1716 

1717 Unless you know you need a different value, you should choose **optional** for your packages. 

1718 """ 

1719 ), 

1720 ), 

1721 DctrlKnownField( 

1722 "Multi-Arch", 

1723 FieldValueClass.SINGLE_VALUE, 

1724 # Explicit "no" tends to be used as "someone reviewed this and concluded no", so we do 

1725 # not warn about it being explicitly "no". 

1726 warn_if_default=False, 

1727 default_value="no", 

1728 custom_field_check=_dctrl_ma_field_validation, 

1729 known_values=_allowed_values( 

1730 Keyword( 

1731 "no", 

1732 hover_text=textwrap.dedent( 

1733 """\ 

1734 The default. The package can be installed for at most one architecture at the time. It can 

1735 *only* satisfy relations for the same architecture as itself. Note that `Architecture: all` 

1736 packages are considered as a part of the system's "primary" architecture (see output of 

1737 `dpkg --print-architecture`). 

1738 

1739 Note: Despite the "no", the package *can* be installed for a foreign architecture (as an example, 

1740 you can install a 32-bit version of a package on a 64-bit system). However, packages depending 

1741 on it must also be installed for the foreign architecture. 

1742 """ 

1743 ), 

1744 ), 

1745 Keyword( 

1746 "foreign", 

1747 hover_text=textwrap.dedent( 

1748 """\ 

1749 The package can be installed for at most one architecture at the time. However, it can 

1750 satisfy relations for packages regardless of their architecture. This is often useful for packages 

1751 solely providing data or binaries that have "Multi-Arch neutral interfaces". 

1752 

1753 Sadly, describing a "Multi-Arch neutral interface" is hard and often only done by Multi-Arch 

1754 experts on a case-by-case basis. Some programs and scripts have "Multi-Arch dependent interfaces" 

1755 and are not safe to declare as `Multi-Arch: foreign`. 

1756 

1757 The name "foreign" refers to the fact that the package can satisfy relations for native 

1758 *and foreign* architectures at the same time. 

1759 """ 

1760 ), 

1761 ), 

1762 Keyword( 

1763 "same", 

1764 hover_text=textwrap.dedent( 

1765 """\ 

1766 The same version of the package can be co-installed for multiple architecture. However, 

1767 for this to work, the package *must* ship all files in architecture unique paths (usually 

1768 beneath `/usr/lib/<DEB_HOST_MULTIARCH>`) or have bit-for-bit identical content 

1769 in files that are in non-architecture unique paths (such as files beneath `/usr/share/doc`). 

1770 

1771 The name `same` refers to the fact that the package can satisfy relations only for the `same` 

1772 architecture as itself. However, in this case, it is co-installable with itself as noted above. 

1773 Note: This value **cannot** be used with `Architecture: all`. 

1774 """ 

1775 ), 

1776 ), 

1777 Keyword( 

1778 "allowed", 

1779 hover_text=textwrap.dedent( 

1780 """\ 

1781 **Advanced value**. The package is *not* co-installable with itself but can satisfy Multi-Arch 

1782 foreign and Multi-Arch same relations at the same. This is useful for implementations of 

1783 scripting languages (such as Perl or Python). Here the interpreter contextually need to 

1784 satisfy some relations as `Multi-Arch: foreign` and others as `Multi-Arch: same`. 

1785 

1786 Typically, native extensions or plugins will need a `Multi-Arch: same`-relation as they only 

1787 work with the interpreter compiled for the same machine architecture as themselves whereas 

1788 scripts are usually less picky and can rely on the `Multi-Arch: foreign` relation. Packages 

1789 wanting to rely on the "Multi-Arch: foreign" interface must explicitly declare this adding a 

1790 `:any` suffix to the package name in the dependency relation (e.g. `Depends: python3:any`). 

1791 However, the `:any"`suffix cannot be used unconditionally and should not be used unless you 

1792 know you need it. 

1793 """ 

1794 ), 

1795 ), 

1796 ), 

1797 hover_text=textwrap.dedent( 

1798 """\ 

1799 **Advanced field**. *This field covers an advanced topic. If you are new to packaging, you are* 

1800 *advised to leave it at its default until you have a working basic package or lots of time to understand* 

1801 *this topic.* 

1802 

1803 This field is used to declare the Multi-Arch interface of the package. 

1804 

1805 The `Multi-Arch` field is used to inform the installation system (APT and dpkg) about how it should handle 

1806 dependency relations involving this package and foreign architectures. This is useful for multiple purposes 

1807 such as cross-building without emulation and installing 32-bit packages on a 64-bit system. The latter is 

1808 often done to use legacy apps or old games that was never ported to 64-bit machines. 

1809 

1810 **Example**: 

1811 ``` 

1812 Multi-Arch: foreign 

1813 ``` 

1814 

1815 The rules for `Multi-Arch` can be quite complicated, but in many cases the following simple rules of thumb 

1816 gets you a long way: 

1817 

1818 * If the [Multi-Arch hinter] comes with a hint, then it almost certainly correct. You are recommended 

1819 to check the hint for further details (some changes can be complicated to do). Note that the 

1820 Multi-Arch hinter is only run for official Debian packages and may not be applicable to your case. 

1821 

1822 * If you have an `Architecture: all` data-only package, then it often want to be `Multi-Arch: foreign` 

1823 

1824 * If you have an architecture dependent package, where everything is installed in 

1825 `/usr/lib/${DEB_HOST_MULTIARCH}` (plus a bit of standard documentation in `/usr/share/doc`), then 

1826 you *probably* want `Multi-Arch: same` 

1827 

1828 * If none of the above applies, then omit the field unless you know what you are doing or you are 

1829 receiving advice from a Multi-Arch expert. 

1830 

1831 

1832 There are 4 possible values for the Multi-Arch field, though not all values are applicable to all packages: 

1833 

1834 

1835 * `no` - The default. The package can be installed for at most one architecture at the time. It can 

1836 *only* satisfy relations for the same architecture as itself. Note that `Architecture: all` packages 

1837 are considered as a part of the system's "primary" architecture (see output of `dpkg --print-architecture`). 

1838 

1839 Use of an explicit `no` over omitting the field is commonly done to signal that someone took the 

1840 effort to understand the situation and concluded `no` was the right answer. 

1841 

1842 Note: Despite the `no`, the package *can* be installed for a foreign architecture (e.g. you can 

1843 install a 32-bit version of a package on a 64-bit system). However, packages depending on it must also 

1844 be installed for the foreign architecture. 

1845 

1846 

1847 * `foreign` - The package can be installed for at most one architecture at the time. However, it can 

1848 satisfy relations for packages regardless of their architecture. This is often useful for packages 

1849 solely providing data or binaries that have "Multi-Arch neutral interfaces". Sadly, describing 

1850 a "Multi-Arch neutral interface" is hard and often only done by Multi-Arch experts on a case-by-case 

1851 basis. Among other, scripts despite being the same on all architectures can still have a "non-neutral" 

1852 "Multi-Arch" interface if their output is architecture dependent or if they dependencies force them 

1853 out of the `foreign` role. The dependency issue usually happens when depending indirectly on an 

1854 `Multi-Arch: allowed` package. 

1855 

1856 Some programs are have "Multi-Arch dependent interfaces" and are not safe to declare as 

1857 `Multi-Arch: foreign`. The name `foreign` refers to the fact that the package can satisfy relations 

1858 for native *and foreign* architectures at the same time. 

1859 

1860 

1861 * `same` - The same version of the package can be co-installed for multiple architecture. However, 

1862 for this to work, the package **must** ship all files in architecture unique paths (usually 

1863 beneath `/usr/lib/${DEB_HOST_MULTIARCH}`) **or** have bit-for-bit identical content in files 

1864 that are in non-architecture unique paths (e.g. `/usr/share/doc`). Note that these packages 

1865 typically do not contain configuration files or **dpkg** `conffile`s. 

1866 

1867 The name `same` refers to the fact that the package can satisfy relations only for the "same" 

1868 architecture as itself. However, in this case, it is co-installable with itself as noted above. 

1869 

1870 Note: This value **cannot** be used with `Architecture: all`. 

1871 

1872 

1873 * `allowed` - **Advanced value**. This value is for a complex use-case that most people does not 

1874 need. Consider it only if none of the other values seem to do the trick. 

1875 

1876 The package is **NOT** co-installable with itself but can satisfy Multi-Arch foreign and Multi-Arch same 

1877 relations at the same. This is useful for implementations of scripting languages (e.g. Perl or Python). 

1878 Here the interpreter contextually need to satisfy some relations as `Multi-Arch: foreign` and others as 

1879 `Multi-Arch: same` (or `Multi-Arch: no`). 

1880 

1881 Typically, native extensions or plugins will need a `Multi-Arch: same`-relation as they only work with 

1882 the interpreter compiled for the same machine architecture as themselves whereas scripts are usually 

1883 less picky and can rely on the `Multi-Arch: foreign` relation. Packages wanting to rely on the 

1884 `Multi-Arch: foreign` interface must explicitly declare this adding a `:any` suffix to the package name 

1885 in the dependency relation (such as `Depends: python3:any`). However, the `:any` suffix cannot be used 

1886 unconditionally and should not be used unless you know you need it. 

1887 

1888 Note that depending indirectly on a `Multi-Arch: allowed` package can require a `Architecture: all` + 

1889 `Multi-Arch: foreign` package to be converted to a `Architecture: any` package. This case is named 

1890 the "Multi-Arch interpreter problem", since it is commonly seen with script interpreters. However, 

1891 despite the name, it can happen to any kind of package. The bug [Debian#984701] is an example of 

1892 this happen in practice. 

1893 

1894 [Multi-Arch hinter]: https://wiki.debian.org/MultiArch/Hints 

1895 [Debian#984701]: https://bugs.debian.org/984701 

1896 """ 

1897 ), 

1898 ), 

1899 DctrlKnownField( 

1900 "XB-Installer-Menu-Item", 

1901 FieldValueClass.SINGLE_VALUE, 

1902 custom_field_check=_combined_custom_field_check( 

1903 _udeb_only_field_validation, 

1904 _each_value_match_regex_validation(re.compile(r"^[1-9]\d{3,4}$")), 

1905 ), 

1906 hover_text=textwrap.dedent( 

1907 """\ 

1908 This field is only relevant for `udeb` packages (debian-installer). 

1909 

1910 The field is used to declare where in the installer menu this package's menu item should 

1911 be placed (assuming it has any menu item). For packages targeting the Debian archive, 

1912 any new package should have its menu item number aligned with the debian-installer team 

1913 before upload. 

1914 

1915 A menu item is 4-5 digits (In the range `1000 <= X <= 99999`). In rare cases, the menu 

1916 item can be architecture dependent. For architecture dependent menu item values, use a 

1917 custom substvar. 

1918 

1919 See <https://d-i.debian.org/doc/internals/apa.html> for the full list of menu item ranges 

1920 and for how to request a number. 

1921 """ 

1922 ), 

1923 ), 

1924 DctrlKnownField( 

1925 "X-DH-Build-For-Type", 

1926 FieldValueClass.SINGLE_VALUE, 

1927 custom_field_check=_arch_not_all_only_field_validation, 

1928 default_value="host", 

1929 known_values=_allowed_values( 

1930 Keyword( 

1931 "host", 

1932 hover_text="The package should be compiled for `DEB_HOST_TARGET` (the default).", 

1933 ), 

1934 Keyword( 

1935 "target", 

1936 hover_text="The package should be compiled for `DEB_TARGET_ARCH`.", 

1937 ), 

1938 ), 

1939 hover_text=textwrap.dedent( 

1940 """\ 

1941 **Special-purpose only**. *This field is a special purpose field and is rarely needed.* 

1942 *You are recommended to omit unless you know you need it or someone told you to use it.* 

1943 

1944 This field is used when building a cross-compiling C-compiler (or similar cases), some packages need 

1945 to be build for target (DEB_**TARGET**_ARCH) rather than the host (DEB_**HOST**_ARCH) architecture. 

1946 

1947 **Example**: 

1948 ``` 

1949 Package: gcc 

1950 Architecture: any 

1951 # ... 

1952 

1953 Package: libgcc-s1 

1954 Architecture: any 

1955 # When building a cross-compiling gcc, then this library needs to be built for the target architecture 

1956 # as binaries compiled by gcc will link with this library. 

1957 X-DH-Build-For-Type: target 

1958 # ... 

1959 ``` 

1960 

1961 If you are in doubt, then you probably do **not** need this field. 

1962 """ 

1963 ), 

1964 ), 

1965 DctrlKnownField( 

1966 "X-Time64-Compat", 

1967 FieldValueClass.SINGLE_VALUE, 

1968 custom_field_check=_each_value_match_regex_validation(PKGNAME_REGEX), 

1969 hover_text=textwrap.dedent( 

1970 """\ 

1971 Special purpose field related to the 64-bit time transition. 

1972 

1973 It is used to inform packaging helpers what the original (non-transitioned) package name 

1974 was when the auto-detection is inadequate. The non-transitioned package name is then 

1975 conditionally provided in the `${t64:Provides}` substitution variable. 

1976 """ 

1977 ), 

1978 ), 

1979 DctrlKnownField( 

1980 "Homepage", 

1981 FieldValueClass.SINGLE_VALUE, 

1982 hover_text=textwrap.dedent( 

1983 """\ 

1984 Link to the upstream homepage for this binary package. 

1985 

1986 This field is rarely used in Package stanzas as most binary packages should have the 

1987 same homepage as the source package. Though, in the exceptional case where a particular 

1988 binary package should have a more specific homepage than the source package, you can 

1989 use this field to override the source package field. 

1990 ``` 

1991 """ 

1992 ), 

1993 ), 

1994 DctrlKnownField( 

1995 "Description", 

1996 FieldValueClass.FREE_TEXT_FIELD, 

1997 spellcheck_value=True, 

1998 # It will build just fine. But no one will know what it is for, so it probably won't be installed 

1999 missing_field_severity=DiagnosticSeverity.Warning, 

2000 hover_text=textwrap.dedent( 

2001 """\ 

2002 A human-readable description of the package. This field consists of two related but distinct parts. 

2003 

2004 

2005 The first line immediately after the field is called the *Synopsis* and is a short "noun-phrase" 

2006 intended to provide a one-line summary of the package. The lines after the **Synopsis** is known 

2007 as the **Extended Description** and is intended as a longer summary of the package. 

2008 

2009 **Example**: 

2010 ``` 

2011 Description: documentation generator for Python projects 

2012 Sphinx is a tool for producing documentation for Python projects, using 

2013 reStructuredText as markup language. 

2014 . 

2015 Sphinx features: 

2016 * HTML, CHM, LaTeX output, 

2017 * Cross-referencing source code, 

2018 * Automatic indices, 

2019 * Code highlighting, using Pygments, 

2020 * Extensibility. Existing extensions: 

2021 - automatic testing of code snippets, 

2022 - including docstrings from Python modules. 

2023 . 

2024 Build-depend on sphinx if your package uses /usr/bin/sphinx-* 

2025 executables. Build-depend on python3-sphinx if your package uses 

2026 the Python API (for instance by calling python3 -m sphinx). 

2027 ``` 

2028 

2029 The **Synopsis** is usually displayed in cases where there is limited space such as when reviewing 

2030 the search results from `apt search foo`. It is often a good idea to imagine that the **Synopsis** 

2031 part is inserted into a sentence like "The package provides {{Synopsis-goes-here}}". The 

2032 **Extended Description** is a standalone description that should describe what the package does and 

2033 how it relates to the rest of the system (in terms of, for example, which subsystem it is which part of). 

2034 Please see <https://www.debian.org/doc/debian-policy/ch-controlfields.html#description> for more details 

2035 about the description field and suggestions for how to write it. 

2036 """ 

2037 ), 

2038 ), 

2039 DctrlKnownField( 

2040 "XB-Cnf-Visible-Pkgname", 

2041 FieldValueClass.SINGLE_VALUE, 

2042 custom_field_check=_each_value_match_regex_validation(PKGNAME_REGEX), 

2043 hover_text=textwrap.dedent( 

2044 """\ 

2045 **Special-case field**: *This field is only useful in very special circumstances.* 

2046 *Consider whether you truly need it before adding this field.* 

2047 

2048 This field is used by `command-not-found` and can be used to override which package 

2049 `command-not-found` should propose the user to install. 

2050 

2051 Normally, when `command-not-found` detects a missing command, it will suggest the 

2052 user to install the package name listed in the `Package` field. In most cases, this 

2053 is what you want. However, in certain special-cases, the binary is provided by a 

2054 minimal package for technical reasons (like `python3-minimal`) and the user should 

2055 really install a package that provides more features (such as `python3` to follow 

2056 the example). 

2057 

2058 **Example**: 

2059 ``` 

2060 Package: python3-minimal 

2061 XB-Cnf-Visible-Pkgname: python3 

2062 ``` 

2063 

2064 Related bug: <https://bugs.launchpad.net/ubuntu/+source/python-defaults/+bug/1867157> 

2065 """ 

2066 ), 

2067 ), 

2068 DctrlKnownField( 

2069 "X-DhRuby-Root", 

2070 FieldValueClass.SINGLE_VALUE, 

2071 hover_text=textwrap.dedent( 

2072 """\ 

2073 Used by `dh_ruby` to request "multi-binary" layout and where the root for the given 

2074 package is. 

2075 

2076 Please refer to the documentation of `dh_ruby` for more details. 

2077 

2078 <https://manpages.debian.org/dh_ruby> 

2079 """ 

2080 ), 

2081 ), 

2082) 

2083_DEP5_HEADER_FIELDS = _fields( 

2084 Deb822KnownField( 

2085 "Format", 

2086 FieldValueClass.SINGLE_VALUE, 

2087 is_stanza_name=True, 

2088 missing_field_severity=DiagnosticSeverity.Error, 

2089 ), 

2090 Deb822KnownField( 

2091 "Upstream-Name", 

2092 FieldValueClass.FREE_TEXT_FIELD, 

2093 ), 

2094 Deb822KnownField( 

2095 "Upstream-Contact", 

2096 FieldValueClass.FREE_TEXT_FIELD, 

2097 ), 

2098 Deb822KnownField( 

2099 "Source", 

2100 FieldValueClass.FREE_TEXT_FIELD, 

2101 ), 

2102 Deb822KnownField( 

2103 "Disclaimer", 

2104 FieldValueClass.FREE_TEXT_FIELD, 

2105 spellcheck_value=True, 

2106 ), 

2107 Deb822KnownField( 

2108 "Comment", 

2109 FieldValueClass.FREE_TEXT_FIELD, 

2110 spellcheck_value=True, 

2111 ), 

2112 Deb822KnownField( 

2113 "License", 

2114 FieldValueClass.FREE_TEXT_FIELD, 

2115 # Do not tempt people to change legal text because the spellchecker wants to do a typo fix. 

2116 spellcheck_value=False, 

2117 ), 

2118) 

2119_DEP5_FILES_FIELDS = _fields( 

2120 Deb822KnownField( 

2121 "Files", 

2122 FieldValueClass.DEP5_FILE_LIST, 

2123 is_stanza_name=True, 

2124 missing_field_severity=DiagnosticSeverity.Error, 

2125 ), 

2126 Deb822KnownField( 

2127 "Copyright", 

2128 FieldValueClass.FREE_TEXT_FIELD, 

2129 # Mostly going to be names with very little free-text; high risk of false positives with low value 

2130 spellcheck_value=False, 

2131 missing_field_severity=DiagnosticSeverity.Error, 

2132 ), 

2133 Deb822KnownField( 

2134 "License", 

2135 FieldValueClass.FREE_TEXT_FIELD, 

2136 missing_field_severity=DiagnosticSeverity.Error, 

2137 # Do not tempt people to change legal text because the spellchecker wants to do a typo fix. 

2138 spellcheck_value=False, 

2139 ), 

2140 Deb822KnownField( 

2141 "Comment", 

2142 FieldValueClass.FREE_TEXT_FIELD, 

2143 spellcheck_value=True, 

2144 ), 

2145) 

2146_DEP5_LICENSE_FIELDS = _fields( 

2147 Deb822KnownField( 

2148 "License", 

2149 FieldValueClass.FREE_TEXT_FIELD, 

2150 is_stanza_name=True, 

2151 # Do not tempt people to change legal text because the spellchecker wants to do a typo fix. 

2152 spellcheck_value=False, 

2153 missing_field_severity=DiagnosticSeverity.Error, 

2154 ), 

2155 Deb822KnownField( 

2156 "Comment", 

2157 FieldValueClass.FREE_TEXT_FIELD, 

2158 spellcheck_value=True, 

2159 ), 

2160) 

2161 

2162_DTESTSCTRL_FIELDS = _fields( 

2163 Deb822KnownField( 

2164 "Architecture", 

2165 FieldValueClass.SPACE_SEPARATED_LIST, 

2166 unknown_value_diagnostic_severity=None, 

2167 known_values=_allowed_values(*dpkg_arch_and_wildcards()), 

2168 hover_text=textwrap.dedent( 

2169 """\ 

2170 When package tests are only supported on a limited set of 

2171 architectures, or are known to not work on a particular (set of) 

2172 architecture(s), this field can be used to define the supported 

2173 architectures. The autopkgtest will be skipped when the 

2174 architecture of the testbed doesn't match the content of this 

2175 field. The format is the same as in (Build-)Depends, with the 

2176 understanding that `all` is not allowed, and `any` means that 

2177 the test will be run on every architecture, which is the default 

2178 when not specifying this field at all. 

2179 """ 

2180 ), 

2181 ), 

2182 Deb822KnownField( 

2183 "Classes", 

2184 FieldValueClass.FREE_TEXT_FIELD, 

2185 hover_text=textwrap.dedent( 

2186 """\ 

2187 Most package tests should work in a minimal environment and are 

2188 usually not hardware specific. However, some packages like the 

2189 kernel, X.org, or graphics drivers should be tested on particular 

2190 hardware, and also run on a set of different platforms rather than 

2191 just a single virtual testbeds. 

2192 

2193 This field can specify a list of abstract class names such as 

2194 "desktop" or "graphics-driver". Consumers of autopkgtest can then 

2195 map these class names to particular machines/platforms/policies. 

2196 Unknown class names should be ignored. 

2197 

2198 This is purely an informational field for autopkgtest itself and 

2199 will be ignored. 

2200 """ 

2201 ), 

2202 ), 

2203 Deb822KnownField( 

2204 "Depends", 

2205 FieldValueClass.COMMA_SEPARATED_LIST, 

2206 default_value="@", 

2207 hover_text="""\ 

2208 Declares that the specified packages must be installed for the test 

2209 to go ahead. This supports all features of dpkg dependencies, including 

2210 the architecture qualifiers (see 

2211 <https://www.debian.org/doc/debian-policy/ch-relationships.html>), 

2212 plus the following extensions: 

2213 

2214 `@` stands for the package(s) generated by the source package 

2215 containing the tests; each dependency (strictly, or-clause, which 

2216 may contain `|`s but not commas) containing `@` is replicated 

2217 once for each such binary package, with the binary package name 

2218 substituted for each `@` (but normally `@` should occur only 

2219 once and without a version restriction). 

2220 

2221 `@builddeps@` will be replaced by the package's 

2222 `Build-Depends:`, `Build-Depends-Indep:`, `Build-Depends-Arch:`, and 

2223 `build-essential`. This is useful if you have many build 

2224 dependencies which are only necessary for running the test suite and 

2225 you don't want to replicate them in the test `Depends:`. However, 

2226 please use this sparingly, as this can easily lead to missing binary 

2227 package dependencies being overlooked if they get pulled in via 

2228 build dependencies. 

2229 

2230 `@recommends@` stands for all the packages listed in the 

2231 `Recommends:` fields of all the binary packages mentioned in the 

2232 `debian/control` file. Please note that variables are stripped, 

2233 so if some required test dependencies aren't explicitly mentioned, 

2234 they may not be installed. 

2235 

2236 If no Depends field is present, `Depends: @` is assumed. Note that 

2237 the source tree's Build-Dependencies are *not* necessarily 

2238 installed, and if you specify any Depends, no binary packages from 

2239 the source are installed unless explicitly requested. 

2240 """, 

2241 ), 

2242 Deb822KnownField( 

2243 "Features", 

2244 FieldValueClass.COMMA_OR_SPACE_SEPARATED_LIST, 

2245 hover_text=textwrap.dedent( 

2246 """\ 

2247 Declares some additional capabilities or good properties of the 

2248 tests defined in this stanza. Any unknown features declared will be 

2249 completely ignored. See below for the defined features. 

2250 

2251 Features are separated by commas and/or whitespace. 

2252 """ 

2253 ), 

2254 ), 

2255 Deb822KnownField( 

2256 "Restrictions", 

2257 FieldValueClass.COMMA_OR_SPACE_SEPARATED_LIST, 

2258 unknown_value_diagnostic_severity=DiagnosticSeverity.Warning, 

2259 known_values=_allowed_values( 

2260 Keyword( 

2261 "allow-stderr", 

2262 hover_text=textwrap.dedent( 

2263 """\ 

2264 Output to stderr is not considered a failure. This is useful for 

2265 tests which write e. g. lots of logging to stderr. 

2266 """ 

2267 ), 

2268 ), 

2269 Keyword( 

2270 "breaks-testbed", 

2271 hover_text=textwrap.dedent( 

2272 """\ 

2273 The test, when run, is liable to break the testbed system. This 

2274 includes causing data loss, causing services that the machine is 

2275 running to malfunction, or permanently disabling services; it does 

2276 not include causing services on the machine to temporarily fail. 

2277 

2278 When this restriction is present the test will usually be skipped 

2279 unless the testbed's virtualisation arrangements are sufficiently 

2280 powerful, or alternatively if the user explicitly requests. 

2281 """ 

2282 ), 

2283 ), 

2284 Keyword( 

2285 "build-needed", 

2286 hover_text=textwrap.dedent( 

2287 """\ 

2288 The tests need to be run from a built source tree. The test runner 

2289 will build the source tree (honouring the source package's build 

2290 dependencies), before running the tests. However, the tests are 

2291 *not* entitled to assume that the source package's build 

2292 dependencies will be installed when the test is run. 

2293 

2294 Please use this considerately, as for large builds it unnecessarily 

2295 builds the entire project when you only need a tiny subset (like the 

2296 `tests/` subdirectory). It is often possible to run `make -C tests` 

2297 instead, or copy the test code to `$AUTOPKGTEST_TMP` and build it 

2298 there with some custom commands. This cuts down the load on the 

2299 Continuous Integration servers and also makes tests more robust as 

2300 it prevents accidentally running them against the built source tree 

2301 instead of the installed packages. 

2302 """ 

2303 ), 

2304 ), 

2305 Keyword( 

2306 "flaky", 

2307 hover_text=textwrap.dedent( 

2308 """\ 

2309 The test is expected to fail intermittently, and is not suitable for 

2310 gating continuous integration. This indicates a bug in either the 

2311 package under test, a dependency or the test itself, but such bugs 

2312 can be difficult to fix, and it is often difficult to know when the 

2313 bug has been fixed without running the test for a while. If a 

2314 `flaky` test succeeds, it will be treated like any other 

2315 successful test, but if it fails it will be treated as though it 

2316 had been skipped. 

2317 """ 

2318 ), 

2319 ), 

2320 Keyword( 

2321 "hint-testsuite-triggers", 

2322 hover_text=textwrap.dedent( 

2323 """\ 

2324 This test exists purely as a hint to suggest when rerunning the 

2325 tests is likely to be useful. Specifically, it exists to 

2326 influence the way dpkg-source generates the Testsuite-Triggers 

2327 .dsc header from test metadata: the Depends for this test are 

2328 to be added to Testsuite-Triggers. (Just as they are for any other 

2329 test.) 

2330 

2331 The test with the hint-testsuite-triggers restriction should not 

2332 actually be run. 

2333 

2334 The packages listed as Depends for this test are usually indirect 

2335 dependencies, updates to which are considered to pose a risk of 

2336 regressions in other tests defined in this package. 

2337 

2338 There is currently no way to specify this hint on a per-test 

2339 basis; but in any case the debian.org machinery is not able to 

2340 think about triggering individual tests. 

2341 """ 

2342 ), 

2343 ), 

2344 Keyword( 

2345 "isolation-container", 

2346 hover_text=textwrap.dedent( 

2347 """\ 

2348 The test wants to start services or open network TCP ports. This 

2349 commonly fails in a simple chroot/schroot, so tests need to be run 

2350 in their own container (e. g. autopkgtest-virt-lxc) or their own 

2351 machine/VM (e. g. autopkgtest-virt-qemu or autopkgtest-virt-null). 

2352 When running the test in a virtualization server which does not 

2353 provide this (like autopkgtest-schroot) it will be skipped. 

2354 

2355 Tests may assume that this restriction implies that process 1 in the 

2356 container's process namespace is a system service manager (init system) 

2357 such as systemd or sysvinit + sysv-rc, and therefore system services 

2358 are available via the `service(8)`, `invoke-rc.d(8)` and 

2359 `update-rc.d(8))` interfaces. 

2360 

2361 Tests must not assume that a specific init system is in use: a 

2362 dependency such as `systemd-sysv` or `sysvinit-core` does not work 

2363 in practice, because switching the init system often cannot be done 

2364 automatically. Tests that require a specific init system should use the 

2365 `skippable` restriction, and skip the test if the required init system 

2366 was not detected. 

2367 

2368 Many implementations of the `isolation-container` restriction will 

2369 also provide `systemd-logind(8)` or a compatible interface, but this 

2370 is not guaranteed. Tests requiring a login session registered with 

2371 logind should declare a dependency on `default-logind | logind` 

2372 or on a more specific implementation of `logind`, and should use the 

2373 `skippable` restriction to exit gracefully if its functionality is 

2374 not available at runtime. 

2375 

2376 """ 

2377 ), 

2378 ), 

2379 Keyword( 

2380 "isolation-machine", 

2381 hover_text=textwrap.dedent( 

2382 """\ 

2383 The test wants to interact with the kernel, reboot the machine, or 

2384 other things which fail in a simple schroot and even a container. 

2385 Those tests need to be run in their own machine/VM (e. g. 

2386 autopkgtest-virt-qemu or autopkgtest-virt-null). When running the 

2387 test in a virtualization server which does not provide this it will 

2388 be skipped. 

2389 

2390 This restriction also provides the same facilities as 

2391 `isolation-container`. 

2392 """ 

2393 ), 

2394 ), 

2395 Keyword( 

2396 "needs-internet", 

2397 hover_text=textwrap.dedent( 

2398 """\ 

2399 The test needs unrestricted internet access, e.g. to download test data 

2400 that's not shipped as a package, or to test a protocol implementation 

2401 against a test server. Please also see the note about Network access later 

2402 in this document. 

2403 """ 

2404 ), 

2405 ), 

2406 Keyword( 

2407 "needs-reboot", 

2408 hover_text=textwrap.dedent( 

2409 """\ 

2410 The test wants to reboot the machine using 

2411 `/tmp/autopkgtest-reboot`. 

2412 """ 

2413 ), 

2414 ), 

2415 Keyword( 

2416 "needs-recommends", 

2417 is_obsolete=True, 

2418 hover_text=textwrap.dedent( 

2419 """\ 

2420 Please use `@recommends@` in your test `Depends:` instead. 

2421 """ 

2422 ), 

2423 ), 

2424 Keyword( 

2425 "needs-root", 

2426 hover_text=textwrap.dedent( 

2427 """\ 

2428 The test script must be run as root. 

2429 

2430 While running tests with this restriction, some test runners will 

2431 set the `AUTOPKGTEST_NORMAL_USER` environment variable to the name 

2432 of an ordinary user account. If so, the test script may drop 

2433 privileges from root to that user, for example via the `runuser` 

2434 command. Test scripts must not assume that this environment variable 

2435 will always be set. 

2436 

2437 For tests that declare both the `needs-root` and `isolation-machine` 

2438 restrictions, the test may assume that it has "global root" with full 

2439 control over the kernel that is running the test, and not just root 

2440 in a container (more formally, it has uid 0 and full capabilities in 

2441 the initial user namespace as defined in `user_namespaces(7)`). 

2442 For example, it can expect that mounting block devices will succeed. 

2443 

2444 For tests that declare the `needs-root` restriction but not the 

2445 `isolation-machine` restriction, the test will be run as uid 0 in 

2446 a user namespace with a reasonable range of system and user uids 

2447 available, but will not necessarily have full control over the kernel, 

2448 and in particular it is not guaranteed to have elevated capabilities 

2449 in the initial user namespace as defined by `user_namespaces(7)`. 

2450 For example, it might be run in a namespace where uid 0 is mapped to 

2451 an ordinary uid in the initial user namespace, or it might run in a 

2452 Docker-style container where global uid 0 is used but its ability to 

2453 carry out operations that affect the whole system is restricted by 

2454 capabilities and system call filtering. Tests requiring particular 

2455 privileges should use the `skippable` restriction to check for 

2456 required functionality at runtime. 

2457 """ 

2458 ), 

2459 ), 

2460 Keyword( 

2461 "needs-sudo", 

2462 hover_text=textwrap.dedent( 

2463 """\ 

2464 The test script needs to be run as a non-root user who is a member of 

2465 the `sudo` group, and has the ability to elevate privileges to root 

2466 on-demand. 

2467 

2468 This is useful for testing user components which should not normally 

2469 be run as root, in test scenarios that require configuring a system 

2470 service to support the test. For example, gvfs has a test-case which 

2471 uses sudo for privileged configuration of a Samba server, so that 

2472 the unprivileged gvfs service under test can communicate with that server. 

2473 

2474 While running a test with this restriction, `sudo(8)` will be 

2475 installed and configured to allow members of the `sudo` group to run 

2476 any command without password authentication. 

2477 

2478 Because the test user is a member of the `sudo` group, they will 

2479 also gain the ability to take any other privileged actions that are 

2480 controlled by membership in that group. In particular, several packages 

2481 install `polkit(8)` policies allowing members of group `sudo` to 

2482 take administrative actions with or without authentication. 

2483 

2484 If the test requires access to additional privileged actions, it may 

2485 use its access to `sudo(8)` to install additional configuration 

2486 files, for example configuring `polkit(8)` or `doas.conf(5)` 

2487 to allow running `pkexec(1)` or `doas(1)` without authentication. 

2488 

2489 Commands run via `sudo(8)` or another privilege-elevation tool could 

2490 be run with either "global root" or root in a container, depending 

2491 on the presence or absence of the `isolation-machine` restriction, 

2492 in the same way described for `needs-root`. 

2493 """ 

2494 ), 

2495 ), 

2496 Keyword( 

2497 "rw-build-tree", 

2498 hover_text=textwrap.dedent( 

2499 """\ 

2500 The test(s) needs write access to the built source tree (so it may 

2501 need to be copied first). Even with this restriction, the test is 

2502 not allowed to make any change to the built source tree which (i) 

2503 isn't cleaned up by `debian/rules clean`, (ii) affects the future 

2504 results of any test, or (iii) affects binary packages produced by 

2505 the build tree in the future. 

2506 """ 

2507 ), 

2508 ), 

2509 Keyword( 

2510 "skip-not-installable", 

2511 hover_text=textwrap.dedent( 

2512 """\ 

2513 This restrictions may cause a test to miss a regression due to 

2514 installability issues, so use with caution. If one only wants to 

2515 skip certain architectures, use the `Architecture` field for 

2516 that. 

2517 

2518 This test might have test dependencies that can't be fulfilled in 

2519 all suites or in derivatives. Therefore, when apt-get installs the 

2520 test dependencies, it will fail. Don't treat this as a test 

2521 failure, but instead treat it as if the test was skipped. 

2522 """ 

2523 ), 

2524 ), 

2525 Keyword( 

2526 "skippable", 

2527 hover_text=textwrap.dedent( 

2528 """\ 

2529 The test might need to be skipped for reasons that cannot be 

2530 described by an existing restriction such as isolation-machine or 

2531 breaks-testbed, but must instead be detected at runtime. If the 

2532 test exits with status 77 (a convention borrowed from Automake), it 

2533 will be treated as though it had been skipped. If it exits with any 

2534 other status, its success or failure will be derived from the exit 

2535 status and stderr as usual. Test authors must be careful to ensure 

2536 that `skippable` tests never exit with status 77 for reasons that 

2537 should be treated as a failure. 

2538 """ 

2539 ), 

2540 ), 

2541 Keyword( 

2542 "superficial", 

2543 hover_text=textwrap.dedent( 

2544 """\ 

2545 The test does not provide significant test coverage, so if it 

2546 passes, that does not necessarily mean that the package under test 

2547 is actually functional. If a `superficial` test fails, it will be 

2548 treated like any other failing test, but if it succeeds, this is 

2549 only a weak indication of success. Continuous integration systems 

2550 should treat a package where all non-superficial tests are skipped as 

2551 equivalent to a package where all tests are skipped. 

2552 

2553 For example, a C library might have a superficial test that simply 

2554 compiles, links and executes a "hello world" program against the 

2555 library under test but does not attempt to make use of the library's 

2556 functionality, while a Python or Perl library might have a 

2557 superficial test that runs `import foo` or `require Foo;` but 

2558 does not attempt to use the library beyond that. 

2559 """ 

2560 ), 

2561 ), 

2562 ), 

2563 hover_text=textwrap.dedent( 

2564 """\ 

2565 Declares some restrictions or problems with the tests defined in 

2566 this stanza. Depending on the test environment capabilities, user 

2567 requests, and so on, restrictions can cause tests to be skipped or 

2568 can cause the test to be run in a different manner. Tests which 

2569 declare unknown restrictions will be skipped. See below for the 

2570 defined restrictions. 

2571 

2572 Restrictions are separated by commas and/or whitespace. 

2573 """ 

2574 ), 

2575 ), 

2576 Deb822KnownField( 

2577 "Tests", 

2578 FieldValueClass.COMMA_OR_SPACE_SEPARATED_LIST, 

2579 hover_text=textwrap.dedent( 

2580 """\ 

2581 This field names the tests which are defined by this stanza, and map 

2582 to executables/scripts in the test directory. All of the other 

2583 fields in the same stanza apply to all of the named tests. Either 

2584 this field or `Test-Command:` must be present. 

2585 

2586 Test names are separated by comma and/or whitespace and should 

2587 contain only characters which are legal in package names. It is 

2588 permitted, but not encouraged, to use upper-case characters as well. 

2589 """ 

2590 ), 

2591 ), 

2592 Deb822KnownField( 

2593 "Test-Command", 

2594 FieldValueClass.FREE_TEXT_FIELD, 

2595 hover_text=textwrap.dedent( 

2596 """\ 

2597 If your test only contains a shell command or two, or you want to 

2598 reuse an existing upstream test executable and just need to wrap it 

2599 with some command like `dbus-launch` or `env`, you can use this 

2600 field to specify the shell command directly. It will be run under 

2601 `bash -e`. This is mutually exclusive with the `Tests:` field. 

2602 

2603 This is also useful for running the same script under different 

2604 interpreters and/or with different dependencies, such as 

2605 `Test-Command: python debian/tests/mytest.py` and 

2606 `Test-Command: python3 debian/tests/mytest.py`. 

2607 """ 

2608 ), 

2609 ), 

2610 Deb822KnownField( 

2611 "Test-Directory", 

2612 FieldValueClass.FREE_TEXT_FIELD, # TODO: Single path 

2613 hover_text=textwrap.dedent( 

2614 """\ 

2615 Replaces the path segment `debian/tests` in the filenames of the 

2616 test programs with `path`. I. e., the tests are run by executing 

2617 `built/source/tree/path/testname`. `path` must be a relative 

2618 path and is interpreted starting from the root of the built source 

2619 tree. 

2620 

2621 This allows tests to live outside the `debian/` metadata area, so that 

2622 they can more palatably be shared with non-Debian distributions. 

2623 """ 

2624 ), 

2625 ), 

2626) 

2627 

2628 

2629@dataclasses.dataclass(slots=True, frozen=True) 

2630class StanzaMetadata(Mapping[str, F], Generic[F], ABC): 

2631 stanza_type_name: str 

2632 stanza_fields: Mapping[str, F] 

2633 

2634 def stanza_diagnostics( 

2635 self, 

2636 stanza: Deb822ParagraphElement, 

2637 stanza_position_in_file: "TEPosition", 

2638 ) -> Iterable[Diagnostic]: 

2639 raise NotImplementedError 

2640 

2641 def __getitem__(self, key: str) -> F: 

2642 key_lc = key.lower() 

2643 key_norm = normalize_dctrl_field_name(key_lc) 

2644 return self.stanza_fields[key_norm] 

2645 

2646 def __len__(self) -> int: 

2647 return len(self.stanza_fields) 

2648 

2649 def __iter__(self): 

2650 return iter(self.stanza_fields.keys()) 

2651 

2652 

2653@dataclasses.dataclass(slots=True, frozen=True) 

2654class Dep5StanzaMetadata(StanzaMetadata[Deb822KnownField]): 

2655 def stanza_diagnostics( 

2656 self, 

2657 stanza: Deb822ParagraphElement, 

2658 stanza_position_in_file: "TEPosition", 

2659 ) -> Iterable[Diagnostic]: 

2660 pass 

2661 

2662 

2663@dataclasses.dataclass(slots=True, frozen=True) 

2664class DctrlStanzaMetadata(StanzaMetadata[DctrlKnownField]): 

2665 

2666 def stanza_diagnostics( 

2667 self, 

2668 stanza: Deb822ParagraphElement, 

2669 stanza_position_in_file: "TEPosition", 

2670 ) -> Iterable[Diagnostic]: 

2671 pass 

2672 

2673 

2674@dataclasses.dataclass(slots=True, frozen=True) 

2675class DTestsCtrlStanzaMetadata(StanzaMetadata[Deb822KnownField]): 

2676 

2677 def stanza_diagnostics( 

2678 self, 

2679 stanza: Deb822ParagraphElement, 

2680 stanza_position_in_file: "TEPosition", 

2681 ) -> Iterable[Diagnostic]: 

2682 pass 

2683 

2684 

2685class Deb822FileMetadata(Generic[S]): 

2686 def classify_stanza(self, stanza: Deb822ParagraphElement, stanza_idx: int) -> S: 

2687 return self.guess_stanza_classification_by_idx(stanza_idx) 

2688 

2689 def guess_stanza_classification_by_idx(self, stanza_idx: int) -> S: 

2690 raise NotImplementedError 

2691 

2692 def stanza_types(self) -> Iterable[S]: 

2693 raise NotImplementedError 

2694 

2695 def __getitem__(self, item: str) -> S: 

2696 raise NotImplementedError 

2697 

2698 def file_diagnostics( 

2699 self, 

2700 file: Deb822FileElement, 

2701 ) -> Iterable[Diagnostic]: 

2702 raise NotImplementedError 

2703 

2704 def get(self, item: str) -> Optional[S]: 

2705 try: 

2706 return self[item] 

2707 except KeyError: 

2708 return None 

2709 

2710 

2711_DCTRL_SOURCE_STANZA = DctrlStanzaMetadata( 

2712 "Source", 

2713 SOURCE_FIELDS, 

2714) 

2715_DCTRL_PACKAGE_STANZA = DctrlStanzaMetadata("Package", BINARY_FIELDS) 

2716 

2717_DEP5_HEADER_STANZA = Dep5StanzaMetadata( 

2718 "Header", 

2719 _DEP5_HEADER_FIELDS, 

2720) 

2721_DEP5_FILES_STANZA = Dep5StanzaMetadata( 

2722 "Files", 

2723 _DEP5_FILES_FIELDS, 

2724) 

2725_DEP5_LICENSE_STANZA = Dep5StanzaMetadata( 

2726 "License", 

2727 _DEP5_LICENSE_FIELDS, 

2728) 

2729 

2730_DTESTSCTRL_STANZA = DTestsCtrlStanzaMetadata("Tests", _DTESTSCTRL_FIELDS) 

2731 

2732 

2733class Dep5FileMetadata(Deb822FileMetadata[Dep5StanzaMetadata]): 

2734 def classify_stanza(self, stanza: Deb822ParagraphElement, stanza_idx: int) -> S: 

2735 if stanza_idx == 0: 

2736 return _DEP5_HEADER_STANZA 

2737 if stanza_idx > 0: 

2738 if "Files" in stanza: 

2739 return _DEP5_FILES_STANZA 

2740 return _DEP5_LICENSE_STANZA 

2741 raise ValueError("The stanza_idx must be 0 or greater") 

2742 

2743 def guess_stanza_classification_by_idx(self, stanza_idx: int) -> S: 

2744 if stanza_idx == 0: 

2745 return _DEP5_HEADER_STANZA 

2746 if stanza_idx > 0: 

2747 return _DEP5_FILES_STANZA 

2748 raise ValueError("The stanza_idx must be 0 or greater") 

2749 

2750 def stanza_types(self) -> Iterable[S]: 

2751 yield _DEP5_HEADER_STANZA 

2752 yield _DEP5_FILES_STANZA 

2753 yield _DEP5_LICENSE_STANZA 

2754 

2755 def __getitem__(self, item: str) -> S: 

2756 if item == "Header": 

2757 return _DEP5_FILES_STANZA 

2758 if item == "Files": 

2759 return _DEP5_FILES_STANZA 

2760 if item == "License": 

2761 return _DEP5_LICENSE_STANZA 

2762 raise KeyError(item) 

2763 

2764 

2765class DctrlFileMetadata(Deb822FileMetadata[DctrlStanzaMetadata]): 

2766 def guess_stanza_classification_by_idx(self, stanza_idx: int) -> S: 

2767 if stanza_idx == 0: 2767 ↛ 2768line 2767 didn't jump to line 2768, because the condition on line 2767 was never true

2768 return _DCTRL_SOURCE_STANZA 

2769 if stanza_idx > 0: 2769 ↛ 2771line 2769 didn't jump to line 2771, because the condition on line 2769 was never false

2770 return _DCTRL_PACKAGE_STANZA 

2771 raise ValueError("The stanza_idx must be 0 or greater") 

2772 

2773 def stanza_types(self) -> Iterable[S]: 

2774 yield _DCTRL_SOURCE_STANZA 

2775 yield _DCTRL_PACKAGE_STANZA 

2776 

2777 def __getitem__(self, item: str) -> S: 

2778 if item == "Source": 

2779 return _DCTRL_SOURCE_STANZA 

2780 if item == "Package": 

2781 return _DCTRL_PACKAGE_STANZA 

2782 raise KeyError(item) 

2783 

2784 

2785class DTestsCtrlFileMetadata(Deb822FileMetadata[DctrlStanzaMetadata]): 

2786 def guess_stanza_classification_by_idx(self, stanza_idx: int) -> S: 

2787 if stanza_idx >= 0: 

2788 return _DTESTSCTRL_STANZA 

2789 raise ValueError("The stanza_idx must be 0 or greater") 

2790 

2791 def stanza_types(self) -> Iterable[S]: 

2792 yield _DTESTSCTRL_STANZA 

2793 

2794 def __getitem__(self, item: str) -> S: 

2795 if item == "Tests": 

2796 return _DTESTSCTRL_STANZA 

2797 raise KeyError(item)