conda-forge / conda-smithy

The tool for managing conda-forge feedstocks.
https://conda-forge.org/
BSD 3-Clause "New" or "Revised" License
152 stars 183 forks source link

Linting `conda-forge.yml` does not diagnose (some) schema violations #2152

Open h-vetinari opened 2 days ago

h-vetinari commented 2 days ago

The following file as conda-forge.yml yields a clean slate from the linter

build_platform:
  wrong: a
os_version:
  wrong: b
provider:
  wrong: c

despite the fact that, based on schema.py (or at least the obvious intent there), it should fail: https://github.com/conda-forge/conda-smithy/blob/2b18d8dd41de178e30506e420022b2a5590a4acf/conda_smithy/schema.py#L548-L563

All three of those are using pydantic's create_model, which I presume is not working as intended here.

h-vetinari commented 2 days ago

With an addition of ConfigDict(extra='forbid'), I can get the following

from conda.base.constants import KNOWN_SUBDIRS
from pydantic import ConfigDict, Field, create_model
from enum import StrEnum

dirs = [subdir.replace("-", "_") for subdir in KNOWN_SUBDIRS if "-" in subdir]
Platforms = StrEnum("Platforms", dirs)

BuildPlatform = create_model(
    "build_platform",
    __config__=ConfigDict(extra='forbid'),
    **{
        platform.value: (Platforms, Field(default=platform.value))
        for platform in Platforms
    },
)

to yield

>>> BuildPlatform(wrong="linux_64")
pydantic_core._pydantic_core.ValidationError: 1 validation error for build_platform
wrong
  Extra inputs are not permitted [type=extra_forbidden, input_value='linux_64', input_type=str]
    For further information visit https://errors.pydantic.dev/2.9/v/extra_forbidden

However, if I add ConfigDict(extra='forbid') to schema.py and lint an affected recipe, nothing triggers. 🤔

h-vetinari commented 1 day ago

I found that the work for this has already been done by @ytausch in #1920. I merged main in that PR and verified that it correctly diagnoses wrong values (as hints), and with a pretty nice message too:

recipe has some suggestions:
  Unexpected key build_platform.wrong
  Unexpected key os_version.wrong
  Unexpected key provider.wrong