trio-typing


Nametrio-typing JSON
Version 0.10.0 PyPI version JSON
download
home_pagehttps://github.com/python-trio/trio-typing
SummaryStatic type checking support for Trio and related projects
upload_time2023-12-01 02:54:55
maintainer
docs_urlNone
authorJoshua Oreman
requires_python
licenseMIT -or- Apache License 2.0
keywords async trio mypy
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            .. image:: https://img.shields.io/pypi/v/trio-typing.svg
   :target: https://pypi.org/project/trio-typing
   :alt: Latest PyPI version

.. image:: https://travis-ci.org/python-trio/trio-typing.svg?branch=master
   :target: https://travis-ci.org/python-trio/trio-typing
   :alt: Automated test status

.. image:: https://img.shields.io/badge/code%20style-black-000000.svg
   :target: https://github.com/ambv/black
   :alt: Code style: black

.. image:: http://www.mypy-lang.org/static/mypy_badge.svg
   :target: http://www.mypy-lang.org/
   :alt: Checked with mypy

trio-typing: static typing for Trio and related projects
========================================================

This repository provides:

* PEP 561 typing stubs packages for the Trio project packages:

  * `trio <https://github.com/python-trio/trio>`__ (``trio-stubs``)

  * `outcome <https://github.com/python-trio/outcome>`__ (``outcome-stubs``)

  * `async_generator <https://github.com/python-trio/async_generator>`__
    (``async_generator-stubs``)

* A package ``trio_typing`` containing types that Trio programs often want
  to refer to (``AsyncGenerator[Y, S]`` and ``TaskStatus[T]``)
  (``Nursery`` is exported publicly by mainline Trio as of version 0.12.0.)

* A mypy plugin that smooths over some limitations in the basic type hints.


Supported platforms
~~~~~~~~~~~~~~~~~~~

Like Trio, we require Python 3.7 or later. Both PyPy and CPython are
supported at runtime, but type checking must occur on CPython (due to
limitations of mypy).  We test on Linux using the latest releases
from the 3.7, 3.8, 3.9, and 3.10 branches. We're
not knowingly doing anything OS-specific, so other OSes should work
too.

Type checkers other than mypy are not supported, but might work.
Experience reports and patches to add support are welcome.


Quickstart
~~~~~~~~~~

runtime only
------------

Install with::

    pip install trio-typing

Then import some typing names from ``trio_typing``, like ``TaskStatus``;
see below for more details.


with mypy support
-----------------

Install trio-typing with mypy extras::

    pip install trio-typing[mypy]

Note that due to recent plugin API changes, trio-typing 0.10.0+ requires mypy 1.0+.

Enable the plugin in your ``mypy.ini``::

    [mypy]
    plugins = trio_typing.plugin

Start running mypy on your Trio code!

NOTE: ``trio-typing`` is the correct dependency to list in the requirements
  of your own library using the ``trio_typing`` module.  Don't use
  ``trio-typing[mypy]``, since that would needlessly add a mypy dependency to
  every app having a transitive dependency on your library.


What's in the box?
~~~~~~~~~~~~~~~~~~

The stubs packages provide types for all public non-deprecated APIs of
``trio``, ``outcome``, and ``async_generator``, as of the release date
of the corresponding ``trio-typing`` distribution. You don't need to
explicitly configure these; just say ``import trio`` (for example)
and mypy will know to look in ``trio-stubs`` for the type information.

The ``trio_typing`` package provides:

* ``TaskStatus[T]``, the type of the object passed as the ``task_status``
  argument to a task started with ``nursery.start()``. The type parameter
  ``T`` is the type of the value the task provides to be returned from
  ``nursery.start()``. This is implemented as an ABC, and the actual
  private types inside Trio are registered as virtual subclasses
  of it. So, you can't instantiate ``trio_typing.TaskStatus``, but
  ``isinstance(task_status, trio_typing.TaskStatus)`` where ``task_status``
  is a Trio task status object does return True.

* (Previous versions of ``trio_typing`` provided an analogous ABC for
  ``Nursery``, but the actual class is available as ``trio.Nursery`` as of
  Trio 0.12.0; you should use that instead.)

* A backport of ``typing.AsyncGenerator[YieldT, SendT]`` to Python 3.5.
  (``YieldT`` is the type of values yielded by the generator, and
  ``SendT`` is the type of values it accepts as an argument to ``asend()``.)
  This is an abstract class describing the async generator interface:
  ``AsyncIterator`` plus ``asend``, ``athrow``, ``aclose``, and the
  ``ag_*`` introspection attributes. On 3.6+, ``trio_typing.AsyncGenerator``
  is just a reexport of ``typing.AsyncGenerator``.

* ``CompatAsyncGenerator[YieldT, SendT, ReturnT]``,
  a name for the otherwise-anonymous concrete async generator type
  returned by ``@async_generator`` functions. It is a subtype of
  ``AsyncGenerator[YieldT, SendT]`` and provides the same methods.
  (Native async generators don't have a ``ReturnT``; it is only relevant
  in determining the return type of ``await async_generator.yield_from_()``.)

* A few types that are only useful with the mypy plugin: ``YieldType[T]``,
  ``SendType[T]``, and the decorator ``@takes_callable_and_args``.

The ``trio_typing.plugin`` mypy plugin provides:

* Inference of more specific ``trio.open_file()`` and ``trio.Path.open()``
  return types based on constant ``mode`` and ``buffering`` arguments, so
  ``await trio.open_file("foo", "rb", 0)`` returns an unbuffered async
  file object in binary mode and ``await trio.open_file("bar")`` returns
  an async file object in text mode

* Boilerplate reduction for functions that take parameters ``(fn, *args)``
  and ultimately invoke ``fn(*args)``: just write::

      from mypy_extensions import VarArg

      @trio_typing.takes_callable_and_args
      def start_soon(
          async_fn: Callable[[VarArg()], Awaitable[T]],
          *args: Any,
          other_keywords: str = are_ok_too,
      ):
          # your implementation here

  ``start_soon(async_fn, *args)`` will raise an error if ``async_fn(*args)``
  would do so. You can also make the callable take some non-splatted
  arguments; the ``*args`` get inserted at whatever position in the
  argument list you write ``VarArg()``.

  The above example will always fail when the plugin is not being
  used. If you want to always pass in such cases, you can use a union::

      @trio_typing.takes_callable_and_args
      def start_soon(
          async_fn: Union[
              Callable[..., Awaitable[T]],
              Callable[[VarArg()], Awaitable[T]],
          ],
          *args: Any,
          other_keywords: str = are_ok_too,
      ):
          # your implementation here

  Without the plugin, this type-checks fine (and allows inference of
  ``T``), since any callable will match the ``Callable[...,
  Awaitable[T]]`` option. With the plugin, the entire union will be
  replaced with specific argument types.

  Note: due to mypy limitations, we only support a maximum of 5
  positional arguments, and keyword arguments can't be passed in this way;
  ``nursery.start_soon(functools.partial(...))`` will pass the type checker
  but won't be able to actually check the argument types.

* Mostly-full support for type checking ``@async_generator`` functions.
  You write the decorated function as if it returned a union of its actual
  return type, its yield type wrapped in ``YieldType[]``, and its send
  type wrapped in ``SendType[]``::

      from trio_typing import YieldType, SendType
      @async_generator
      async def sleep_and_sqrt() -> Union[None, SendType[int], YieldType[float]]:
          next_yield = 0.0
          while True:
              amount = await yield_(next_yield)  # amount is an int
              if amount < 0:
                  return None
              await trio.sleep(amount)
              next_yield = math.sqrt(amount)

      # prints: CompatAsyncGenerator[float, int, None]
      reveal_type(sleep_and_sqrt())

  Calls to ``yield_`` and ``yield_from_`` inside an ``@async_generator``
  function are type-checked based on these declarations. If you leave
  off *either* the yield type or send type, the missing one is assumed
  to be ``None``; if you leave off *both* (writing just
  ``async def sleep_and_sqrt() -> None:``, like you would if you weren't
  using the plugin), they're both assumed to be ``Any``.

  Note the explicit ``return None``; mypy won't accept ``return`` or
  falling off the end of the function, unless you run it with
  ``--no-warn-no-return``.


Limitations
~~~~~~~~~~~

* Calls to variadic Trio functions like ``trio.run()``,
  ``nursery.start_soon()``, and so on, only can type-check up to five
  positional arguments. (This number could be increased easily, but
  only at the cost of slower typechecking for everyone; mypy's current
  architecture requires that we generate overload sets initially for
  every arity we want to be able to use.) You can work around this with
  a ``# type: ignore`` comment.

* ``outcome.capture()`` and ``outcome.acapture()`` currently don't typecheck
  their arguments at all.


Running the tests
~~~~~~~~~~~~~~~~~

``trio-typing`` comes with a fairly extensive testsuite; it doesn't test all
the mechanical parts of the stubs, but does exercise most of the interesting
plugin behavior. You can run it after installing, with::

    pytest -p trio_typing._tests.datadriven --pyargs trio_typing


License
~~~~~~~

Your choice of MIT or Apache 2.0.

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/python-trio/trio-typing",
    "name": "trio-typing",
    "maintainer": "",
    "docs_url": null,
    "requires_python": "",
    "maintainer_email": "",
    "keywords": "async,trio,mypy",
    "author": "Joshua Oreman",
    "author_email": "oremanj@gmail.com",
    "download_url": "https://files.pythonhosted.org/packages/b5/74/a87aafa40ec3a37089148b859892cbe2eef08d132c816d58a60459be5337/trio-typing-0.10.0.tar.gz",
    "platform": null,
    "description": ".. image:: https://img.shields.io/pypi/v/trio-typing.svg\n   :target: https://pypi.org/project/trio-typing\n   :alt: Latest PyPI version\n\n.. image:: https://travis-ci.org/python-trio/trio-typing.svg?branch=master\n   :target: https://travis-ci.org/python-trio/trio-typing\n   :alt: Automated test status\n\n.. image:: https://img.shields.io/badge/code%20style-black-000000.svg\n   :target: https://github.com/ambv/black\n   :alt: Code style: black\n\n.. image:: http://www.mypy-lang.org/static/mypy_badge.svg\n   :target: http://www.mypy-lang.org/\n   :alt: Checked with mypy\n\ntrio-typing: static typing for Trio and related projects\n========================================================\n\nThis repository provides:\n\n* PEP 561 typing stubs packages for the Trio project packages:\n\n  * `trio <https://github.com/python-trio/trio>`__ (``trio-stubs``)\n\n  * `outcome <https://github.com/python-trio/outcome>`__ (``outcome-stubs``)\n\n  * `async_generator <https://github.com/python-trio/async_generator>`__\n    (``async_generator-stubs``)\n\n* A package ``trio_typing`` containing types that Trio programs often want\n  to refer to (``AsyncGenerator[Y, S]`` and ``TaskStatus[T]``)\n  (``Nursery`` is exported publicly by mainline Trio as of version 0.12.0.)\n\n* A mypy plugin that smooths over some limitations in the basic type hints.\n\n\nSupported platforms\n~~~~~~~~~~~~~~~~~~~\n\nLike Trio, we require Python 3.7 or later. Both PyPy and CPython are\nsupported at runtime, but type checking must occur on CPython (due to\nlimitations of mypy).  We test on Linux using the latest releases\nfrom the 3.7, 3.8, 3.9, and 3.10 branches. We're\nnot knowingly doing anything OS-specific, so other OSes should work\ntoo.\n\nType checkers other than mypy are not supported, but might work.\nExperience reports and patches to add support are welcome.\n\n\nQuickstart\n~~~~~~~~~~\n\nruntime only\n------------\n\nInstall with::\n\n    pip install trio-typing\n\nThen import some typing names from ``trio_typing``, like ``TaskStatus``;\nsee below for more details.\n\n\nwith mypy support\n-----------------\n\nInstall trio-typing with mypy extras::\n\n    pip install trio-typing[mypy]\n\nNote that due to recent plugin API changes, trio-typing 0.10.0+ requires mypy 1.0+.\n\nEnable the plugin in your ``mypy.ini``::\n\n    [mypy]\n    plugins = trio_typing.plugin\n\nStart running mypy on your Trio code!\n\nNOTE: ``trio-typing`` is the correct dependency to list in the requirements\n  of your own library using the ``trio_typing`` module.  Don't use\n  ``trio-typing[mypy]``, since that would needlessly add a mypy dependency to\n  every app having a transitive dependency on your library.\n\n\nWhat's in the box?\n~~~~~~~~~~~~~~~~~~\n\nThe stubs packages provide types for all public non-deprecated APIs of\n``trio``, ``outcome``, and ``async_generator``, as of the release date\nof the corresponding ``trio-typing`` distribution. You don't need to\nexplicitly configure these; just say ``import trio`` (for example)\nand mypy will know to look in ``trio-stubs`` for the type information.\n\nThe ``trio_typing`` package provides:\n\n* ``TaskStatus[T]``, the type of the object passed as the ``task_status``\n  argument to a task started with ``nursery.start()``. The type parameter\n  ``T`` is the type of the value the task provides to be returned from\n  ``nursery.start()``. This is implemented as an ABC, and the actual\n  private types inside Trio are registered as virtual subclasses\n  of it. So, you can't instantiate ``trio_typing.TaskStatus``, but\n  ``isinstance(task_status, trio_typing.TaskStatus)`` where ``task_status``\n  is a Trio task status object does return True.\n\n* (Previous versions of ``trio_typing`` provided an analogous ABC for\n  ``Nursery``, but the actual class is available as ``trio.Nursery`` as of\n  Trio 0.12.0; you should use that instead.)\n\n* A backport of ``typing.AsyncGenerator[YieldT, SendT]`` to Python 3.5.\n  (``YieldT`` is the type of values yielded by the generator, and\n  ``SendT`` is the type of values it accepts as an argument to ``asend()``.)\n  This is an abstract class describing the async generator interface:\n  ``AsyncIterator`` plus ``asend``, ``athrow``, ``aclose``, and the\n  ``ag_*`` introspection attributes. On 3.6+, ``trio_typing.AsyncGenerator``\n  is just a reexport of ``typing.AsyncGenerator``.\n\n* ``CompatAsyncGenerator[YieldT, SendT, ReturnT]``,\n  a name for the otherwise-anonymous concrete async generator type\n  returned by ``@async_generator`` functions. It is a subtype of\n  ``AsyncGenerator[YieldT, SendT]`` and provides the same methods.\n  (Native async generators don't have a ``ReturnT``; it is only relevant\n  in determining the return type of ``await async_generator.yield_from_()``.)\n\n* A few types that are only useful with the mypy plugin: ``YieldType[T]``,\n  ``SendType[T]``, and the decorator ``@takes_callable_and_args``.\n\nThe ``trio_typing.plugin`` mypy plugin provides:\n\n* Inference of more specific ``trio.open_file()`` and ``trio.Path.open()``\n  return types based on constant ``mode`` and ``buffering`` arguments, so\n  ``await trio.open_file(\"foo\", \"rb\", 0)`` returns an unbuffered async\n  file object in binary mode and ``await trio.open_file(\"bar\")`` returns\n  an async file object in text mode\n\n* Boilerplate reduction for functions that take parameters ``(fn, *args)``\n  and ultimately invoke ``fn(*args)``: just write::\n\n      from mypy_extensions import VarArg\n\n      @trio_typing.takes_callable_and_args\n      def start_soon(\n          async_fn: Callable[[VarArg()], Awaitable[T]],\n          *args: Any,\n          other_keywords: str = are_ok_too,\n      ):\n          # your implementation here\n\n  ``start_soon(async_fn, *args)`` will raise an error if ``async_fn(*args)``\n  would do so. You can also make the callable take some non-splatted\n  arguments; the ``*args`` get inserted at whatever position in the\n  argument list you write ``VarArg()``.\n\n  The above example will always fail when the plugin is not being\n  used. If you want to always pass in such cases, you can use a union::\n\n      @trio_typing.takes_callable_and_args\n      def start_soon(\n          async_fn: Union[\n              Callable[..., Awaitable[T]],\n              Callable[[VarArg()], Awaitable[T]],\n          ],\n          *args: Any,\n          other_keywords: str = are_ok_too,\n      ):\n          # your implementation here\n\n  Without the plugin, this type-checks fine (and allows inference of\n  ``T``), since any callable will match the ``Callable[...,\n  Awaitable[T]]`` option. With the plugin, the entire union will be\n  replaced with specific argument types.\n\n  Note: due to mypy limitations, we only support a maximum of 5\n  positional arguments, and keyword arguments can't be passed in this way;\n  ``nursery.start_soon(functools.partial(...))`` will pass the type checker\n  but won't be able to actually check the argument types.\n\n* Mostly-full support for type checking ``@async_generator`` functions.\n  You write the decorated function as if it returned a union of its actual\n  return type, its yield type wrapped in ``YieldType[]``, and its send\n  type wrapped in ``SendType[]``::\n\n      from trio_typing import YieldType, SendType\n      @async_generator\n      async def sleep_and_sqrt() -> Union[None, SendType[int], YieldType[float]]:\n          next_yield = 0.0\n          while True:\n              amount = await yield_(next_yield)  # amount is an int\n              if amount < 0:\n                  return None\n              await trio.sleep(amount)\n              next_yield = math.sqrt(amount)\n\n      # prints: CompatAsyncGenerator[float, int, None]\n      reveal_type(sleep_and_sqrt())\n\n  Calls to ``yield_`` and ``yield_from_`` inside an ``@async_generator``\n  function are type-checked based on these declarations. If you leave\n  off *either* the yield type or send type, the missing one is assumed\n  to be ``None``; if you leave off *both* (writing just\n  ``async def sleep_and_sqrt() -> None:``, like you would if you weren't\n  using the plugin), they're both assumed to be ``Any``.\n\n  Note the explicit ``return None``; mypy won't accept ``return`` or\n  falling off the end of the function, unless you run it with\n  ``--no-warn-no-return``.\n\n\nLimitations\n~~~~~~~~~~~\n\n* Calls to variadic Trio functions like ``trio.run()``,\n  ``nursery.start_soon()``, and so on, only can type-check up to five\n  positional arguments. (This number could be increased easily, but\n  only at the cost of slower typechecking for everyone; mypy's current\n  architecture requires that we generate overload sets initially for\n  every arity we want to be able to use.) You can work around this with\n  a ``# type: ignore`` comment.\n\n* ``outcome.capture()`` and ``outcome.acapture()`` currently don't typecheck\n  their arguments at all.\n\n\nRunning the tests\n~~~~~~~~~~~~~~~~~\n\n``trio-typing`` comes with a fairly extensive testsuite; it doesn't test all\nthe mechanical parts of the stubs, but does exercise most of the interesting\nplugin behavior. You can run it after installing, with::\n\n    pytest -p trio_typing._tests.datadriven --pyargs trio_typing\n\n\nLicense\n~~~~~~~\n\nYour choice of MIT or Apache 2.0.\n",
    "bugtrack_url": null,
    "license": "MIT -or- Apache License 2.0",
    "summary": "Static type checking support for Trio and related projects",
    "version": "0.10.0",
    "project_urls": {
        "Homepage": "https://github.com/python-trio/trio-typing"
    },
    "split_keywords": [
        "async",
        "trio",
        "mypy"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "89ff9bd795273eb14fac7f6a59d16cc8c4d0948a619a1193d375437c7f50f3eb",
                "md5": "7afb726255a1f7fcc015a82ed2303eb1",
                "sha256": "6d0e7ec9d837a2fe03591031a172533fbf4a1a95baf369edebfc51d5a49f0264"
            },
            "downloads": -1,
            "filename": "trio_typing-0.10.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "7afb726255a1f7fcc015a82ed2303eb1",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": null,
            "size": 42224,
            "upload_time": "2023-12-01T02:54:54",
            "upload_time_iso_8601": "2023-12-01T02:54:54.100710Z",
            "url": "https://files.pythonhosted.org/packages/89/ff/9bd795273eb14fac7f6a59d16cc8c4d0948a619a1193d375437c7f50f3eb/trio_typing-0.10.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "b574a87aafa40ec3a37089148b859892cbe2eef08d132c816d58a60459be5337",
                "md5": "3eee8f78cb0cfa6bbf66d53b7e8f9b9b",
                "sha256": "065ee684296d52a8ab0e2374666301aec36ee5747ac0e7a61f230250f8907ac3"
            },
            "downloads": -1,
            "filename": "trio-typing-0.10.0.tar.gz",
            "has_sig": false,
            "md5_digest": "3eee8f78cb0cfa6bbf66d53b7e8f9b9b",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": null,
            "size": 38747,
            "upload_time": "2023-12-01T02:54:55",
            "upload_time_iso_8601": "2023-12-01T02:54:55.508179Z",
            "url": "https://files.pythonhosted.org/packages/b5/74/a87aafa40ec3a37089148b859892cbe2eef08d132c816d58a60459be5337/trio-typing-0.10.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-12-01 02:54:55",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "python-trio",
    "github_project": "trio-typing",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "trio-typing"
}
        
Elapsed time: 0.15119s