Skip to content

Generated Python models report optional fields as required in pyright/Pylance #394

Description

@fernandezcuesta

What happened?

The Python models that crossplane dependency update-cache (and crossplane project build) generate have many optional fields that type checkers report as required.

datamodel-code-generator writes the default of a field as a positional argument of Field when the field also has other arguments:

continue_: str | None = Field(None, alias='continue')
metadata: v1.ObjectMeta | None = Field({}, validate_default=True)

Pyright (and so Pylance, the default Python language server of VS Code) reads a default only from the default= keyword. It reports each of these fields as a required argument:

from models.io.k8s.api.apps.v1 import Deployment, DeploymentSpec
from models.io.k8s.api.core.v1 import PodTemplateSpec
from models.io.k8s.api.networking.v1 import IPBlock, NetworkPolicyIngressRule
from models.io.k8s.apimachinery.pkg.apis.core.meta.v1 import LabelSelector, ListMeta

Deployment()
DeploymentSpec(selector=LabelSelector(), template=PodTemplateSpec())
IPBlock(cidr="10.0.0.0/8")
NetworkPolicyIngressRule()
ListMeta()
t.py:6:1 - error: Arguments missing for parameters "metadata", "spec", "status" (reportCallIssue)
t.py:7:1 - error: Argument missing for parameter "strategy" (reportCallIssue)
t.py:7:51 - error: Arguments missing for parameters "metadata", "spec" (reportCallIssue)
t.py:8:1 - error: Argument missing for parameter "except" (reportCallIssue)
t.py:9:1 - error: Argument missing for parameter "from" (reportCallIssue)
t.py:10:1 - error: Argument missing for parameter "continue" (reportCallIssue)
6 errors, 0 warnings, 0 informations

Pydantic itself accepts these calls, because the defaults are correct at runtime. Only static type checks fail. In the Kubernetes v1.36.4 core API models, 146 fields use Field({}, ...), plus the fields renamed from Python keywords (continue_, except_, from_, and int_/bool_ since #63).

Expected: no errors. The fields have a default, so they are optional.

How can we reproduce it?

cat > crossplane-project.yaml <<'EOF'
apiVersion: dev.crossplane.io/v1alpha1
kind: Project
metadata:
  name: repro
spec:
  repository: example.com/repro
  schemas:
    languages: [python]
  dependencies:
    - type: k8s
      k8s:
        version: v1.36.4
EOF
crossplane dependency update-cache
grep -rn "Field(None, alias=\|Field({}" schemas/python/models | head

Then run pyright on the snippet above with schemas/python on the Python path (for example pyrightconfig.json with "extraPaths": ["schemas/python"]).

What environment did it happen in?

  • Crossplane CLI version: v2.5.0
  • Platform (e.g., linux/amd64): linux/amd64
  • Crossplane version (if applicable): n/a
  • datamodel-code-generator: 0.59.0 (pinned by the CLI), pyright 1.1.406, pydantic 2

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions