На второе октября намечен релиз Python 3.12, поэтому Никита Соболев (opensource разработчик и контрибьютор в сpython) рассказывает про новинки в новой версии и чуть затрагивает то, что ожидает нас в 3.13.
Рекомендую посмотреть, чтобы оставаться в теме новых обновлений.
#посмотреть
Рекомендую посмотреть, чтобы оставаться в теме новых обновлений.
#посмотреть
YouTube
«Новинки в Python 3.12 и даже немного про 3.13», Никита Соболев
«Окей, Никита, что нового в Python?»
Еще одни спикер #GPDays2023 Никита Соболев – Open Source разработчик и любитель Python рассказал о чистке stdlib, PEP 695, новом синтаксисе для типизации, а также uops из Python 3.13:
01:19 Что нового в новом Python…
Еще одни спикер #GPDays2023 Никита Соболев – Open Source разработчик и любитель Python рассказал о чистке stdlib, PEP 695, новом синтаксисе для типизации, а также uops из Python 3.13:
01:19 Что нового в новом Python…
Недавно пришлось писать конвертор который транслировал Markdown в довольно специфичный формат.
Была следующая идея - мне нужен парсер, который перегонит Markdown в синтаксическое дерево, которое я буду обходить.
С обычным python-markdown в этом плане банально неудобно работать - у него нет простого и расширяемого API (как минимум), который бы позволял решить мою задачу.
А вот у mistletoe такое API есть. Например, вот так выглядит рендерер markdown в jira:
#библиотека
Была следующая идея - мне нужен парсер, который перегонит Markdown в синтаксическое дерево, которое я буду обходить.
С обычным python-markdown в этом плане банально неудобно работать - у него нет простого и расширяемого API (как минимум), который бы позволял решить мою задачу.
А вот у mistletoe такое API есть. Например, вот так выглядит рендерер markdown в jira:
class JiraRenderer(BaseRenderer):Ещё mistletoe можно использовать как утилиту. Например, вот так markdown-файл можно перевести в тот же формат Jira:
def render_strong(self, token):
template = '*{}*'
return template.format(self.render_inner(token))
def render_emphasis(self, token):
template = '_{}_'
return template.format(self.render_inner(token))
mistletoe foo.md --renderer mistletoe.contrib.jira_renderer.JiraRendererПоэтому, если вам нужна небольшая, но расширяемая библиотека для работы с markdown - берите её, не прогадаете.
#библиотека
Пока я спал, руководящий совет языка принял PEP 703 (Making the Global Interpreter Lock Optional in CPython).
Кратко о том, о чём говорится в посте:
1. Руководящему совету ясно, что несмотря на все проблемы и недостатки потоков, nogil будет полезен для Python, так как позволит находить более масштабируемые решения.
2. В то же время, они не уверены, получится ли убрать GIL не сломав при этом обратную совместимость - всё же не хотелось бы терять десятилетия развития базы пакетов. Существующая пакетная экосистема - это одна из сильных сторон языка, как и простая интеграция библиотек на C c CPython.
3. Оценить влияние nogil без реализации сложно, поэтому nogil должен выпускаться в составе регулярных релизов и не обязательно он там должен быть по-умолчанию.
4. Это всё ещё не гарантированная история. Если что-то пойдет не так - от изменений откажутся. Развёртывание должно быть постепенным и наиболее плавным.
5. Выкатка будет происходить в 3 фазы, которые возможно изменятся:
- В первой фазе nogil сделают возможным таргетом при сборке, чтобы разработчики могли тестировать свои пакеты.
- Во второй фазе, когда изменения в API и ABI будут сформированы, а поддержка nogil от сообщества будет достаточной, nogil-сборку добавлят как "поддерживаемую, но не по умолчанию".
- В третьей фазе nogil-сборку сделают сборкой "по-умолчанию", а от gil-сборки будут отказываться.
6. При успешной реализации nogil, ожидается падение производительности на 10-15% в худшем случае.
#pep
Кратко о том, о чём говорится в посте:
1. Руководящему совету ясно, что несмотря на все проблемы и недостатки потоков, nogil будет полезен для Python, так как позволит находить более масштабируемые решения.
2. В то же время, они не уверены, получится ли убрать GIL не сломав при этом обратную совместимость - всё же не хотелось бы терять десятилетия развития базы пакетов. Существующая пакетная экосистема - это одна из сильных сторон языка, как и простая интеграция библиотек на C c CPython.
3. Оценить влияние nogil без реализации сложно, поэтому nogil должен выпускаться в составе регулярных релизов и не обязательно он там должен быть по-умолчанию.
4. Это всё ещё не гарантированная история. Если что-то пойдет не так - от изменений откажутся. Развёртывание должно быть постепенным и наиболее плавным.
5. Выкатка будет происходить в 3 фазы, которые возможно изменятся:
- В первой фазе nogil сделают возможным таргетом при сборке, чтобы разработчики могли тестировать свои пакеты.
- Во второй фазе, когда изменения в API и ABI будут сформированы, а поддержка nogil от сообщества будет достаточной, nogil-сборку добавлят как "поддерживаемую, но не по умолчанию".
- В третьей фазе nogil-сборку сделают сборкой "по-умолчанию", а от gil-сборки будут отказываться.
6. При успешной реализации nogil, ожидается падение производительности на 10-15% в худшем случае.
#pep
Discussions on Python.org
PEP 703 (Making the Global Interpreter Lock Optional in CPython) acceptance
(Posted for the whole Steering Council.) As we’ve announced before, the Steering Council has decided to accept PEP 703 (Making the Global Interpreter Lock Optional in CPython) . We want to make it clear why, and under what expectations we’re doing so. It…
Коробка с питоном
Если обычного itertools вам мало, то можно использовать more-itertools. Эта библиотека добавляет огромное количество функций для работы с итераторами. На практике всеми ими не всегда пользуются, поэтому я выделю некоторые из тех, которые сам использую часто.…
На сегодня расскажу ещё пару рецептов с
1)
2) Получить последний элемент можно при помощи
Ещё есть
3)
4) Ну и в конце про
#itertools #more_itertools #библиотека #рецепт
more_itertools
.1)
map_if
работает как обычный map
, но применяет функцию на элемент только если оно попадает под условие. Например, вот так мы можем возвести в квадрат только те числа, которые делятся на 2 нацело:example = [1, 2, 3, 4, 5, 6, 7, 8]
list(map_if(example, lambda x: x % 2 == 0, lambda x: x * x)) # [1, 4, 3, 16, 5, 36, 7, 64]
2) Получить последний элемент можно при помощи
last
. Возникает вопрос а зачем он существует, если можно указать sequence[-1]
? Ответом является то, что last
позволяет указать, что ему возвращать, если элементов в коллекции нет:last([1, 2, 3]) # Очевидно получим 3
last([], 0) # Список пустой, но получим 0
[][-1] # Получим IndexError
Ещё есть
first
- как понятно из названия, он получает первый элемент.3)
map_except
тоже работает как map
, но умеет игнорировать ошибки. Например, мы хотим получить только те элементы, которые получилось привести к целому числу:example = [1, "1", "2", "test", "three", object, 4.0]
list(map_except(int, example, ValueError, TypeError)) # [1, 1, 2, 4]
4) Ну и в конце про
take
- он просто берет N элементов из итерируемого объекта:example = range(10)
take(3, example) # [0, 1, 2]
take(20, example) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] - если больше, возьмет доступные
#itertools #more_itertools #библиотека #рецепт
В одном чатике встретил проект fakeredis, реализующий Redis-сервер на питоне, который можно использовать для тестов. Очевидно, чтобы не таскать для тестов настоящий Redis.
Поддерживаются практически все стандартные команды, которые я встречал для работы с типами/коллекциями (список здесь). Есть не полная поддержка JSON, поиска, time series.
Если каких-то команд не хватает, автор оставил гайд, как её сделать. Ну а если сделаете - законтрибутьте в опенсорс, полезное дело всё таки!
#библиотека
Поддерживаются практически все стандартные команды, которые я встречал для работы с типами/коллекциями (список здесь). Есть не полная поддержка JSON, поиска, time series.
Если каких-то команд не хватает, автор оставил гайд, как её сделать. Ну а если сделаете - законтрибутьте в опенсорс, полезное дело всё таки!
#библиотека
GitHub
GitHub - cunla/fakeredis-py: Implementation of Redis in python without having a Redis server running. Fully compatible with using…
Implementation of Redis in python without having a Redis server running. Fully compatible with using redis-py. - cunla/fakeredis-py
Forwarded from Питонические атаки
PSF и JetBrains запустили своё ежегодное исследование Python Developers Survey 2023. Погнали заполнять! 👇
https://survey.alchemer.com/s3/7554174/python-developers-survey-2023
Через год, когда подведут результаты, будет повод написать пост, типа такого 😅
https://survey.alchemer.com/s3/7554174/python-developers-survey-2023
Через год, когда подведут результаты, будет повод написать пост, типа такого 😅
Alchemer
Python Developers Survey 2023
The official Python Developers Survey 2023. Join and contribute to the community knowledge!
Forwarded from Николай Хитров
Да, у нас есть тесты. А толку?
Супер-мега-гига экслюзивный доступ к записи моего доклада с прошедшего PiterPy. Организаторы разрешили выложить не дожидаясь следующего года. Получилось как всегда холиварно, не всё всем может понравиться, но как минимум советую присмотреться к библиотечкам и статьям/докладам из полезных ссылок. Там немного, но самое годное из того что знаю по этой теме. Куда кидать помидоры и звездочки вы знаете 🙂🙃
https://youtu.be/liECQCFGfkE
Супер-мега-гига экслюзивный доступ к записи моего доклада с прошедшего PiterPy. Организаторы разрешили выложить не дожидаясь следующего года. Получилось как всегда холиварно, не всё всем может понравиться, но как минимум советую присмотреться к библиотечкам и статьям/докладам из полезных ссылок. Там немного, но самое годное из того что знаю по этой теме. Куда кидать помидоры и звездочки вы знаете 🙂🙃
https://youtu.be/liECQCFGfkE
YouTube
Николай Хитров — Да, у нас есть тесты. А толку?
Подробнее о конференции PiterPy: https://jrg.su/QZ6wK1
— —
Скачать презентацию с сайта PiterPy — https://jrg.su/eCB2vc
Кандидаты часто спрашивают на собеседованиях, принято ли в команде писать тесты. И ответ в духе «да, мы пишем тесты» дает некоторую надежду…
— —
Скачать презентацию с сайта PiterPy — https://jrg.su/eCB2vc
Кандидаты часто спрашивают на собеседованиях, принято ли в команде писать тесты. И ответ в духе «да, мы пишем тесты» дает некоторую надежду…
Решил расширить канал ещё одной тематикой - занимательными задачками.
Пока что буду писать про те, которые встречались на тех. собеседованиях.Они не всегда будут адекватные, но что уж есть :)
А начнём, как полагается с классики. Надо объяснить следующее поведение:
Вопрос в том, что здесь творится с ссылками. Разберём самую первую часть. Пробуем получить id объектов:
На вопрос, почему у них одинаковые идентификаторы ответит деталь реализации PyLong_FromLong(для искушенных читать можно читать отсюда ) , которая указывает, что интерпретатор хранит массив целочисленных объектов для всех чисел в диапазоне от -5 до 256. Поэтому, когда мы создаем переменную с числом в этом диапазоне он просто отдает ссылку на уже существующий объект.
Микрооптимизация, при чём очень важная - так уж получилось что числа из этого диапазона используются чаще всего.
В Java есть похожая оптимизация, там такой диапазон составляет от -128 до 127, но есть нюансы .
Второй вопрос отпадает сам собой (будут разные ссылки), но что будет если мы создадим файл с следующим содержимым и запустим его:
А вот это уже нюанс работы нашего REPL.
Каждая написанная нами строка в нём разбирается отдельно. Но при запуске через файл Python имеет возможность применить дополнительные оптимизации для констант, так как он видит сразу весь код - в этом и различие.
А какие ещё неочевидные моменты вы знаете с REPL или int'ами? Пишите в комменты, обсудим :)
#std #задачки
Пока что буду писать про те, которые встречались на тех. собеседованиях.
А начнём, как полагается с классики. Надо объяснить следующее поведение:
>>> a = 256
>>> b = 256
>>> a is b
True # ???
>>> a = 257
>>> b = 257
>>> a is b
False # ???
Вопрос в том, что здесь творится с ссылками. Разберём самую первую часть. Пробуем получить id объектов:
>>> a = 256
>>> b = 256
>>> id(a), id(b)
(2214170730704, 2214170730704)
На вопрос, почему у них одинаковые идентификаторы ответит деталь реализации PyLong_FromLong
Микрооптимизация, при чём очень важная - так уж получилось что числа из этого диапазона используются чаще всего.
Второй вопрос отпадает сам собой (будут разные ссылки), но что будет если мы создадим файл с следующим содержимым и запустим его:
a = 257
b = 257
print(a is b) # True
А вот это уже нюанс работы нашего REPL.
Каждая написанная нами строка в нём разбирается отдельно. Но при запуске через файл Python имеет возможность применить дополнительные оптимизации для констант, так как он видит сразу весь код - в этом и различие.
А какие ещё неочевидные моменты вы знаете с REPL или int'ами? Пишите в комменты, обсудим :)
#std #задачки
Python documentation
Integer Objects
All integers are implemented as “long” integer objects of arbitrary size. On error, most PyLong_As* APIs return(return type)-1 which cannot be distinguished from a number. Use PyErr_Occurred() to d...
Сегодня у нас простенькая задачка, а то пятница, все отдыхать хотят, я понимаю.
Есть следующий код:
Вопрос - что вернется при вызове(ну не просто так же мы собрались, верно?) , но почему?
Ответ, как обычно, есть в документации. Возвращаемое функцией значение определяется последним выполненным return.
Вторым важным аспектом является то, что finally исполняется всегда, поэтому мы и получаем его return.
#std #задачки
Есть следующий код:
def test():
try:
return 1
finally:
return 2
Вопрос - что вернется при вызове
test()
? Все и так на этом моменте понимают, что вернётся 2 Ответ, как обычно, есть в документации. Возвращаемое функцией значение определяется последним выполненным return.
Вторым важным аспектом является то, что finally исполняется всегда, поэтому мы и получаем его return.
raise
, кстати, тоже работать не будет:def test():
try:
raise ValueError()
finally:
return 3
test() # 3
#std #задачки
Python documentation
8. Errors and Exceptions
Until now error messages haven’t been more than mentioned, but if you have tried out the examples you have probably seen some. There are (at least) two distinguishable kinds of errors: syntax error...
Автор Pydantic совершенно недавно начал разрабатывать ещё один проект... И на этот раз он решил сделать UI фронтенд-фреимворк который назвал FastUI.
Если отвечать на вопрос "зачем", то в readme изложены вот такие поинты:
1) Если не хочется разбираться в JS/фронтенд фреимворках и всей их экосистеме;
2) Если хочется декларативно писать фронтенд на питоне, с переиспользуемыми компонентами;
3) FastUI - противоположность GraphQL, но у них одинаковые цели: когда GraphQL позволяет расширять фронтенд без расширения бекенда, FastUI предлагает расширять бекенд без разработки фронтенда;
Под капотом у нас:
- Сам пакет FastUI, который содержит утилиты и сами компоненты. Cами компоненты описаны с использованием Pydantic.
- Так как это всё это работает на react, есть npm пакет @pydantic/fastui, который позволяет повторно использовать механизмы и типы FastUI при реализации собственных компонентов.
- Bootstrap компоненты для FastUI.
- @pydantic/fastui-prebuilt который предоставляет пребилд основной части фронтенда.
Вкратце, как это работает - при помощи Pydantic моделей описываются интерфейсы React компонентов, а дальше их описания отправляются на фронтенд, где по ним отрисовываются компоненты.
Само описание небольшой страницы выглядит как-то так:
Простенько, лаконично, декларативно. Но такой же подход использует Flet, Dash и ещё куча других фреимворков. Очень интересно, взлетит ли это или нет?
Забавно, что мы не кодим на Rust, но всё у нас "fast" - FastAPI, FastUI, FastStream :D
#библиотека
Если отвечать на вопрос "зачем", то в readme изложены вот такие поинты:
1) Если не хочется разбираться в JS/фронтенд фреимворках и всей их экосистеме;
2) Если хочется декларативно писать фронтенд на питоне, с переиспользуемыми компонентами;
3) FastUI - противоположность GraphQL, но у них одинаковые цели: когда GraphQL позволяет расширять фронтенд без расширения бекенда, FastUI предлагает расширять бекенд без разработки фронтенда;
Под капотом у нас:
- Сам пакет FastUI, который содержит утилиты и сами компоненты. Cами компоненты описаны с использованием Pydantic.
- Так как это всё это работает на react, есть npm пакет @pydantic/fastui, который позволяет повторно использовать механизмы и типы FastUI при реализации собственных компонентов.
- Bootstrap компоненты для FastUI.
- @pydantic/fastui-prebuilt который предоставляет пребилд основной части фронтенда.
Вкратце, как это работает - при помощи Pydantic моделей описываются интерфейсы React компонентов, а дальше их описания отправляются на фронтенд, где по ним отрисовываются компоненты.
Само описание небольшой страницы выглядит как-то так:
c.Page(
components=[
c.Heading(text=user.name, level=2),
c.Link(components=[c.Text(text='Back')], on_click=BackEvent()),
c.Details(data=user),
]
)
Простенько, лаконично, декларативно. Но такой же подход использует Flet, Dash и ещё куча других фреимворков. Очень интересно, взлетит ли это или нет?
#библиотека
GitHub
GitHub - pydantic/FastUI: Build better UIs faster.
Build better UIs faster. Contribute to pydantic/FastUI development by creating an account on GitHub.
С наступившим 2024 вас! Сегодня расскажу про dirty-equals.
Этот пакет используется для реализации более читаемых и декларативных проверок на равенство/соответствие, но в полной мере он себя раскрывает при написании тестов.
Как обычно, приведу несколько примеров:
Рекомендую заглянуть в документацию, там таких удобных штук ещё очень много! Ну и изучите исходники - написано не сложно, под капотом используется чуток метаклассов, для изучения темы - самое то!
#библиотека
Этот пакет используется для реализации более читаемых и декларативных проверок на равенство/соответствие, но в полной мере он себя раскрывает при написании тестов.
Как обычно, приведу несколько примеров:
from dirty_equals import *
>>> assert 1 == IsPositive # Всё ок, число положительное
>>> assert -2 == IsPositive # AssertionError
>>> # Проверки можно комбинировать при помощи булевой логики
>>> assert ['a', 'b', 'c'] == HasLen(3) & Contains('a') # Ок, список на 3 элемента, содержит 'a'
>>> # Есть проверка словарей
>>> assert {'a': 1, 'b': 2} == IsDict(a=1, b=2)
>>> # Словари можно проверять частично
>>> assert {'a': 1, 'b': 2, 'c': 3} == IsDict(a=1, b=2).settings(partial=True)
>>> # Или вот так
>>> assert {'a': 1, 'b': 2, 'c': 3} == IsPartialDict(a=1, b=2)
>>> Можно проверять соответствие регуляркам
>>> assert 'test@kiriha.ru' == IsStr(regex=r'^[^@]+@[^@]+\.[^@]+$')
>>> # И так далее...
Рекомендую заглянуть в документацию, там таких удобных штук ещё очень много! Ну и изучите исходники - написано не сложно, под капотом используется чуток метаклассов, для изучения темы - самое то!
#библиотека
Forwarded from Николай Хитров
Тренажер по тайпингу в Python для самых маленьких (и не только)
Для некоторых задач доступны подсказки со ссылками на документацию.
Проверить свои знания по типам сюда
Посмотреть исходный код сюда
Python Type Challenges
, очень прикольный сайт-тренажер для изучения типизации. Выбираешь тему, дописываешь необходимые куски кода и запускаешь проверку линтером. Почти как олимпиадные задачки, только полезные😁Для некоторых задач доступны подсказки со ссылками на документацию.
Проверить свои знания по типам сюда
Посмотреть исходный код сюда
Совсем скоро (релиз запланирован на конец января - начало февраля) выйдет NumPy 2. Список изменений можно прочитать здесь, а информацию по миграции - здесь. Статус и анонсы можно читать здесь.
Изменений в API очень много, поэтому рекомендую зайти в свои проекты и зафиксировать зависимости.
По большей части релиз выглядит как рефакторинг API.
Некоторые функции, модули, константы переместили или удалили, чтобы сделать неимспейсы более удобными и чистыми. Про это можно прочитать в NEP 52.
Релиз так же затронет юзеров с Виндой - теперь int в numpy 64х-разрядный (для 32х систем - 32х-разрядный), хотя ранее, по историческим причинам, связанных Python 2, был эквивалентен типу long в C.
Изменений в API очень много, поэтому рекомендую зайти в свои проекты и зафиксировать зависимости.
По большей части релиз выглядит как рефакторинг API.
Некоторые функции, модули, константы переместили или удалили, чтобы сделать неимспейсы более удобными и чистыми. Про это можно прочитать в NEP 52.
Релиз так же затронет юзеров с Виндой - теперь int в numpy 64х-разрядный (для 32х систем - 32х-разрядный), хотя ранее, по историческим причинам, связанных Python 2, был эквивалентен типу long в C.
GitHub
NumPy 2.0 development status & announcements · Issue #24300 · numpy/numpy
The purpose of this issue is to serve as a brief "umbrella issue" which (a) links out to some key design proposals and other places where design changes and guidance for the 2.0 release a...
Подписчиков набежало, а постов всё так же не было. Буду исправляться!
Сегодня расскажу про deptry - тулзу, которая позволяет находить неиспользованные, транзитивные или отсутствующие зависимости в проекте на Python.
Работает это следующим образом - запускаем утилиту в каталоге с проектом, она сканит все импортированные модули и сравнивает их с тем, что описано в зависимостях. Умеет работать с любым пакетным менеджером который строго следует PEP 621, а так же
Где это может быть полезно? Для себя выявил несколько сценариев:
1. Получили старый проект без зависимостей и пытаемся собрать либы, которые он использует (много раз такое было на фрилансе).
2. Проводим глубокий рефакторинг, трекаем ненужные зависимости и таким образом избавляемся от них.
3. Если кто-то напихал нормальные зависимости в качестве
4. Отлично детектит использование транзитивных зависимостей - это такие пакеты, которые мы не устанавливаем напрямую, но которые устанавливаются при установке другого пакета как его зависимость. Самый простой пример - установка
5. Добавляем в CI и время от времени смотрим отчеты, таким образом поддерживаем зависимости в нормальном виде.
Настраивается достаточно гибко, документация лежит здесь.
#утилита
Сегодня расскажу про deptry - тулзу, которая позволяет находить неиспользованные, транзитивные или отсутствующие зависимости в проекте на Python.
Работает это следующим образом - запускаем утилиту в каталоге с проектом, она сканит все импортированные модули и сравнивает их с тем, что описано в зависимостях. Умеет работать с любым пакетным менеджером который строго следует PEP 621, а так же
pyproject.toml
от Poetry и PDM. Ну и обычный requirements.txt
тоже поддерживается!Где это может быть полезно? Для себя выявил несколько сценариев:
1. Получили старый проект без зависимостей и пытаемся собрать либы, которые он использует (много раз такое было на фрилансе).
2. Проводим глубокий рефакторинг, трекаем ненужные зависимости и таким образом избавляемся от них.
3. Если кто-то напихал нормальные зависимости в качестве
dev
зависимостей, утилита тоже это покажет.4. Отлично детектит использование транзитивных зависимостей - это такие пакеты, которые мы не устанавливаем напрямую, но которые устанавливаются при установке другого пакета как его зависимость. Самый простой пример - установка
sqlparse
при установке Django
. Такие зависимости должны быть указаны явно.5. Добавляем в CI и время от времени смотрим отчеты, таким образом поддерживаем зависимости в нормальном виде.
Настраивается достаточно гибко, документация лежит здесь.
#утилита
GitHub
GitHub - fpgmaas/deptry: Find unused, missing and transitive dependencies in a Python project.
Find unused, missing and transitive dependencies in a Python project. - fpgmaas/deptry
Forwarded from Советы разработчикам (python и не только)
Dishka - IoC-контейнер для Python
Когда мы следуем подходу Dependency Injection, а особенно - слоистой архитектуре, у нас образуется отдельная группа функций и классов, выполняющих только одну задачу - создание других объектов. Такой код лучше держать поближе к main, так как он связывает воедино разные части приложения и связан с конфигурацией запуска.
В сложном приложении такой компонент может содержать большое количество функций, контролировать как создание, так и корректную очистку объектов и, что самое главное, их взаимосвязь. Для упрощения работы с такими фабриками придумали отдельный тип библиотек - IoC-контейнеры (DI-фреймворки).
В Python меня долго не устраивали существующие контейнеры и я решил сделать свой:
Хочу представить вам Dishka
Цель этого проекта - предоставить простой и удобный IoC-контейнер, который сможет забрать всю работу с зависимостями. Мне кажется, на текущий момент это самый функциональный вариант контейнера, имеющий при этом самое простое API.
• Вы можете использовать его с любым фреймворком, но для некоторых мы уже подготовили хелперы
• Для создания зависимости можно указать отдельную функцию или использовать
• Зависимости имеют ограниченное время жизни (скоуп) и вы сами управляете им
• Зависимости кэшируются, поэтому один и тот же объект может быть переиспользован пока он жив. Так можно передать одно соединение с БД в несколько гейтвеев
• Фабрики зависимостей можно группировать в классы и компоненты, что позволяет делать контейнер модульным
• Можно декорировать объекты, использовать один объект для нескольких типов
• При старте проверяется корректность конфигурации контейнера, что позволяет исключить многие ошибки
Что значит версия 1.0?
У библиотеки было 9 промежуточных релизов, мы ради объявить, что закончена вся работа по стабилизации её интерфейса и исправлению ошибок. И у нас есть планы по развитию, уникальные фичи сами себя не напишут.
Будем рады новым пользователям, багрепортам, запросам фич и звездам на гитхабе
• Github
• Pypi
• Документация
Когда мы следуем подходу Dependency Injection, а особенно - слоистой архитектуре, у нас образуется отдельная группа функций и классов, выполняющих только одну задачу - создание других объектов. Такой код лучше держать поближе к main, так как он связывает воедино разные части приложения и связан с конфигурацией запуска.
В сложном приложении такой компонент может содержать большое количество функций, контролировать как создание, так и корректную очистку объектов и, что самое главное, их взаимосвязь. Для упрощения работы с такими фабриками придумали отдельный тип библиотек - IoC-контейнеры (DI-фреймворки).
В Python меня долго не устраивали существующие контейнеры и я решил сделать свой:
Хочу представить вам Dishka
1.0
Цель этого проекта - предоставить простой и удобный IoC-контейнер, который сможет забрать всю работу с зависимостями. Мне кажется, на текущий момент это самый функциональный вариант контейнера, имеющий при этом самое простое API.
• Вы можете использовать его с любым фреймворком, но для некоторых мы уже подготовили хелперы
• Для создания зависимости можно указать отдельную функцию или использовать
__init__
класса• Зависимости имеют ограниченное время жизни (скоуп) и вы сами управляете им
• Зависимости кэшируются, поэтому один и тот же объект может быть переиспользован пока он жив. Так можно передать одно соединение с БД в несколько гейтвеев
• Фабрики зависимостей можно группировать в классы и компоненты, что позволяет делать контейнер модульным
• Можно декорировать объекты, использовать один объект для нескольких типов
• При старте проверяется корректность конфигурации контейнера, что позволяет исключить многие ошибки
Что значит версия 1.0?
У библиотеки было 9 промежуточных релизов, мы ради объявить, что закончена вся работа по стабилизации её интерфейса и исправлению ошибок. И у нас есть планы по развитию, уникальные фичи сами себя не напишут.
Будем рады новым пользователям, багрепортам, запросам фич и звездам на гитхабе
• Github
• Pypi
• Документация
Там в Python 3.12 добавили нашумевший PEP 659, а у меня пет-проект один давно не обновлялся, и так уж звёзды сошлись, что я сижу второй день обновляю его на 3.12
Задача - есть функционал, который под капотом имеет некоторый класс следующего вида:
Мы определяем новые классы наследуясь от
Ну прямо дженерик напрашивается! Тем более в 3.12 их завезли, красивые:
Встаёт вопрос, а как нам получить наш тип из дженерика?
Для начала, получим
Ещё можно это сделать с помощью
Теперь надо получить получить сам тип в дженерике. В этом нам поможет
Теперь в методе
Проверяем:
Вы восхитительны!
Кстати, эта же штука должна работать ещё вроде как аж с 3.8, так как в нём именно был добавлен
Ага,
#рецепт #std
Задача - есть функционал, который под капотом имеет некоторый класс следующего вида:
class BaseFunction:
serialize_to: None
def serialize(self, data: dict) -> serialize_to:
pass # тут мы используем наш serialize_to
@dataclass
class ModelA:
x: str
class FunctionA(BaseFunction):
serialize_to: ModelA
Мы определяем новые классы наследуясь от
BaseFunction
, переопределяем в них serialize_to
и вызываем serialize
который делает нам инстанс serialize_to
. Ну прямо дженерик напрашивается! Тем более в 3.12 их завезли, красивые:
class BaseFunction[T]:
def serialize(self, data: dict) -> T:
pass # тут мы используем наш serialize_to
class FunctionA(BaseFunction[ModelA]):
pass
Встаёт вопрос, а как нам получить наш тип из дженерика?
Для начала, получим
__orig_bases__[0]
- он вернёт нам классы, от которых мы наследовались. Так как нам нужен только наш первый класс, мы указываем [0]
:>>> FunctionA.__orig_bases__
__main__.BaseFunction[__main__.ModelA]
Ещё можно это сделать с помощью
get_original_bases
из types
, но его добавили только в 3.12 (почему я об этом сказал - узнаете ниже).Теперь надо получить получить сам тип в дженерике. В этом нам поможет
typing.get_args
, который получает все аргументы типа. Дополнительно укажем, что нам нужен первый тип:>>> get_args(FunctionA.__orig_bases__[0])[0]
<class '__main__.ModelA'>
Теперь в методе
serialize
класса BaseFunction[T]
можно написать штуку, которая автоматически сериализует наши данные:def serialize(self, data: dict) -> T:
type_from_generic = get_args(self.__class__.__orig_bases__[0])[0]
return type_from_generic(**data)
Проверяем:
>>> f = FunctionA()
>>> f.serialize(data={"x": 1})
ModelA(x=1)
Вы восхитительны!
Кстати, эта же штука должна работать ещё вроде как аж с 3.8, так как в нём именно был добавлен
__orig_bases__
(PEP 560), ну и под капотом у новых дженериков используется...>>> FunctionA.__mro__
(<class '__main__.FunctionA'>, <class '__main__.BaseFunction'>, <class 'typing.Generic'>, <class 'object'>)
Ага,
typing.Generic
:)#рецепт #std
Да, оно существует.
Под капотом низкоуровневая магия, из самого понятного - оно позволяет создавать поддельные объекты на куче. Можно создать байтовый массив с базовым адресом 0 и длинной
Такая техника, кстати, используется в эксплоитах движков javascript. Парочкой похожих эксплоитов уже давно хакают PS4.
Под капотом низкоуровневая магия, из самого понятного - оно позволяет создавать поддельные объекты на куче. Можно создать байтовый массив с базовым адресом 0 и длинной
SSIZE_MAX
, что даст доступ к сырой памяти, на чтение и запись.Такая техника, кстати, используется в эксплоитах движков javascript. Парочкой похожих эксплоитов уже давно хакают PS4.
Итак, ко мне пришли ребята из Podlodka Python Crew и предложили разыграть один бесплатный билет на новый сезон их конференции, где участников с 3 по 7 июня будет ждать целая неделя онлаин-воркшопов и много докладов по теме инфраструктуры.
Из интересного:
— К ним придёт разработчик FastStream, про который я неоднократно рассказывал здесь, покажет насколько удобно можно работать с Kafka, RabbitMQ, NATS и другими брокерами.
— Для енжоеров микросервисной архитектуры расскажут и покажут, как гарантировать консистентную работу всей системы при помощи паттерна "transactional outbox". Будет демо-стенд и реализация на практике.
— Приложение без метрик - плохое приложение. Покажут как собирать и анализировать данные, чтобы всегда быть в курсе состояния системы.
— Так же будут истории от экспертов про фейлы с инфраструктурой и как их можно избежать.
А так же нетворкинг, много практических примеров и дискуссии!
Чтобы попытать счастье, постите под этим постом любой мем про наш любимый язык до 02.06.24. Самый залайканный станет победителем - ему и отправится билет.
А если пытать счастье не хочется - вот вам скидка в 500 рублей по промокоду `podlodka_boxwithpython`
Ждем всех, тыкай чтобы попасть 😎
Из интересного:
— К ним придёт разработчик FastStream, про который я неоднократно рассказывал здесь, покажет насколько удобно можно работать с Kafka, RabbitMQ, NATS и другими брокерами.
— Для енжоеров микросервисной архитектуры расскажут и покажут, как гарантировать консистентную работу всей системы при помощи паттерна "transactional outbox". Будет демо-стенд и реализация на практике.
— Приложение без метрик - плохое приложение. Покажут как собирать и анализировать данные, чтобы всегда быть в курсе состояния системы.
— Так же будут истории от экспертов про фейлы с инфраструктурой и как их можно избежать.
А так же нетворкинг, много практических примеров и дискуссии!
Чтобы попытать счастье, постите под этим постом любой мем про наш любимый язык до 02.06.24. Самый залайканный станет победителем - ему и отправится билет.
Ждем всех, тыкай чтобы попасть 😎
Коробка с питоном
Итак, ко мне пришли ребята из Podlodka Python Crew и предложили разыграть один бесплатный билет на новый сезон их конференции, где участников с 3 по 7 июня будет ждать целая неделя онлаин-воркшопов и много докладов по теме инфраструктуры. Из интересного:…
Самым залайканным оказался вот этот мемас, приз отправлен автору!
Сегодня расскажу про модуль, который поможет остановить время в ваших тестах и не только - FreezeGun
Сначала история из жизни.
Недавно мне принесли скрипт, который скрапил некоторую информацию с онлаин-каталога на текущий момент. Задачей было заставить его скрапить данные до определенного момента.
В нём было очень много вызовов
Поэтому я такой хоп:
И всё работает!
Но вы так не делайте, конечно, это самый настоящий подпор костылём, мне вообще повезло, что оно заработало.
Или делайте если надо, разрешаю.
В основном этот пакет используют для тестов и как было понятно с примера выше - он позволяет "заморозить" время на определенном моменте.
Проверить истечение подписки, корректность фильтров, расчёт на определенное время - этот пакет позволит сделать всё это всего в пару строк кода!
Есть возможность использовать декоратор вместо контекстного менеджера:
А если оба варианта вам не нравятся, и хочется более гибкого управления - можно руками задавать когда время остановится и возобновится:
С асинком, кстати, тоже работает. Библиотека довольно фичастая, так что за примерами использования можно проследовать в тесты.
Сначала история из жизни.
Недавно мне принесли скрипт, который скрапил некоторую информацию с онлаин-каталога на текущий момент. Задачей было заставить его скрапить данные до определенного момента.
В нём было очень много вызовов
datetime.now()
(пагинация по датам, ага), перепиливать все это мне не очень хотелось, а результат хотели вчера. Поэтому я такой хоп:
from freezegun import freeze_time
with freeze_time("01-08-24"):
result = call_api()
И всё работает!
Но вы так не делайте, конечно, это самый настоящий подпор костылём, мне вообще повезло, что оно заработало.
В основном этот пакет используют для тестов и как было понятно с примера выше - он позволяет "заморозить" время на определенном моменте.
Проверить истечение подписки, корректность фильтров, расчёт на определенное время - этот пакет позволит сделать всё это всего в пару строк кода!
Есть возможность использовать декоратор вместо контекстного менеджера:
@freeze_time("2012-01-14")
def test():
assert datetime.datetime.now() == datetime.datetime(2012, 1, 14)
А если оба варианта вам не нравятся, и хочется более гибкого управления - можно руками задавать когда время остановится и возобновится:
freezer = freeze_time("2012-01-14 12:00:01")
freezer.start()
assert datetime.datetime.now() == datetime.datetime(2012, 1, 14, 12, 0, 1)
freezer.stop()
С асинком, кстати, тоже работает. Библиотека довольно фичастая, так что за примерами использования можно проследовать в тесты.
GitHub
GitHub - spulec/freezegun: Let your Python tests travel through time
Let your Python tests travel through time. Contribute to spulec/freezegun development by creating an account on GitHub.