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
« 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)
24from debian.debian_support import DpkgArchTable
25from lsprotocol.types import DiagnosticSeverity, Diagnostic, DiagnosticTag, Range
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
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
70F = TypeVar("F", bound="Deb822KnownField")
71S = TypeVar("S", bound="StanzaMetadata")
74# FIXME: should go into python3-debian
75_RE_COMMA = re.compile("([^,]*),([^,]*)")
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))
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)
111CustomFieldCheck = Callable[
112 [
113 "F",
114 Deb822KeyValuePairElement,
115 "TERange",
116 Deb822ParagraphElement,
117 "TEPosition",
118 "LintCapablePositionCodec",
119 List[str],
120 ],
121 Iterable[Diagnostic],
122]
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)
188ALL_COMPONENTS = frozenset(
189 [
190 "main",
191 "restricted", # Ubuntu
192 "non-free",
193 "non-free-firmware",
194 "contrib",
195 ]
196)
199def _fields(*fields: F) -> Mapping[str, F]:
200 return {normalize_dctrl_field_name(f.name.lower()): f for f in fields}
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
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
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)
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).
236 Applicable if dpkg *needs* this package to function and it is not a library.
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.
249 Applicable if 99% of all users in the distribution needs this package and it is not a library.
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.
264 Applicable if your distribution installer will install this package by default on a new system
265 and it is not a library.
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)
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.
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.
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
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))
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
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 )
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 )
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 )
432def _each_value_match_regex_validation(
433 regex: re.Pattern,
434 *,
435 diagnostic_severity: DiagnosticSeverity = DiagnosticSeverity.Error,
436) -> CustomFieldCheck:
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]:
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
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 )
474 return _validator
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 )
498 return _validator
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
511 def interpreter(self) -> Optional[Interpretation[Any]]:
512 return self.value[1]
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
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 )
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 )
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 )
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
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
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 )
720@dataclasses.dataclass(slots=True, frozen=True)
721class DctrlKnownField(Deb822KnownField):
722 inherits_from_source: bool = False
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.
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.
748 **Example**:
749 ```
750 Standards-Version: 4.5.2
751 ```
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.
767 **Example**:
768 ```
769 Section: devel
770 ```
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.
786 The priority field describes how important the package is for the functionality of the system.
788 **Example**:
789 ```
790 Priority: optional
791 ```
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.
805 **Example**:
806 ```
807 Maintainer: Jane Contributor <jane@janes.email-provider.org>
808 ```
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.
821 **Example**:
822 ```
823 Uploaders:
824 John Doe <john@doe.org>,
825 Lisbeth Worker <lis@worker.org>,
826 ```
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.
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.
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.
859 This should be used together with the **Vcs-Browser** field provided there is a web UI for the repo.
861 Note it is possible to specify a branch via the `-b` option.
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.
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.
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.
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.
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.
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.
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
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.
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.
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**.
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.
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**.
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**.
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.
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.
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`.
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.
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.
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.
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.
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.
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.
1109 **Example**:
1110 ```
1111 Rules-Requires-Root: no
1112 ```
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.
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`
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
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.
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
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
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
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.
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.
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.
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 ```
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)
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.*
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.
1283 **Example**:
1284 ```
1285 Package: architecture-specific-package
1286 Architecture: any
1287 # ...
1290 Package: data-only-package
1291 Architecture: all
1292 Multi-Arch: foreign
1293 # ...
1296 Package: linux-only-package
1297 Architecture: linux-any
1298 # ...
1299 ```
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.
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.*
1334 Whether the package should be considered Essential as defined by Debian Policy.
1336 Essential packages are subject to several distinct but very important rules:
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.
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.
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.
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.
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.*
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.
1411 **Example**:
1412 ```
1413 Pre-Depends: ${misc:Pre-Depends}
1414 ```
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.
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 ```
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.
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*.
1460 **Example**:
1461 ```
1462 Recommends: foo-optional
1463 ```
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.
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.
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.
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.
1516 **Example**:
1517 ```
1518 Package: foo
1519 ...
1521 Package: foo-plus
1522 Provides: foo (= ${source:Upstream-Version})
1523 ```
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:
1529 **Archive scenario**: (This is *not* a `debian/control` file, despite the resemblance)
1530 ```
1531 Package foo
1532 Depends: bar (>= 1.0)
1534 Package: bar
1535 Version: 0.9
1537 Package: bar-plus
1538 Provides: bar (= 1.0)
1540 Package: bar-clone
1541 Provides: bar
1542 ```
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*.
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.
1561 **Example**:
1562 ```
1563 Conflicts: bar
1564 ```
1566 Please check the description of the **Breaks** field for when you would use **Breaks** vs.
1567 **Conflicts**.
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.
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.
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".
1588 **Example**:
1589 ```
1590 Breaks: bar (<= 1.0~)
1591 ````
1593 **Breaks vs. Conflicts**:
1595 * I moved files from **foo** to **bar** in version X, what should I do?
1597 Add `Breaks: foo (<< X~)` + `Replaces: foo (<< X~)` to **bar**
1599 * Upgrading **bar** while **foo** is version X or less causes problems **foo** or **bar** to break.
1600 How do I solve this?
1602 Add `Breaks: foo (<< X~)` to **bar**
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?
1607 See section 7.6.2 [Replacing whole packages, forcing their removal] in the Debian Policy Manual.
1609 * How to handle when **foo** and **bar** packages are unrelated but happen to provide the same binary?
1611 Attempt to resolve the name conflict by renaming the clashing files in question on either (or both) sides.
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.
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.
1629 **Attention**: The `Replaces` field is **always** used with either `Breaks` or `Conflicts` field.
1631 **Example**:
1632 ```
1633 Package: foo
1634 ...
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 ```
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.*
1656 Declare that the package will only built when the given build-profiles are satisfied.
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.
1661 **Example**:
1662 ```
1663 Package: foo
1664 ...
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 ```
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.
1689 **Example**:
1690 ```
1691 Section: devel
1692 ```
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.
1710 The priority field describes how important the package is for the functionality of the system.
1712 **Example**:
1713 ```
1714 Priority: optional
1715 ```
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`).
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".
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`.
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`).
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`.
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.*
1803 This field is used to declare the Multi-Arch interface of the package.
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.
1810 **Example**:
1811 ```
1812 Multi-Arch: foreign
1813 ```
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:
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.
1822 * If you have an `Architecture: all` data-only package, then it often want to be `Multi-Arch: foreign`
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`
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.
1832 There are 4 possible values for the Multi-Arch field, though not all values are applicable to all packages:
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`).
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.
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.
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.
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.
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.
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.
1870 Note: This value **cannot** be used with `Architecture: all`.
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.
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`).
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.
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.
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).
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.
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.
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.*
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.
1947 **Example**:
1948 ```
1949 Package: gcc
1950 Architecture: any
1951 # ...
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 ```
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.
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.
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.
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.
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 ```
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.*
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.
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).
2058 **Example**:
2059 ```
2060 Package: python3-minimal
2061 XB-Cnf-Visible-Pkgname: python3
2062 ```
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.
2076 Please refer to the documentation of `dh_ruby` for more details.
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)
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.
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.
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:
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).
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.
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.
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.
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.
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.
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.)
2331 The test with the hint-testsuite-triggers restriction should not
2332 actually be run.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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)
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]
2634 def stanza_diagnostics(
2635 self,
2636 stanza: Deb822ParagraphElement,
2637 stanza_position_in_file: "TEPosition",
2638 ) -> Iterable[Diagnostic]:
2639 raise NotImplementedError
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]
2646 def __len__(self) -> int:
2647 return len(self.stanza_fields)
2649 def __iter__(self):
2650 return iter(self.stanza_fields.keys())
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
2663@dataclasses.dataclass(slots=True, frozen=True)
2664class DctrlStanzaMetadata(StanzaMetadata[DctrlKnownField]):
2666 def stanza_diagnostics(
2667 self,
2668 stanza: Deb822ParagraphElement,
2669 stanza_position_in_file: "TEPosition",
2670 ) -> Iterable[Diagnostic]:
2671 pass
2674@dataclasses.dataclass(slots=True, frozen=True)
2675class DTestsCtrlStanzaMetadata(StanzaMetadata[Deb822KnownField]):
2677 def stanza_diagnostics(
2678 self,
2679 stanza: Deb822ParagraphElement,
2680 stanza_position_in_file: "TEPosition",
2681 ) -> Iterable[Diagnostic]:
2682 pass
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)
2689 def guess_stanza_classification_by_idx(self, stanza_idx: int) -> S:
2690 raise NotImplementedError
2692 def stanza_types(self) -> Iterable[S]:
2693 raise NotImplementedError
2695 def __getitem__(self, item: str) -> S:
2696 raise NotImplementedError
2698 def file_diagnostics(
2699 self,
2700 file: Deb822FileElement,
2701 ) -> Iterable[Diagnostic]:
2702 raise NotImplementedError
2704 def get(self, item: str) -> Optional[S]:
2705 try:
2706 return self[item]
2707 except KeyError:
2708 return None
2711_DCTRL_SOURCE_STANZA = DctrlStanzaMetadata(
2712 "Source",
2713 SOURCE_FIELDS,
2714)
2715_DCTRL_PACKAGE_STANZA = DctrlStanzaMetadata("Package", BINARY_FIELDS)
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)
2730_DTESTSCTRL_STANZA = DTestsCtrlStanzaMetadata("Tests", _DTESTSCTRL_FIELDS)
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")
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")
2750 def stanza_types(self) -> Iterable[S]:
2751 yield _DEP5_HEADER_STANZA
2752 yield _DEP5_FILES_STANZA
2753 yield _DEP5_LICENSE_STANZA
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)
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")
2773 def stanza_types(self) -> Iterable[S]:
2774 yield _DCTRL_SOURCE_STANZA
2775 yield _DCTRL_PACKAGE_STANZA
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)
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")
2791 def stanza_types(self) -> Iterable[S]:
2792 yield _DTESTSCTRL_STANZA
2794 def __getitem__(self, item: str) -> S:
2795 if item == "Tests":
2796 return _DTESTSCTRL_STANZA
2797 raise KeyError(item)