mode-streaming


Namemode-streaming JSON
Version 0.4.1 PyPI version JSON
download
home_pageNone
SummaryAsyncIO Service-based programming
upload_time2024-04-15 13:28:26
maintainerNone
docs_urlNone
authorNone
requires_python>=3.8
licenseNone
keywords asyncio service bootsteps graph coroutine
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # AsyncIO Services Fork

![python versions](https://img.shields.io/pypi/pyversions/mode-streaming.svg)
![implementation](https://img.shields.io/pypi/implementation/mode-streaming)
![version](https://img.shields.io/pypi/v/mode-streaming)
![license](https://img.shields.io/pypi/l/mode-streaming)
![downloads](https://img.shields.io/pypi/dw/mode-streaming)


---

**Documentation**: <a href="https://faust-streaming.github.io/mode/" target="_blank">https://faust-streaming.github.io/mode/</a>

**Source Code**: <a href="https://github.com/faust-streaming/mode" target="_blank">https://github.com/faust-streaming/mode</a>

---

## Why the fork

We have decided to fork the original *Mode* project because there is a critical process of releasing new versions which causes uncertainty in the community. Everybody is welcome to contribute to this *fork*, and you can be added as a maintainer.

We want to:

- Ensure continues release
- Code quality
- Support latest Python versions
- Update the documentation

and more...

## What is Mode?

Mode is a very minimal Python library built-on top of AsyncIO that makes
it much easier to use.

In Mode your program is built out of services that you can start, stop,
restart and supervise.

A service is just a class:

```python
class PageViewCache(Service):
    redis: Redis = None

    async def on_start(self) -> None:
        self.redis = connect_to_redis()

    async def update(self, url: str, n: int = 1) -> int:
        return await self.redis.incr(url, n)

    async def get(self, url: str) -> int:
        return await self.redis.get(url)
```

Services are started, stopped and restarted and have
callbacks for those actions.

It can start another service:

```python
class App(Service):
    page_view_cache: PageViewCache = None

    async def on_start(self) -> None:
        await self.add_runtime_dependency(self.page_view_cache)

    @cached_property
    def page_view_cache(self) -> PageViewCache:
        return PageViewCache()
```

It can include background tasks:

```python
class PageViewCache(Service):

    @Service.timer(1.0)
    async def _update_cache(self) -> None:
        self.data = await cache.get('key')
```

Services that depends on other services actually form a graph
that you can visualize.

### Worker

Mode optionally provides a worker that you can use to start the program,
with support for logging, blocking detection, remote debugging and more.

To start a worker add this to your program:


```python
if __name__ == '__main__':
    from mode import Worker
    Worker(Service(), loglevel="info").execute_from_commandline()
```

Then execute your program to start the worker:

```log
$ python examples/tutorial.py
[2018-03-27 15:47:12,159: INFO]: [^Worker]: Starting...
[2018-03-27 15:47:12,160: INFO]: [^-AppService]: Starting...
[2018-03-27 15:47:12,160: INFO]: [^--Websockets]: Starting...
STARTING WEBSOCKET SERVER
[2018-03-27 15:47:12,161: INFO]: [^--UserCache]: Starting...
[2018-03-27 15:47:12,161: INFO]: [^--Webserver]: Starting...
[2018-03-27 15:47:12,164: INFO]: [^--Webserver]: Serving on port 8000
REMOVING EXPIRED USERS
REMOVING EXPIRED USERS
```

To stop it hit `Control-c`:

```log
[2018-03-27 15:55:08,084: INFO]: [^Worker]: Stopping on signal received...
[2018-03-27 15:55:08,084: INFO]: [^Worker]: Stopping...
[2018-03-27 15:55:08,084: INFO]: [^-AppService]: Stopping...
[2018-03-27 15:55:08,084: INFO]: [^--UserCache]: Stopping...
REMOVING EXPIRED USERS
[2018-03-27 15:55:08,085: INFO]: [^Worker]: Gathering service tasks...
[2018-03-27 15:55:08,085: INFO]: [^--UserCache]: -Stopped!
[2018-03-27 15:55:08,085: INFO]: [^--Webserver]: Stopping...
[2018-03-27 15:55:08,085: INFO]: [^Worker]: Gathering all futures...
[2018-03-27 15:55:08,085: INFO]: [^--Webserver]: Closing server
[2018-03-27 15:55:08,086: INFO]: [^--Webserver]: Waiting for server to close handle
[2018-03-27 15:55:08,086: INFO]: [^--Webserver]: Shutting down web application
[2018-03-27 15:55:08,086: INFO]: [^--Webserver]: Waiting for handler to shut down
[2018-03-27 15:55:08,086: INFO]: [^--Webserver]: Cleanup
[2018-03-27 15:55:08,086: INFO]: [^--Webserver]: -Stopped!
[2018-03-27 15:55:08,086: INFO]: [^--Websockets]: Stopping...
[2018-03-27 15:55:08,086: INFO]: [^--Websockets]: -Stopped!
[2018-03-27 15:55:08,087: INFO]: [^-AppService]: -Stopped!
[2018-03-27 15:55:08,087: INFO]: [^Worker]: -Stopped!
```

### Beacons

The `beacon` object that we pass to services keeps track of the services
in a graph.

They are not strictly required, but can be used to visualize a running
system, for example we can render it as a pretty graph.

This requires you to have the `pydot` library and GraphViz
installed:

```sh
$ pip install pydot
```

Let's change the app service class to dump the graph to an image
at startup:

```python
class AppService(Service):

    async def on_start(self) -> None:
        print('APP STARTING')
        import pydot
        import io
        o = io.StringIO()
        beacon = self.app.beacon.root or self.app.beacon
        beacon.as_graph().to_dot(o)
        graph, = pydot.graph_from_dot_data(o.getvalue())
        print('WRITING GRAPH TO image.png')
        with open('image.png', 'wb') as fh:
            fh.write(graph.create_png())
```

## Creating a Service

To define a service, simply subclass and fill in the methods
to do stuff as the service is started/stopped etc.:


```python
class MyService(Service):

    async def on_start(self) -> None:
        print('Im starting now')

    async def on_started(self) -> None:
        print('Im ready')

    async def on_stop(self) -> None:
        print('Im stopping now')
```

To start the service, call `await service.start()`:

```python
await service.start()
```

Or you can use `mode.Worker` (or a subclass of this) to start your
services-based asyncio program from the console:

```python
if __name__ == '__main__':
    import mode
    worker = mode.Worker(
        MyService(),
        loglevel='INFO',
        logfile=None,
        daemon=False,
    )
    worker.execute_from_commandline()
```

## It's a Graph!

Services can start other services, coroutines, and background tasks.

1) Starting other services using `add_dependency`:

```python
class MyService(Service):
    def __post_init__(self) -> None:
        self.add_dependency(OtherService(loop=self.loop))
```

1) Start a list of services using `on_init_dependencies`:

```python
class MyService(Service):

    def on_init_dependencies(self) -> None:
        return [
            ServiceA(loop=self.loop),
            ServiceB(loop=self.loop),
            ServiceC(loop=self.loop),
        ]
```

1) Start a future/coroutine (that will be waited on to complete on stop):

```python
class MyService(Service):

    async def on_start(self) -> None:
        self.add_future(self.my_coro())

    async def my_coro(self) -> None:
        print('Executing coroutine')
```

1) Start a background task:

```python
class MyService(Service):

    @Service.task
    async def _my_coro(self) -> None:
        print('Executing coroutine')
```

1) Start a background task that keeps running:

```python
class MyService(Service):

    @Service.task
    async def _my_coro(self) -> None:
        while not self.should_stop:
            # NOTE: self.sleep will wait for one second, or
            #       until service stopped/crashed.
            await self.sleep(1.0)
            print('Background thread waking up')
```

## Installation

You can install Mode either via the Python Package Index (PyPI)
or from source.

To install using `pip`:

```sh
$ pip install -U mode-streaming
```

Downloading and installing from source: http://pypi.org/project/mode-streaming

You can install it by doing the following:

```sh
$ tar xvfz mode-streaming-0.2.1.tar.gz
$ cd mode-0.2.1
$ python -m build .
# python install
```

The last command must be executed as a privileged user if
you are not currently using a virtualenv.


Using the development version:

With pip:

You can install the latest snapshot of Mode using the following
pip command:

```sh
$ pip install mode-streaming
```

## Developing

The guideline and associated information are stored in [CONTRIBUTING.md](./CONTRIBUTING.md)

## FAQ

#### Can I use Mode with Django/Flask/etc.?

Yes! Use gevent/eventlet as a bridge to integrate with asyncio.

Using `gevent`:

This works with any blocking Python library that can work with gevent.

Using gevent requires you to install the `aiogevent` module,
and you can install this as a bundle with Mode:

```sh
$ pip install -U mode-streaming[gevent]
```

Then to actually use gevent as the event loop you have to
execute the following in your entrypoint module (usually where you
start the worker), before any other third party libraries are imported:


```python
#!/usr/bin/env python3
import mode.loop
mode.loop.use('gevent')
# execute program
```

REMEMBER: This must be located at the very top of the module,
in such a way that it executes before you import other libraries.


Using `eventlet`:

This works with any blocking Python library that can work with eventlet.

Using eventlet requires you to install the `aioeventlet` module,
and you can install this as a bundle with Mode:

```sh
$ pip install -U mode-streaming[eventlet]
```

Then to actually use eventlet as the event loop you have to
execute the following in your entrypoint module (usually where you
start the worker), before any other third party libraries are imported:

```python
#!/usr/bin/env python3
import mode.loop
mode.loop.use('eventlet')
# execute program
```

REMEMBER: It's very important this is at the very top of the module,
and that it executes before you import libraries.

#### Can I use Mode with Tornado?

Yes! Use the `tornado.platform.asyncio` bridge: http://www.tornadoweb.org/en/stable/asyncio.html

#### Can I use Mode with Twisted?

Yes! Use the asyncio reactor implementation:
https://twistedmatrix.com/documents/17.1.0/api/twisted.internet.asyncioreactor.html

#### Will you support Python 3.5 or earlier?

There are no immediate plans to support Python 3.5, but you are welcome to
contribute to the project.

Here are some of the steps required to accomplish this:

- Source code transformation to rewrite variable annotations to comments for example, the code:

```python
class Point:
    x: int = 0
    y: int = 0
```
must be rewritten into:

```python
class Point:
    x = 0  # type: int
    y = 0  # type: int
```

- Source code transformation to rewrite async functions for example, the code:

```python
async def foo():
    await asyncio.sleep(1.0)
```

must be rewritten into:

```python
@coroutine
def foo():
    yield from asyncio.sleep(1.0)
```

#### Will you support Python 2?

There are no plans to support Python 2, but you are welcome to contribute to
the project (details in question above is relevant also for Python 2).


### At Shutdown I get lots of warnings, what is this about?

If you get warnings such as this at shutdown:

```log
Task was destroyed but it is pending!
task: <Task pending coro=<Service._execute_task() running at /opt/devel/mode/mode/services.py:643> wait_for=<Future pending cb=[<TaskWakeupMethWrapper object at 0x1100a7468>()]>>
Task was destroyed but it is pending!
task: <Task pending coro=<Service._execute_task() running at /opt/devel/mode/mode/services.py:643> wait_for=<Future pending cb=[<TaskWakeupMethWrapper object at 0x1100a72e8>()]>>
Task was destroyed but it is pending!
task: <Task pending coro=<Service._execute_task() running at /opt/devel/mode/mode/services.py:643> wait_for=<Future pending cb=[<TaskWakeupMethWrapper object at 0x1100a7678>()]>>
Task was destroyed but it is pending!
task: <Task pending coro=<Event.wait() running at /Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/asyncio/locks.py:269> cb=[_release_waiter(<Future pendi...1100a7468>()]>)() at /Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/asyncio/tasks.py:316]>
Task was destroyed but it is pending!
    task: <Task pending coro=<Event.wait() running at /Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/asyncio/locks.py:269> cb=[_release_waiter(<Future pendi...1100a7678>()]>)() at /Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/asyncio/tasks.py:316]>
```

It usually means you forgot to stop a service before the process exited.

## Code of Conduct

Everyone interacting in the project's codebases, issue trackers, chat rooms,
and mailing lists is expected to follow the Mode Code of Conduct.

As contributors and maintainers of these projects, and in the interest of fostering
an open and welcoming community, we pledge to respect all people who contribute
through reporting issues, posting feature requests, updating documentation,
submitting pull requests or patches, and other activities.

We are committed to making participation in these projects a harassment-free
experience for everyone, regardless of level of experience, gender,
gender identity and expression, sexual orientation, disability,
personal appearance, body size, race, ethnicity, age,
religion, or nationality.

Examples of unacceptable behavior by participants include:

* The use of sexualized language or imagery
* Personal attacks
* Trolling or insulting/derogatory comments
* Public or private harassment
* Publishing other's private information, such as physical
  or electronic addresses, without explicit permission
* Other unethical or unprofessional conduct.

Project maintainers have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct. By adopting this Code of Conduct,
project maintainers commit themselves to fairly and consistently applying
these principles to every aspect of managing this project. Project maintainers
who do not follow or enforce the Code of Conduct may be permanently removed from
the project team.

This code of conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community.

Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by opening an issue or contacting one or more of the project maintainers.

This Code of Conduct is adapted from the Contributor Covenant,
version 1.2.0 available at http://contributor-covenant.org/version/1/2/0/.

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "mode-streaming",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.8",
    "maintainer_email": "William Barnhart <williambbarnhart@gmail.com>",
    "keywords": "asyncio, service, bootsteps, graph, coroutine",
    "author": null,
    "author_email": "Ask Solem Hoel <ask@robinhood.com>",
    "download_url": null,
    "platform": null,
    "description": "# AsyncIO Services Fork\n\n![python versions](https://img.shields.io/pypi/pyversions/mode-streaming.svg)\n![implementation](https://img.shields.io/pypi/implementation/mode-streaming)\n![version](https://img.shields.io/pypi/v/mode-streaming)\n![license](https://img.shields.io/pypi/l/mode-streaming)\n![downloads](https://img.shields.io/pypi/dw/mode-streaming)\n\n\n---\n\n**Documentation**: <a href=\"https://faust-streaming.github.io/mode/\" target=\"_blank\">https://faust-streaming.github.io/mode/</a>\n\n**Source Code**: <a href=\"https://github.com/faust-streaming/mode\" target=\"_blank\">https://github.com/faust-streaming/mode</a>\n\n---\n\n## Why the fork\n\nWe have decided to fork the original *Mode* project because there is a critical process of releasing new versions which causes uncertainty in the community. Everybody is welcome to contribute to this *fork*, and you can be added as a maintainer.\n\nWe want to:\n\n- Ensure continues release\n- Code quality\n- Support latest Python versions\n- Update the documentation\n\nand more...\n\n## What is Mode?\n\nMode is a very minimal Python library built-on top of AsyncIO that makes\nit much easier to use.\n\nIn Mode your program is built out of services that you can start, stop,\nrestart and supervise.\n\nA service is just a class:\n\n```python\nclass PageViewCache(Service):\n    redis: Redis = None\n\n    async def on_start(self) -> None:\n        self.redis = connect_to_redis()\n\n    async def update(self, url: str, n: int = 1) -> int:\n        return await self.redis.incr(url, n)\n\n    async def get(self, url: str) -> int:\n        return await self.redis.get(url)\n```\n\nServices are started, stopped and restarted and have\ncallbacks for those actions.\n\nIt can start another service:\n\n```python\nclass App(Service):\n    page_view_cache: PageViewCache = None\n\n    async def on_start(self) -> None:\n        await self.add_runtime_dependency(self.page_view_cache)\n\n    @cached_property\n    def page_view_cache(self) -> PageViewCache:\n        return PageViewCache()\n```\n\nIt can include background tasks:\n\n```python\nclass PageViewCache(Service):\n\n    @Service.timer(1.0)\n    async def _update_cache(self) -> None:\n        self.data = await cache.get('key')\n```\n\nServices that depends on other services actually form a graph\nthat you can visualize.\n\n### Worker\n\nMode optionally provides a worker that you can use to start the program,\nwith support for logging, blocking detection, remote debugging and more.\n\nTo start a worker add this to your program:\n\n\n```python\nif __name__ == '__main__':\n    from mode import Worker\n    Worker(Service(), loglevel=\"info\").execute_from_commandline()\n```\n\nThen execute your program to start the worker:\n\n```log\n$ python examples/tutorial.py\n[2018-03-27 15:47:12,159: INFO]: [^Worker]: Starting...\n[2018-03-27 15:47:12,160: INFO]: [^-AppService]: Starting...\n[2018-03-27 15:47:12,160: INFO]: [^--Websockets]: Starting...\nSTARTING WEBSOCKET SERVER\n[2018-03-27 15:47:12,161: INFO]: [^--UserCache]: Starting...\n[2018-03-27 15:47:12,161: INFO]: [^--Webserver]: Starting...\n[2018-03-27 15:47:12,164: INFO]: [^--Webserver]: Serving on port 8000\nREMOVING EXPIRED USERS\nREMOVING EXPIRED USERS\n```\n\nTo stop it hit `Control-c`:\n\n```log\n[2018-03-27 15:55:08,084: INFO]: [^Worker]: Stopping on signal received...\n[2018-03-27 15:55:08,084: INFO]: [^Worker]: Stopping...\n[2018-03-27 15:55:08,084: INFO]: [^-AppService]: Stopping...\n[2018-03-27 15:55:08,084: INFO]: [^--UserCache]: Stopping...\nREMOVING EXPIRED USERS\n[2018-03-27 15:55:08,085: INFO]: [^Worker]: Gathering service tasks...\n[2018-03-27 15:55:08,085: INFO]: [^--UserCache]: -Stopped!\n[2018-03-27 15:55:08,085: INFO]: [^--Webserver]: Stopping...\n[2018-03-27 15:55:08,085: INFO]: [^Worker]: Gathering all futures...\n[2018-03-27 15:55:08,085: INFO]: [^--Webserver]: Closing server\n[2018-03-27 15:55:08,086: INFO]: [^--Webserver]: Waiting for server to close handle\n[2018-03-27 15:55:08,086: INFO]: [^--Webserver]: Shutting down web application\n[2018-03-27 15:55:08,086: INFO]: [^--Webserver]: Waiting for handler to shut down\n[2018-03-27 15:55:08,086: INFO]: [^--Webserver]: Cleanup\n[2018-03-27 15:55:08,086: INFO]: [^--Webserver]: -Stopped!\n[2018-03-27 15:55:08,086: INFO]: [^--Websockets]: Stopping...\n[2018-03-27 15:55:08,086: INFO]: [^--Websockets]: -Stopped!\n[2018-03-27 15:55:08,087: INFO]: [^-AppService]: -Stopped!\n[2018-03-27 15:55:08,087: INFO]: [^Worker]: -Stopped!\n```\n\n### Beacons\n\nThe `beacon` object that we pass to services keeps track of the services\nin a graph.\n\nThey are not strictly required, but can be used to visualize a running\nsystem, for example we can render it as a pretty graph.\n\nThis requires you to have the `pydot` library and GraphViz\ninstalled:\n\n```sh\n$ pip install pydot\n```\n\nLet's change the app service class to dump the graph to an image\nat startup:\n\n```python\nclass AppService(Service):\n\n    async def on_start(self) -> None:\n        print('APP STARTING')\n        import pydot\n        import io\n        o = io.StringIO()\n        beacon = self.app.beacon.root or self.app.beacon\n        beacon.as_graph().to_dot(o)\n        graph, = pydot.graph_from_dot_data(o.getvalue())\n        print('WRITING GRAPH TO image.png')\n        with open('image.png', 'wb') as fh:\n            fh.write(graph.create_png())\n```\n\n## Creating a Service\n\nTo define a service, simply subclass and fill in the methods\nto do stuff as the service is started/stopped etc.:\n\n\n```python\nclass MyService(Service):\n\n    async def on_start(self) -> None:\n        print('Im starting now')\n\n    async def on_started(self) -> None:\n        print('Im ready')\n\n    async def on_stop(self) -> None:\n        print('Im stopping now')\n```\n\nTo start the service, call `await service.start()`:\n\n```python\nawait service.start()\n```\n\nOr you can use `mode.Worker` (or a subclass of this) to start your\nservices-based asyncio program from the console:\n\n```python\nif __name__ == '__main__':\n    import mode\n    worker = mode.Worker(\n        MyService(),\n        loglevel='INFO',\n        logfile=None,\n        daemon=False,\n    )\n    worker.execute_from_commandline()\n```\n\n## It's a Graph!\n\nServices can start other services, coroutines, and background tasks.\n\n1) Starting other services using `add_dependency`:\n\n```python\nclass MyService(Service):\n    def __post_init__(self) -> None:\n        self.add_dependency(OtherService(loop=self.loop))\n```\n\n1) Start a list of services using `on_init_dependencies`:\n\n```python\nclass MyService(Service):\n\n    def on_init_dependencies(self) -> None:\n        return [\n            ServiceA(loop=self.loop),\n            ServiceB(loop=self.loop),\n            ServiceC(loop=self.loop),\n        ]\n```\n\n1) Start a future/coroutine (that will be waited on to complete on stop):\n\n```python\nclass MyService(Service):\n\n    async def on_start(self) -> None:\n        self.add_future(self.my_coro())\n\n    async def my_coro(self) -> None:\n        print('Executing coroutine')\n```\n\n1) Start a background task:\n\n```python\nclass MyService(Service):\n\n    @Service.task\n    async def _my_coro(self) -> None:\n        print('Executing coroutine')\n```\n\n1) Start a background task that keeps running:\n\n```python\nclass MyService(Service):\n\n    @Service.task\n    async def _my_coro(self) -> None:\n        while not self.should_stop:\n            # NOTE: self.sleep will wait for one second, or\n            #       until service stopped/crashed.\n            await self.sleep(1.0)\n            print('Background thread waking up')\n```\n\n## Installation\n\nYou can install Mode either via the Python Package Index (PyPI)\nor from source.\n\nTo install using `pip`:\n\n```sh\n$ pip install -U mode-streaming\n```\n\nDownloading and installing from source: http://pypi.org/project/mode-streaming\n\nYou can install it by doing the following:\n\n```sh\n$ tar xvfz mode-streaming-0.2.1.tar.gz\n$ cd mode-0.2.1\n$ python -m build .\n# python install\n```\n\nThe last command must be executed as a privileged user if\nyou are not currently using a virtualenv.\n\n\nUsing the development version:\n\nWith pip:\n\nYou can install the latest snapshot of Mode using the following\npip command:\n\n```sh\n$ pip install mode-streaming\n```\n\n## Developing\n\nThe guideline and associated information are stored in [CONTRIBUTING.md](./CONTRIBUTING.md)\n\n## FAQ\n\n#### Can I use Mode with Django/Flask/etc.?\n\nYes! Use gevent/eventlet as a bridge to integrate with asyncio.\n\nUsing `gevent`:\n\nThis works with any blocking Python library that can work with gevent.\n\nUsing gevent requires you to install the `aiogevent` module,\nand you can install this as a bundle with Mode:\n\n```sh\n$ pip install -U mode-streaming[gevent]\n```\n\nThen to actually use gevent as the event loop you have to\nexecute the following in your entrypoint module (usually where you\nstart the worker), before any other third party libraries are imported:\n\n\n```python\n#!/usr/bin/env python3\nimport mode.loop\nmode.loop.use('gevent')\n# execute program\n```\n\nREMEMBER: This must be located at the very top of the module,\nin such a way that it executes before you import other libraries.\n\n\nUsing `eventlet`:\n\nThis works with any blocking Python library that can work with eventlet.\n\nUsing eventlet requires you to install the `aioeventlet` module,\nand you can install this as a bundle with Mode:\n\n```sh\n$ pip install -U mode-streaming[eventlet]\n```\n\nThen to actually use eventlet as the event loop you have to\nexecute the following in your entrypoint module (usually where you\nstart the worker), before any other third party libraries are imported:\n\n```python\n#!/usr/bin/env python3\nimport mode.loop\nmode.loop.use('eventlet')\n# execute program\n```\n\nREMEMBER: It's very important this is at the very top of the module,\nand that it executes before you import libraries.\n\n#### Can I use Mode with Tornado?\n\nYes! Use the `tornado.platform.asyncio` bridge: http://www.tornadoweb.org/en/stable/asyncio.html\n\n#### Can I use Mode with Twisted?\n\nYes! Use the asyncio reactor implementation:\nhttps://twistedmatrix.com/documents/17.1.0/api/twisted.internet.asyncioreactor.html\n\n#### Will you support Python 3.5 or earlier?\n\nThere are no immediate plans to support Python 3.5, but you are welcome to\ncontribute to the project.\n\nHere are some of the steps required to accomplish this:\n\n- Source code transformation to rewrite variable annotations to comments for example, the code:\n\n```python\nclass Point:\n    x: int = 0\n    y: int = 0\n```\nmust be rewritten into:\n\n```python\nclass Point:\n    x = 0  # type: int\n    y = 0  # type: int\n```\n\n- Source code transformation to rewrite async functions for example, the code:\n\n```python\nasync def foo():\n    await asyncio.sleep(1.0)\n```\n\nmust be rewritten into:\n\n```python\n@coroutine\ndef foo():\n    yield from asyncio.sleep(1.0)\n```\n\n#### Will you support Python 2?\n\nThere are no plans to support Python 2, but you are welcome to contribute to\nthe project (details in question above is relevant also for Python 2).\n\n\n### At Shutdown I get lots of warnings, what is this about?\n\nIf you get warnings such as this at shutdown:\n\n```log\nTask was destroyed but it is pending!\ntask: <Task pending coro=<Service._execute_task() running at /opt/devel/mode/mode/services.py:643> wait_for=<Future pending cb=[<TaskWakeupMethWrapper object at 0x1100a7468>()]>>\nTask was destroyed but it is pending!\ntask: <Task pending coro=<Service._execute_task() running at /opt/devel/mode/mode/services.py:643> wait_for=<Future pending cb=[<TaskWakeupMethWrapper object at 0x1100a72e8>()]>>\nTask was destroyed but it is pending!\ntask: <Task pending coro=<Service._execute_task() running at /opt/devel/mode/mode/services.py:643> wait_for=<Future pending cb=[<TaskWakeupMethWrapper object at 0x1100a7678>()]>>\nTask was destroyed but it is pending!\ntask: <Task pending coro=<Event.wait() running at /Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/asyncio/locks.py:269> cb=[_release_waiter(<Future pendi...1100a7468>()]>)() at /Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/asyncio/tasks.py:316]>\nTask was destroyed but it is pending!\n    task: <Task pending coro=<Event.wait() running at /Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/asyncio/locks.py:269> cb=[_release_waiter(<Future pendi...1100a7678>()]>)() at /Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/asyncio/tasks.py:316]>\n```\n\nIt usually means you forgot to stop a service before the process exited.\n\n## Code of Conduct\n\nEveryone interacting in the project's codebases, issue trackers, chat rooms,\nand mailing lists is expected to follow the Mode Code of Conduct.\n\nAs contributors and maintainers of these projects, and in the interest of fostering\nan open and welcoming community, we pledge to respect all people who contribute\nthrough reporting issues, posting feature requests, updating documentation,\nsubmitting pull requests or patches, and other activities.\n\nWe are committed to making participation in these projects a harassment-free\nexperience for everyone, regardless of level of experience, gender,\ngender identity and expression, sexual orientation, disability,\npersonal appearance, body size, race, ethnicity, age,\nreligion, or nationality.\n\nExamples of unacceptable behavior by participants include:\n\n* The use of sexualized language or imagery\n* Personal attacks\n* Trolling or insulting/derogatory comments\n* Public or private harassment\n* Publishing other's private information, such as physical\n  or electronic addresses, without explicit permission\n* Other unethical or unprofessional conduct.\n\nProject maintainers have the right and responsibility to remove, edit, or reject\ncomments, commits, code, wiki edits, issues, and other contributions that are\nnot aligned to this Code of Conduct. By adopting this Code of Conduct,\nproject maintainers commit themselves to fairly and consistently applying\nthese principles to every aspect of managing this project. Project maintainers\nwho do not follow or enforce the Code of Conduct may be permanently removed from\nthe project team.\n\nThis code of conduct applies both within project spaces and in public spaces\nwhen an individual is representing the project or its community.\n\nInstances of abusive, harassing, or otherwise unacceptable behavior may be\nreported by opening an issue or contacting one or more of the project maintainers.\n\nThis Code of Conduct is adapted from the Contributor Covenant,\nversion 1.2.0 available at http://contributor-covenant.org/version/1/2/0/.\n",
    "bugtrack_url": null,
    "license": null,
    "summary": "AsyncIO Service-based programming",
    "version": "0.4.1",
    "project_urls": {
        "Documentation": "https://faust-streaming.github.io/mode/",
        "Homepage": "https://github.com/faust-streaming/mode",
        "Repository": "https://github.com/faust-streaming/mode"
    },
    "split_keywords": [
        "asyncio",
        " service",
        " bootsteps",
        " graph",
        " coroutine"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "bce26cbe2bd0b41bf71ef6f574237d26642798ff58ba7d52c43d72a605969a73",
                "md5": "88770230cf35d84ac77c2ca7609e9679",
                "sha256": "9e773e1e7982165e64ba35e59acffb2916dd01f2a86e8eb174f9e95023ec370a"
            },
            "downloads": -1,
            "filename": "mode_streaming-0.4.1-py2.py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "88770230cf35d84ac77c2ca7609e9679",
            "packagetype": "bdist_wheel",
            "python_version": "py2.py3",
            "requires_python": ">=3.8",
            "size": 94651,
            "upload_time": "2024-04-15T13:28:26",
            "upload_time_iso_8601": "2024-04-15T13:28:26.615160Z",
            "url": "https://files.pythonhosted.org/packages/bc/e2/6cbe2bd0b41bf71ef6f574237d26642798ff58ba7d52c43d72a605969a73/mode_streaming-0.4.1-py2.py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-04-15 13:28:26",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "faust-streaming",
    "github_project": "mode",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "requirements": [],
    "tox": true,
    "lcname": "mode-streaming"
}
        
Elapsed time: 3.35003s