Mode

Latest version: v4.4.0

Safety actively analyzes 629639 Python packages for vulnerabilities to keep your Python projects secure.

Scan your dependencies

Page 11 of 15

1.12.1

======
:release-date: 2018-04-24 11:28 P.M PDT
:release-by: Ask Solem

- Now works with CPython 3.6.1 and 3.6.0.

.. _version-1.12.0:

1.12.0

======
:release-date: 2018-04-23 1:28 P.M PDT
:release-by: Ask Solem

Backward Incompatible Changes
-----------------------------

+ Changed ``Service.add_context``

- To add an async context manager (:class:`~typing.AsyncContextManager`),
use :meth:`~mode.Service.add_async_context`::

class S(Service):

async def on_start(self) -> None:
self.context = await self.add_async_context(MyAsyncContext())

- To add a regular context manager (:class:`~typing.ContextManager`),
use :meth:`~mode.Service.add_context`::

class S(Service):

async def on_start(self) -> None:
self.context = self.add_context(MyContext())

This change was made so that contexts can be added from non-async
functions. To add an *async context* you still need to be within an
async function definition.

News
----

+ Worker: Now redirects :data:`sys.stdout` and :data:`sys.stderr` to the
logging subsystem by default.

- To disable this pass ``Worker(redirect_stdouts=False)``.

- The default severity level for ``print`` statements are
:data:`logging.WARN`, but you can change this using
``Worker(redirect_stdouts_level='INFO')``.

+ :class:`~mode.Seconds`/:func:`~mode.want_seconds` can now be expressed
as strings and rate strings:

- float as string: ``want_seconds('1.203') == 1.203``

- *10 in one second*: ``want_seconds('10/s') == 10.0``

- *10.33 in one hour*: ``want_seconds('10.3/h') == 0.0028611111111111116``

- *100 in one hour*: ``want_seconds('100/h') == 0.02777777777777778``

- *100 in one day*: ``want_seconds('100/d') == 0.0011574074074074076``

This is especially useful for the rate argument
to the :class:`~mode.utils.times.rate_limit` helper.

+ Added new context manager: :func:`mode.utils.logging.redirect_stdouts`.

+ Module :mod:`mode.types` now organized by category:

- Service types: :mod:`mode.types.services`

- Signal types: :mod:`mode.types.signals`

- Supervisor types: :mod:`mode.types.supervisors`

+ :class:`mode.flight_recorder` can now wrap objects so that every method call
on that object will result in the call and arguments to that call
being logged.

Example logging statements with ``INFO`` severity::

with flight_recorder(logger, timeout=10.0) as on_timeout:
redis = on_timeout.wrap_info(self.redis)
await redis.get(key)

There's also ``wrap_debug(o)``, ``wrap_warn(o)``, ``wrap_error(o)``,
and for any severity: ``wrap(logging.CRIT, o)``.

Fixes
-----

+ Fixed bug in ``Service.wait`` on Python 3.7.

.. _version-1.11.5:

1.11.5

======
:release-date: 2018-04-19 3:12 P.M PST
:release-by: Ask Solem

+ FlowControlQueue now available in ``mode.utils.queues``.

This is a backward compatible change.

+ Tests for FlowControlQueue

.. _version-1.11.4:

1.11.4

======
:release-date: 2018-04-19 9:36 A.M PST
:release-by: Ask Solem

+ Adds :class:`mode.flight_recorder`

This is a logging utility to log stuff only when something
times out.

For example if you have a background thread that is sometimes
hanging::

class RedisCache(mode.Service):

mode.timer(1.0)
def _background_refresh(self) -> None:
self._users = await self.redis_client.get(USER_KEY)
self._posts = await self.redis_client.get(POSTS_KEY)

You want to figure out on what line this is hanging, but logging
all the time will provide way too much output, and will even change
how fast the program runs and that can mask race conditions, so that
they never happen.

Use the flight recorder to save the logs and only log when it times out:

.. sourcecode:: python

logger = mode.get_logger(__name__)

class RedisCache(mode.Service):

mode.timer(1.0)
def _background_refresh(self) -> None:
with mode.flight_recorder(logger, timeout=10.0) as on_timeout:
on_timeout.info(f'+redis_client.get({USER_KEY!r})')
await self.redis_client.get(USER_KEY)
on_timeout.info(f'-redis_client.get({USER_KEY!r})')

on_timeout.info(f'+redis_client.get({POSTS_KEY!r})')
await self.redis_client.get(POSTS_KEY)
on_timeout.info(f'-redis_client.get({POSTS_KEY!r})')

If the body of this :keyword:`with` statement completes before the
timeout, the logs are forgotten about and never emitted -- if it
takes more than ten seconds to complete, we will see these messages
in the log:

.. sourcecode:: text

[2018-04-19 09:43:55,877: WARNING]: Warning: Task timed out!
[2018-04-19 09:43:55,878: WARNING]: Please make sure it is hanging before restarting.
[2018-04-19 09:43:55,878: INFO]: [Flight Recorder-1] (started at Thu Apr 19 09:43:45 2018) Replaying logs...
[2018-04-19 09:43:55,878: INFO]: [Flight Recorder-1] (Thu Apr 19 09:43:45 2018) +redis_client.get('user')
[2018-04-19 09:43:55,878: INFO]: [Flight Recorder-1] (Thu Apr 19 09:43:49 2018) -redis_client.get('user')
[2018-04-19 09:43:55,878: INFO]: [Flight Recorder-1] (Thu Apr 19 09:43:46 2018) +redis_client.get('posts')
[2018-04-19 09:43:55,878: INFO]: [Flight Recorder-1] -End of log-

Now we know this ``redis_client.get`` call can take too long to complete,
and should consider adding a timeout to it.

.. _version-1.11.3:

1.11.3

======
:release-date: 2018-04-18 5:22 P.M PST
:relese-by: Ask Solem

- Cry handler (`kill -USR1`): Truncate huge data in stack frames.

- ServiceProxy: Now supports ``_crash`` method.

.. _version-1.11.2:

1.11.2

======
:release-date: 2018-04-18 5:02 P.M PST
:release-by: Ask Solem

- Service: ``add_future()`` now maintains futures in a set and futures
are automatically removed from it when done.

- Cry handler (`kill -USR1`) now shows name of Service.task background tasks.

- Stampede: Now propagates cancellation.

.. _version-1.11.1:

Page 11 of 15

© 2024 Safety CLI Cybersecurity Inc. All Rights Reserved.