Skip to content

--verifytypes --ignoreexternal reports public parameter as partially unknown with conditional optional-dependency alias #11277

@tamird

Description

@tamird

Context

I'm trying to increase the strictness of types in pyJWT but have failed to find a way to express the optional dependency on cryptography. Below is a description of the bug and a minimized reproduction produced with the help of an LLM.

Describe the bug

In a typed package with an optional dependency, a public API parameter annotated with a package-local alias is reported as partially unknown:

  • Parameter type is "Unknown | str | bytes"

In this repro, the public function is annotated as AllowedPublicKeys | str | bytes, where AllowedPublicKeys is imported from another module in the same package.

Repro

pkg/algorithms.py

from __future__ import annotations

from typing_extensions import Never

AllowedPublicKeys = Never

try:
    from cryptography.hazmat.primitives.asymmetric.rsa import RSAPublicKey

    AllowedPublicKeys = RSAPublicKey
except ImportError:
    AllowedPublicKeys = Never

pkg/api.py

from __future__ import annotations

from .algorithms import AllowedPublicKeys


def decode(key: AllowedPublicKeys | str | bytes) -> None:
    return None

pkg/__init__.py

from .api import decode as decode

pkg/py.typed (empty file)

pyproject.toml

[build-system]
requires = ["setuptools>=69"]
build-backend = "setuptools.build_meta"

[project]
name = "pkg"
version = "0.0.1"
requires-python = ">=3.9"

[tool.setuptools]
packages = ["pkg"]

[tool.setuptools.package-data]
pkg = ["py.typed"]

Commands

python3 -m venv .venv
. .venv/bin/activate
python -m ensurepip --upgrade
python -m pip install -U pip
python -m pip install pyright .
pyright --version
pyright --verifytypes pkg --ignoreexternal

Actual output

On pyright 1.1.408:

pkg.decode
  .../pkg/api.py:1:28 - error: Type of parameter "key" is partially unknown
    Parameter type is "Unknown | str | bytes"

pkg.algorithms.AllowedPublicKeys is also reported as unknown/ambiguous.

Question / requested guidance

Could you clarify the recommended way to express this optional-dependency
pattern so --verifytypes --ignoreexternal can validate the public API
cleanly?

If this conditional alias approach is not the intended pattern, guidance on
the preferred alternative for typed libraries with optional dependencies would
be very helpful.

Environment

  • pyright: 1.1.408
  • Python: 3.12.12
  • Platform: macOS (Darwin)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions