diff --git a/adopt-project.py b/adopt-project.py index a8b1ef34..86dd27b4 100755 --- a/adopt-project.py +++ b/adopt-project.py @@ -278,9 +278,8 @@ # into its manifest, and whether a repository's name can be a directory's: # asked of the plan's values by `plan`, `check` and `execute` (#261). from shape_materialize import ( # noqa: E402 - KIND_UNREADABLE, MANIFEST_INVALID_REMEDIATION, - MANIFEST_UNREADABLE_REMEDIATION, manifest_judged, manifest_value_problems, - refuse_manifest_values, refuse_unstorable_names, + KIND_NOT_A_MAPPING, PROJECT_MANIFEST, manifest_judged, + manifest_value_problems, refuse_manifest_values, refuse_unstorable_names, ) # What GitHub keeps a repository's name, a topic and an organisation's name # to, asked by `execute` before either leg exists where GitHub is (#838). @@ -5581,6 +5580,12 @@ def _manifest_findings(plan: Plan) -> tuple[list[str], list[str]]: what was read (`_named_as_read`), because the sentence goes on to quote `str` of it, the text `execute` would write and not what the plan says. + + A MANIFEST THE READER MAKES NO MAPPING OF is one finding about no value + (`KIND_NOT_A_MAPPING`, #1059): its remedy is the one for a defect of the + copy of the standard, which `PROJECT_MANIFEST.remediations` gives the + kind, and it has no sentence about the plan's values, none of which is + at fault. """ naming = NamingPolicy.load(NAMING_POLICY) values = _manifest_values(plan, naming) @@ -5591,17 +5596,21 @@ def _manifest_findings(plan: Plan) -> tuple[list[str], list[str]]: ignore=_validator_ignores(plan)) if not problems: return [], [] - # Where the project's own YAML reader refuses the manifest, the words - # are the reader's, and so is the remedy (#708). - remedy = (MANIFEST_UNREADABLE_REMEDIATION - if problems[0][0] == KIND_UNREADABLE - else MANIFEST_INVALID_REMEDIATION) + # The remedy is the kind's own: where the project's own YAML reader + # refuses the manifest, the words are the reader's, and so is the remedy + # (#708); where it reads the template's manifest as something other than + # a mapping, no value is at fault and only the template is, so the remedy + # is the defect-of-the-standard one and the sentence about the plan's + # values is left out (#1059). + kind = problems[0][0] + values_tail = ( + "" if kind == KIND_NOT_A_MAPPING + else " `execute` writes the plan's values into the project's " + "`project.yaml` as they stand, so correct each one named here in " + "the plan, or re-run `plan` with a value the validator accepts.") return ([f"FINDING plan-manifest-invalid: {sentence}" for _, sentence in problems], - [f"{remedy} `execute` writes the plan's " - "values into the project's `project.yaml` as they stand, so " - "correct each one named here in the plan, or re-run `plan` with " - "a value the validator accepts."]) + [f"{PROJECT_MANIFEST.remediations[kind]}{values_tail}"]) def _validator_judged(plan: Plan) -> frozenset[str] | None: diff --git a/scripts/family.py b/scripts/family.py index 82270793..b6d75c30 100755 --- a/scripts/family.py +++ b/scripts/family.py @@ -197,9 +197,10 @@ # `project.yaml`, asked of `family.yaml` (#925), and the first sentence of # the remedy where the holder's reader refuses it (#929). from shape_materialize import ( # noqa: E402 - FAMILY_TEMPLATED, KIND_INVALID, KIND_MISREAD, KIND_UNREADABLE, - UNREADABLE_CHOICE, TemplateManifest, manifest_invalid, manifest_misreads, - manifest_validator, manifest_value_problems, refuse_manifest_problems, + FAMILY_TEMPLATED, KIND_INVALID, KIND_MISREAD, KIND_NOT_A_MAPPING, + KIND_UNREADABLE, UNREADABLE_CHOICE, TemplateManifest, manifest_invalid, + manifest_misreads, manifest_not_a_mapping_remediation, manifest_validator, + manifest_value_problems, refuse_manifest_problems, ) # How every command this prints for a person to paste spells its paths # (#486), the quoting the holder's `scripts/siblings.py` uses too. @@ -3554,10 +3555,17 @@ def _print_next_steps(args, work: Path, folder: Path | None) -> None: "red from its first commit, because `make validate` and the `validate` " "workflow run that validator first, and `init` cannot be run again over " "a pushed holder: there is no --force.") +#: Where the holder's own reader reads the template's `family.yaml` as +#: something other than a mapping (#1059), no value `init` is handed did it, +#: so the remedy is the defect of the standard, aimed at that file, and it +#: is the project's sentence (`shape_materialize`), said of the holder's. +MANIFEST_NOT_A_MAPPING_REMEDIATION = manifest_not_a_mapping_remediation( + "family-root", MANIFEST, "the holder's own YAML reader") #: The remedy for each kind of problem the questions name. KIND_REMEDIATIONS = {KIND_MISREAD: MANIFEST_MISREAD_REMEDIATION, KIND_INVALID: MANIFEST_INVALID_REMEDIATION, - KIND_UNREADABLE: MANIFEST_UNREADABLE_REMEDIATION} + KIND_UNREADABLE: MANIFEST_UNREADABLE_REMEDIATION, + KIND_NOT_A_MAPPING: MANIFEST_NOT_A_MAPPING_REMEDIATION} def _holder_findings(validator, manifest: dict, policy: NamingPolicy): diff --git a/scripts/shape_materialize.py b/scripts/shape_materialize.py index d7f897cb..e55f092c 100644 --- a/scripts/shape_materialize.py +++ b/scripts/shape_materialize.py @@ -5038,11 +5038,13 @@ def _placeholders_of(line: str) -> list[str]: #: The kinds of problem `manifest_value_problems` names, each spelled once #: (#708): a value the project's reader reads back as something else, one -#: its validator refuses, and a manifest the reader refuses before the -#: validator can be asked, which `refuse_manifest_values` refuses under the +#: its validator refuses, a manifest the reader refuses before the validator +#: can be asked, and a manifest the reader reads as something other than a +#: mapping (#1059), which no value a person types can make (only a broken +#: template does). `refuse_manifest_values` refuses the last three under the #: code `invalid` still. -KIND_MISREAD, KIND_INVALID, KIND_UNREADABLE = ( - "misread", "invalid", "unreadable") +KIND_MISREAD, KIND_INVALID, KIND_UNREADABLE, KIND_NOT_A_MAPPING = ( + "misread", "invalid", "unreadable", "not-a-mapping") #: The remediation, without the sentence only the caller can write (what was #: or was not created, whether `--dry-run` refuses the same). @@ -5087,11 +5089,38 @@ def _placeholders_of(line: str) -> list[str]: "which refuses the manifest this run would write before its " "validate-manifest.py can be asked, and a project whose manifest it " "refuses is one whose first bootstrap would fail.") + + +def manifest_not_a_mapping_remediation(template: str, manifest: str, + reader: str) -> str: + """The remedy where the template's own manifest is not a mapping to its + reader (#1059), for the manifest `manifest` in `templates/