CONTEXT¶
Propan хранит контекс приложения и каждого запроса в глобальном контексе, доступ к которому вы можете получить с помощью специального класса Context
.
1 2 3 4 5 |
|
Существующие поля¶
Context уже содержит некоторые глобальные объекты, к которым вы всегда можете получить доступ:
- app - объект
PropanApp
вашего приложения - broker - текущий брокер
- context - непосредственно сам контекс, в который вы можете записать собственные поля
- logger - logger, используемый для вашего брокера (помечает сообщения с помощью message_id)
- message - необработанное сообщение (если вам нужен доступ к нему)
При этом, благодаря contextlib.ContextVar
, message всегда соответствует контексту текущего процесса обработки.
Доступ к полям контекста¶
По умолчанию, как в примере выше, контекст ищет объект исходя из названия аргумента.
1 2 3 4 5 6 7 8 9 10 11 12 |
|
Доступ по имени¶
Иногда у вас может возникнуть необходимость использовать другое название для аргумента (не то, под которым он хранится в контексте). Или даже получить доступ не ко всему объекту, а только к его полю или методу. Для этого просто укажите по имени, что вы хотите получить - и контекст предоставит вам нужный объект.
1 2 3 4 5 6 7 8 9 10 |
|
Annotated¶
Способ по умолчанию не слишком удобен, если вам необходимо использовать одно и то же поле контекста по всему проекту. Также, оно требует явного указания аннотации типа входящего аргумента, если мы хотим пользоваться автодополнением нашей IDE. Для того, чтобы избежать длинных цепочек импортов и дублирования кода, Context
полностью совместим с typing.Annotated
.
1 2 3 4 5 6 7 8 9 10 11 |
|
Для вашего удобства Propan уже содержит аннотации для существующих полей контекста. Вы можете просто импортировать их и использовать в вашем коде.
1 2 3 4 5 6 7 8 9 10 11 12 |
|
Значения по умолчанию¶
Если же вы попробуете получить доступ к полю, которого нет в глобальном контексте, вы получите ошибку pydantic.ValidationError
.
Однако, вы можете установить значение по умолчанию, если испытываете в этом необходимость.
1 2 3 4 5 6 7 8 |
|
Приведение типов контекста¶
По умолчанию, поля контекста НЕ ПРИВОДЯТСЯ к типу, указанному в их аннотации. Если вам необходим этот функционал, вы просто можете установить соотвествующий флаг.
1 2 3 4 5 6 7 8 |
|
Объявление полей контекста¶
Глобально¶
Для объявления полей контекста необходимо просто вызвать метод context.set_global
с указанием ключа, по которому объект будет помещен в контекст.
1 2 3 4 5 6 7 8 |
|
При этом поле становится глобальным полем контекста: оно не зависит от текущего обработчика сообщения (в отличие от message
)
Для удаления поля из контекста просто используйте reset_global
context.reset_global("my_key")
Локально¶
Для установки локального контекста (он будет действовать во всех функциях, вызванных внутри него) используйте контекстный менеджер scope
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
Также, контекст можно установить самостоятельно: тогда он будет действовать в рамках текущего стека вызовов до тех пор, пока вы его не очистите.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
Использование в других функциях¶
По умолчанию контекст доступен там же, где и Depends
:
- в хуках жизненного цикла
- обработчиках сообщений
- зависимостях
Depends¶
При использовании Context
в Depends
нет необходимости писать дополнительный код: как и вложенные Depends
, Context
также доступен по умолчанию.
1 2 3 4 5 6 7 8 9 10 11 12 |
|
Обычные функции¶
Если же вы хотите использовать контекст и в других функциях, просто используйте декоратор @apply_types
. При этом
контекст вызванной функции будет соответсвовать контексту обработчика события, из которого она вызвана.
1 2 3 4 5 6 7 8 9 10 11 12 |
|
В примере выше мы не передавали при вызове функции logger
, он был помещен из контекста.