{"id":980,"library":"eval-type-backport","title":"eval-type-backport","description":"Like `typing._eval_type`, this tiny package provides a replacement to support newer typing features (such as `X | Y` for unions from PEP 604 and `list[X]` for generic built-ins from PEP 585) in older Python versions (>=3.7). It allows libraries like Pydantic to maintain modern type hint syntax while supporting a wider range of Python environments. It is currently at version 0.3.1 and sees updates as needed for compatibility.","status":"active","version":"0.3.1","language":"python","source_language":"en","source_url":"https://github.com/alexmojaki/eval_type_backport","tags":["typing","backport","type-hints","compatibility","python-versions","pydantic"],"install":[{"cmd":"pip install eval-type-backport","lang":"bash","label":"Install from PyPI"}],"dependencies":[{"reason":"Requires Python 3.7 or newer to run.","package":"python","optional":false},{"reason":"Used for running tests, not a runtime dependency.","package":"pytest","optional":true}],"imports":[{"note":"The package provides a single function, not typically imported as the top-level package.","wrong":"import eval_type_backport","symbol":"eval_type_backport","correct":"from eval_type_backport import eval_type_backport"}],"quickstart":{"code":"import sys\nfrom __future__ import annotations\n\nfrom eval_type_backport import eval_type_backport\n\nclass MyModel:\n    field: str | None\n\ndef demonstrate_eval(cls):\n    # Simulate a scenario where `str | None` might not be directly evaluable\n    # e.g., on Python < 3.10 without __future__.annotations, or in certain contexts.\n    # The backport ensures it resolves to typing.Union[str, None].\n    # For this example, we're just showing the direct usage of the function.\n    \n    # Get the annotation for 'field'\n    annotation = cls.__annotations__['field']\n    \n    # Evaluate it using the backport function\n    evaluated_type = eval_type_backport(annotation, globalns=sys.modules[__name__].__dict__, localns={})\n    \n    print(f\"Original annotation: {annotation!r}\")\n    print(f\"Evaluated type: {evaluated_type!r}\")\n\nif __name__ == \"__main__\":\n    demonstrate_eval(MyModel)\n","lang":"python","description":"This quickstart demonstrates how to use `eval_type_backport` to resolve a modern type hint like `str | None`. This function is typically used internally by other libraries (like Pydantic) to provide compatibility for newer Python typing features on older Python versions. The `globalns` and `localns` arguments provide the context for evaluating the type string, similar to `eval()`."},"warnings":[{"fix":"Consider if you truly need to evaluate types at runtime for compatibility; often, simply upgrading your Python version or using `typing.Union`/`typing.List` directly is more appropriate for application code.","message":"This library is primarily intended for use by other libraries (e.g., Pydantic) that need to evaluate type annotations at runtime for compatibility with modern Python typing features on older Python versions. Direct usage by end-user applications is generally rare unless you have a specific, advanced use case mirroring `typing._eval_type`.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Install `eval-type-backport` and ensure libraries evaluating your type hints are configured to use it, or explicitly use older `typing` constructs (e.g., `typing.Union[X, Y]`, `typing.List[X]`), or upgrade to a Python version that natively supports these features.","message":"If you are using modern type hint syntax (e.g., `X | Y` for unions, `list[X]` for generic built-ins) in a project targeting Python <3.10 or <3.9 respectively, you may encounter `TypeError` or `ImportError` at runtime. `eval-type-backport` provides the mechanism to resolve these types dynamically.","severity":"breaking","affected_versions":"<3.10 for `X | Y` syntax; <3.9 for `list[X]` (PEP 585) syntax"},{"fix":"Upgrade your project's Python version to 3.10 or newer to remove the need for this backport for common modern syntax.","message":"While `eval-type-backport` provides a compatibility layer, the recommended long-term solution for leveraging modern Python typing features is to upgrade your Python interpreter. Python 3.9+ natively supports generic built-in types (e.g., `list[int]`), and Python 3.10+ natively supports the `X | Y` union syntax.","severity":"gotcha","affected_versions":"Python 3.7-3.9 (for generic built-ins), Python 3.7-3.9 (for `X | Y`)"},{"fix":"Ensure `from __future__ import annotations` is the absolute first executable statement in your Python script, immediately after the shebang (if present) and encoding declaration (if present), and before any other code or comments.","message":"A `SyntaxError` regarding `from __future__ import annotations` indicates that this import statement was not placed at the very beginning of the script. While often used in conjunction with modern type hints that `eval-type-backport` helps to resolve, this error is a basic Python syntax requirement independent of the library's functionality.","severity":"breaking","affected_versions":"All Python versions"}],"env_vars":null,"last_verified":"2026-05-12T22:05:07.866Z","next_check":"2026-06-27T00:00:00.000Z","problems":[{"fix":"Install the `eval-type-backport` package: `pip install eval-type-backport`. Ensure any libraries that rely on it (like Pydantic) are also updated to versions that correctly leverage this backport. Alternatively, manually replace `X | Y` with `typing.Union[X, Y]` and `list[X]` with `typing.List[X]` in your code.","cause":"This error arises when running Python code with modern type hint syntax (like `X | Y` for unions or `list[X]` for generic built-ins) on older Python versions (e.g., Python < 3.10 for union operator, Python < 3.9 for generic built-ins) without `eval-type-backport` installed or properly utilized by a dependent library like Pydantic, causing Python's runtime to fail evaluating the unsupported syntax.","error":"TypeError: You have a type annotation 'bool | None' which makes use of newer typing features than are supported in your version of Python."},{"fix":"Upgrade `eval-type-backport` to its latest version (`pip install --upgrade eval-type-backport`) to ensure you have the most recent compatibility fixes. If the problem persists, ensure `ClassVar` is explicitly typed (e.g., `MY_CLASS_CONSTANT: ClassVar[int] = 5`) as some contexts might require clearer annotations for evaluation.","cause":"This specific `TypeError` occurs when a library, such as Pydantic, attempts to evaluate a `ClassVar` type annotation in a Python environment where `eval-type-backport` either doesn't have the necessary logic to backport `ClassVar` evaluation for that Python version, or an older version of `eval-type-backport` is in use.","error":"TypeError: Unable to evaluate type annotation 'ClassVar'."},{"fix":"Install the package using pip: `pip install eval-type-backport`. Verify that you are running Python from the correct environment (e.g., a virtual environment) where the package was installed.","cause":"The Python interpreter cannot find the `eval_type_backport` package because it has not been installed in the active Python environment, or there is a typo in the import statement.","error":"ModuleNotFoundError: No module named 'eval_type_backport'"}],"ecosystem":"pypi","meta_description":null,"install_score":100,"install_tag":"verified","quickstart_score":null,"quickstart_tag":null,"pypi_latest":"0.3.1","cli_name":"","install_checks":{"last_tested":"2026-05-12","tag":"verified","tag_description":"installs cleanly on critical runtimes, fast import, recently tested","results":[{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":0.03,"mem_mb":1.5,"disk_size":"17.8M"},{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.03,"mem_mb":1.5,"disk_size":"17.8M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":1.4,"import_time_s":0.02,"mem_mb":1.5,"disk_size":"18M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.02,"mem_mb":1.5,"disk_size":"18M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":0.03,"mem_mb":1.3,"disk_size":"19.6M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.04,"mem_mb":1.3,"disk_size":"19.6M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":1.5,"import_time_s":0.03,"mem_mb":1.3,"disk_size":"20M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.03,"mem_mb":1.3,"disk_size":"20M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":0.02,"mem_mb":1,"disk_size":"11.5M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.02,"mem_mb":1,"disk_size":"11.5M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":1.4,"import_time_s":0.02,"mem_mb":1,"disk_size":"12M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.02,"mem_mb":1,"disk_size":"12M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":0.02,"mem_mb":1.1,"disk_size":"11.3M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.02,"mem_mb":1.1,"disk_size":"11.2M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":1.4,"import_time_s":0.02,"mem_mb":0.9,"disk_size":"12M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.02,"mem_mb":0.9,"disk_size":"12M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":0.02,"mem_mb":1.4,"disk_size":"17.3M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.03,"mem_mb":1.4,"disk_size":"17.3M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":1.7,"import_time_s":0.02,"mem_mb":1.4,"disk_size":"18M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.02,"mem_mb":1.4,"disk_size":"18M"}]},"quickstart_checks":{"last_tested":"2026-04-24","tag":null,"tag_description":null,"results":[{"runtime":"python:3.10-alpine","exit_code":1},{"runtime":"python:3.10-slim","exit_code":1},{"runtime":"python:3.11-alpine","exit_code":1},{"runtime":"python:3.11-slim","exit_code":1},{"runtime":"python:3.12-alpine","exit_code":1},{"runtime":"python:3.12-slim","exit_code":1},{"runtime":"python:3.13-alpine","exit_code":1},{"runtime":"python:3.13-slim","exit_code":1},{"runtime":"python:3.9-alpine","exit_code":1},{"runtime":"python:3.9-slim","exit_code":1}]}}