Share
Embed
Transcript
249 slides
-
Celery celery -A project worker -Q=default --loglevel=info Queue “default” Task
Worker Task Task Queue “=default” -
Celery from argparse import ArgumentParser parser = ArgumentParser() parser.add_argument('--queues', '-Q')
args = parser.parse_args() print(args.queues) • > test.py --queues value 'value' • > test.py --queues=value 'value' • > test.py -Q value 'value' • > test.py -Qvalue 'value' • > test.py -Q=value 'value' • > test.py -Q=”=value” '=value' • > test.py -Q"=value" 'value' -
Celery from argparse import ArgumentParser parser = ArgumentParser() parser.add_argument('--queues', '-Q')
args = parser.parse_args() print(args.queues) • > test.py --queues value 'value' • > test.py --queues=value 'value' • > test.py -Q value 'value' • > test.py -Qvalue 'value' • > test.py -Q=value 'value' • > test.py -Q=”=value” '=value' • > test.py -Q"=value" 'value' -
Celery from argparse import ArgumentParser parser = ArgumentParser() parser.add_argument('--queues', '-Q')
args = parser.parse_args() print(args.queues) • > test.py --queues value value • > test.py --queues=value 'value' • > test.py -Q value 'value' • > test.py -Qvalue 'value' • > test.py -Q=value 'value' • > test.py -Q=”=value” '=value' • > test.py -Q"=value" 'value' -
Celery from argparse import ArgumentParser parser = ArgumentParser() parser.add_argument('--queues', '-Q')
args = parser.parse_args() print(args.queues) • > test.py --queues value value • > test.py --queues=value 'value' • > test.py -Q value 'value' • > test.py -Qvalue 'value' • > test.py -Q=value 'value' • > test.py -Q=”=value” '=value' • > test.py -Q"=value" 'value' -
Celery from argparse import ArgumentParser parser = ArgumentParser() parser.add_argument('--queues', '-Q')
args = parser.parse_args() print(args.queues) • > test.py --queues value value • > test.py --queues=value value • > test.py -Q value 'value' • > test.py -Qvalue 'value' • > test.py -Q=value 'value' • > test.py -Q=”=value” '=value' • > test.py -Q"=value" 'value' -
Celery from argparse import ArgumentParser parser = ArgumentParser() parser.add_argument('--queues', '-Q')
args = parser.parse_args() print(args.queues) • > test.py --queues value value • > test.py --queues=value value • > test.py -Q value 'value' • > test.py -Qvalue 'value' • > test.py -Q=value 'value' • > test.py -Q=”=value” '=value' • > test.py -Q"=value" 'value' -
Celery from argparse import ArgumentParser parser = ArgumentParser() parser.add_argument('--queues', '-Q')
args = parser.parse_args() print(args.queues) • > test.py --queues value value • > test.py --queues=value value • > test.py -Q value value • > test.py -Qvalue 'value' • > test.py -Q=value 'value' • > test.py -Q=”=value” '=value' • > test.py -Q"=value" 'value' -
Celery from argparse import ArgumentParser parser = ArgumentParser() parser.add_argument('--queues', '-Q')
args = parser.parse_args() print(args.queues) • > test.py --queues value value • > test.py --queues=value value • > test.py -Q value value • > test.py -Qvalue 'value' • > test.py -Q=value 'value' • > test.py -Q=”=value” '=value' • > test.py -Q"=value" 'value' -
Celery from argparse import ArgumentParser parser = ArgumentParser() parser.add_argument('--queues', '-Q')
args = parser.parse_args() print(args.queues) • > test.py --queues value value • > test.py --queues=value value • > test.py -Q value value • > test.py -Qvalue value • > test.py -Q=value 'value' • > test.py -Q=”=value” '=value' • > test.py -Q"=value" 'value' -
Celery from argparse import ArgumentParser parser = ArgumentParser() parser.add_argument('--queues', '-Q')
args = parser.parse_args() print(args.queues) • > test.py --queues value value • > test.py --queues=value value • > test.py -Q value value • > test.py -Qvalue value • > test.py -Q=value 'value' • > test.py -Q=”=value” '=value' • > test.py -Q"=value" 'value' -
Celery from argparse import ArgumentParser parser = ArgumentParser() parser.add_argument('--queues', '-Q')
args = parser.parse_args() print(args.queues) • > test.py --queues value value • > test.py --queues=value value • > test.py -Q value value • > test.py -Qvalue value • > test.py -Q=value value • > test.py -Q=”=value” '=value' • > test.py -Q"=value" 'value' -
Celery from argparse import ArgumentParser parser = ArgumentParser() parser.add_argument('--queues', '-Q')
args = parser.parse_args() print(args.queues) • > test.py --queues value value • > test.py --queues=value value • > test.py -Q value value • > test.py -Qvalue value • > test.py -Q=value value • > test.py -Q=”=value” '=value' • > test.py -Q"=value" 'value' -
Celery from argparse import ArgumentParser parser = ArgumentParser() parser.add_argument('--queues', '-Q')
args = parser.parse_args() print(args.queues) • > test.py --queues value value • > test.py --queues=value value • > test.py -Q value value • > test.py -Qvalue value • > test.py -Q=value value • > test.py -Q=”=value” =value • > test.py -Q"=value" 'value' -
Celery from argparse import ArgumentParser parser = ArgumentParser() parser.add_argument('--queues', '-Q')
args = parser.parse_args() print(args.queues) • > test.py --queues value value • > test.py --queues=value value • > test.py -Q value value • > test.py -Qvalue value • > test.py -Q=value value • > test.py -Q=”=value” =value • > test.py -Q"=value" 'value' -
Celery from argparse import ArgumentParser parser = ArgumentParser() parser.add_argument('--queues', '-Q')
args = parser.parse_args() print(args.queues) • > test.py --queues value value • > test.py --queues=value value • > test.py -Q value value • > test.py -Qvalue value • > test.py -Q=value value • > test.py -Q=”=value” =value • > test.py -Q"=value" value -
Celery from argparse import ArgumentParser parser = ArgumentParser() parser.add_argument('--queues', '-Q')
args = parser.parse_args() print(args.queues) • > test.py --queues value value • > test.py --queues=value value • > test.py -Q value value • > test.py -Qvalue value • > test.py -Q=value value • > test.py -Q=”=value” =value • > test.py -Q"=value" value -
Celery import click @click.command() @click.option('--queues', '-Q') def echo(queues): print(queues) if
__name__ == '__main__': echo() • > test.py --queues value value • > test.py --queues=value value • > test.py -Q value value • > test.py -Qvalue value • > test.py -Q=value =value • > test.py -Q=”=value” ==value • > test.py -Q"=value" =value -
Django • Всё покрыто тестами # settings.py SUBSCRIPTION = {
‘duration’: timedelta(days=30), ‘price’: Decimal(100), } # service.py subscriptions = getattr( settings, ‘SUBSCRIPTIONS’, DEFAULT_SETTINGS ) -
Django • Всё покрыто тестами • Выкатываю в прод -
работает не так, как ожидал # settings.py SUBSCRIPTION = { ‘duration’: timedelta(days=30), ‘price’: Decimal(100), } # service.py subscriptions = getattr( settings, ‘SUBSCRIPTIONS’, DEFAULT_SETTINGS ) -
Django • Всё покрыто тестами • Выкатываю в прод -
работает не так, как ожидал • Никаких ошибок нет # settings.py SUBSCRIPTION = { ‘duration’: timedelta(days=30), ‘price’: Decimal(100), } # service.py subscriptions = getattr( settings, ‘SUBSCRIPTIONS’, DEFAULT_SETTINGS ) -
Django • Всё покрыто тестами • Выкатываю в прод -
работает не так, как ожидал • Никаких ошибок нет • В чём ошибка? # settings.py SUBSCRIPTION = { ‘duration’: timedelta(days=30), ‘price’: Decimal(100), } # service.py subscriptions = getattr( settings, ‘SUBSCRIPTIONS’, DEFAULT_SETTINGS ) -
Django • Всё покрыто тестами • Выкатываю в прод -
работает не так, как ожидал • Никаких ошибок нет • В чём ошибка? • Проверяю - забыл одну букву # settings.py SUBSCRIPTIONS = { ‘duration’: timedelta(days=30), ‘price’: Decimal(100), } # service.py subscriptions = getattr( settings, ‘SUBSCRIPTIONS’, DEFAULT_SETTINGS ) -
Sqlalchemy • Пытаюсь записать несколько строк в БД (psycopg.errors.UniqueViolation) duplicate
key value violates unique constraint "ix_tag_name" DETAIL: Key (lower('name'::text))=(name) already exists. [SQL: INSERT INTO tag (name, id) VALUES (%(name)s::VARCHAR, nextval('tag_id_seq')) RETURNING tag.id] [parameters: {'name': 'ai'}] -
Sqlalchemy • Пытаюсь записать несколько строк в БД • Получаю
ошибку, что такая строка уже существует (psycopg.errors.UniqueViolation) duplicate key value violates unique constraint "ix_tag_name" DETAIL: Key (lower('name'::text))=(name) already exists. [SQL: INSERT INTO tag (name, id) VALUES (%(name)s::VARCHAR, nextval('tag_id_seq')) RETURNING tag.id] [parameters: {'name': 'ai'}] -
Sqlalchemy • Пытаюсь записать несколько строк в БД • Получаю
ошибку, что такая строка уже существует • А строки разные! (psycopg.errors.UniqueViolation) duplicate key value violates unique constraint "ix_tag_name" DETAIL: Key (lower('name'::text))=(name) already exists. [SQL: INSERT INTO tag (name, id) VALUES (%(name)s::VARCHAR, nextval('tag_id_seq')) RETURNING tag.id] [parameters: {'name': 'ai'}] -
Sqlalchemy • Пытаюсь записать несколько строк в БД • Получаю
ошибку, что такая строка уже существует • А строки разные! • Смотрю, что уже есть в таблице - а там ничего! -
Sqlalchemy class Tag(BigIntBase): name: Mapped[str] __table_args__ = ( Index( "ix_tag_name",
func.lower('name'), unique=True), ) • Пытаюсь записать несколько строк в БД • Получаю ошибку, что такая строка уже существует • А строки разные! • Смотрю, что уже есть в таблице - а там ничего! • А потому что “name” - это не название колонки, а строка! -
Лучшее - враг хорошего • Однажды я решил, что использовать
tuple[int, int] для интервалов - это не по- сеньорски epoch = (100, 200) jobs = Jobs.objects.filter( block__gte=epoch[0], block__lt=epoch[1], ) .order_by("block") -
Лучшее - враг хорошего • Однажды я решил, что использовать
tuple[int, int] для интервалов - это не по- сеньорски • Есть же специальный тип: range epoch = (100, 200) jobs = Jobs.objects.filter( block__gte=epoch[0], block__lt=epoch[1], ) .order_by("block") -
Лучшее - враг хорошего • Однажды я решил, что использовать
tuple[int, int] для интервалов - это не по- сеньорски • Есть же специальный тип: range • Время рефакторинга! epoch = (100, 200) jobs = Jobs.objects.filter( block__gte=epoch[0], block__lt=epoch[1], ) .order_by("block") -
Лучшее - враг хорошего • Однажды я решил, что использовать
tuple[int, int] для интервалов - это не по- сеньорски • Есть же специальный тип: range • Время рефакторинга! • Всё сломалось epoch = range(100, 201) jobs = Jobs.objects.filter( block__gte=epoch[0], block__lt=epoch[1], ) .order_by("block") -
Лучшее - враг хорошего • Однажды я решил, что использовать
tuple[int, int] для интервалов - это не по- сеньорски • Есть же специальный тип: range • Время рефакторинга! • Всё сломалось • А потому что [1] теперь не то, чем было! epoch = range(100, 201) jobs = Jobs.objects.filter( block__gte=epoch[0], block__lt=epoch[1], ) .order_by("block") -
Лучшее - враг хорошего • Однажды я решил, что использовать
tuple[int, int] для интервалов - это не по- сеньорски • Есть же специальный тип: range • Время рефакторинга! • Всё сломалось • А потому что [1] теперь не то, чем было! epoch = range(100, 201) jobs = Jobs.objects.filter( block__gte=epoch.start, block__lt=epoch.stop, ) .order_by("block") -
#!/bin/bash • Почему нельзя ставить флаги после “#!” ? #!/bin/bash
-ex false echo "Shouldn’t execute" > ./script.sh + false > bash script.sh Shouldn't execute -
#!/bin/bash • Почему нельзя ставить флаги после “#!” ? #!/bin/bash
-e false echo "Shouldn’t execute" > ./script.sh (nothing) > bash script.sh Shouldn't execute -
#!/bin/bash • Почему нельзя ставить флаги после “#!” ? #!/bin/bash
-e false echo "Shouldn’t execute" > ./script.sh (nothing) > bash script.sh Shouldn't execute -
#!/bin/bash • Почему нельзя ставить флаги после “#!” ? #!/bin/bash
set -e false echo "Shouldn’t execute" > ./script.sh (nothing) > bash script.sh (nothing) -
Зачем вообще версии? ZeroVer! • Иногда устаёшь от этих SemVer,
LTS, v2024.08, и хочется просто писать код. 1.0 1.0.0-rc1 18.0 2024.08 0.0.1 0.1.0dev 0.9999999 0.0 -
Зачем вообще версии? ZeroVer! • Иногда устаёшь от этих SemVer,
LTS, v2024.08, и хочется просто писать код. 1.0 1.0.0-rc1 18.0 2024.08 0.0.1 0.1.0dev 0.9999999 0.0 React native 0.75.2 Three.js r167 FastAPI 0.112.1 Hugo 0.133.1 Ruff 0.6.2 Zoxide 0.9.4 Numba 0.60.0 … -
У нас есть git! • Мы как волшебники - можем
путешествовать во времени и создавать параллельные вселенные -
У нас есть git! • Мы как волшебники - можем
путешествовать во времени и создавать параллельные вселенные • Просто смотрим на ветки VCS - и всегда всё понятно -
У нас есть git! • Мы как волшебники - можем
путешествовать во времени и создавать параллельные вселенные • Просто смотрим на ветки VCS - и всегда всё понятно -
У нас есть git! • Мы как волшебники - можем
путешествовать во времени и создавать параллельные вселенные • Просто смотрим на ветки VCS - и всегда всё понятно -
У нас есть git! • Мы как волшебники - можем
путешествовать во времени и создавать параллельные вселенные • Просто смотрим на ветки VCS - и всегда всё понятно -
У нас есть git! • Мы как волшебники - можем
путешествовать во времени и создавать параллельные вселенные • Просто смотрим на ветки VCS - и всегда всё понятно -
У нас есть git! • Мы как волшебники - можем
путешествовать во времени и создавать параллельные вселенные • Просто смотрим на ветки VCS - и всегда всё понятно -
У нас есть git! • Мы как волшебники - можем
путешествовать во времени и создавать параллельные вселенные • Просто смотрим на ветки VCS - и всегда всё понятно -
У нас есть git! • Мы как волшебники - можем
путешествовать во времени и создавать параллельные вселенные • Просто смотрим на ветки VCS - и всегда всё понятно -
У нас есть git! • Мы как волшебники - можем
путешествовать во времени и создавать параллельные вселенные • Просто смотрим на ветки VCS - и всегда всё понятно • А если непонятно - наши коллеги всегда напишут понятные сообщения -
У нас есть git! • Мы как волшебники - можем
путешествовать во времени и создавать параллельные вселенные • Просто смотрим на ветки VCS - и всегда всё понятно • А если непонятно - наши коллеги всегда напишут понятные сообщения -
У нас есть git! • Мы как волшебники - можем
путешествовать во времени и создавать параллельные вселенные • Просто смотрим на ветки VCS - и всегда всё понятно • А если непонятно - наши коллеги всегда напишут понятные сообщения -
У нас есть git! • Мы как волшебники - можем
путешествовать во времени и создавать параллельные вселенные • Просто смотрим на ветки VCS - и всегда всё понятно • А если непонятно - наши коллеги всегда напишут понятные сообщения -
У нас есть git! • Мы как волшебники - можем
путешествовать во времени и создавать параллельные вселенные • Просто смотрим на ветки VCS - и всегда всё понятно • А если непонятно - наши коллеги всегда напишут понятные сообщения -
У нас есть git! • Мы как волшебники - можем
путешествовать во времени и создавать параллельные вселенные • Просто смотрим на ветки VCS - и всегда всё понятно • А если непонятно - наши коллеги всегда напишут понятные сообщения -
У нас есть git! • Мы как волшебники - можем
путешествовать во времени и создавать параллельные вселенные • Просто смотрим на ветки VCS - и всегда всё понятно • А если непонятно - наши коллеги всегда напишут понятные сообщения -
У нас есть git! • Мы как волшебники - можем
путешествовать во времени и создавать параллельные вселенные • Просто смотрим на ветки VCS - и всегда всё понятно • А если непонятно - наши коллеги всегда напишут понятные сообщения -
У нас есть git! • Мы как волшебники - можем
путешествовать во времени и создавать параллельные вселенные • Просто смотрим на ветки VCS - и всегда всё понятно • А если непонятно - наши коллеги всегда напишут понятные сообщения -
У нас есть git! • Мы как волшебники - можем
путешествовать во времени и создавать параллельные вселенные • Просто смотрим на ветки VCS - и всегда всё понятно • А если непонятно - наши коллеги всегда напишут понятные сообщения -
У нас есть git! • Мы как волшебники - можем
путешествовать во времени и создавать параллельные вселенные • Просто смотрим на ветки VCS - и всегда всё понятно • А если непонятно - наши коллеги всегда напишут понятные сообщения -
У нас есть git! • Мы как волшебники - можем
путешествовать во времени и создавать параллельные вселенные • Просто смотрим на ветки VCS - и всегда всё понятно • А если непонятно - наши коллеги всегда напишут понятные сообщения -
У нас есть git! • Мы как волшебники - можем
путешествовать во времени и создавать параллельные вселенные • Просто смотрим на ветки VCS - и всегда всё понятно • А если непонятно - наши коллеги всегда напишут понятные сообщения -
Langchain: усидеть на двух стульях Патч века: - historic_messages =
config["configurable"]["message_history"].messages + historic_messages = await config["configurable"]["message_history"].aget_messages() Почему? • Копипаста • Метод называется “messages”, а не “get_messages” -
Bittensor • Блокчейн, много $$$ • Очень любят исключения •
Но ещё больше любят возвращать результат -
Bittensor • Блокчейн, много $$$ • Очень любят исключения •
Но ещё больше любят возвращать результат • Но коды ошибок - это как-то сложно -
Bittensor • Блокчейн, много $$$ • Очень любят исключения •
Но ещё больше любят возвращать результат • Но коды ошибок - это как-то сложно • Поэтому… -
Bittensor • Блокчейн, много $$$ • Очень любят исключения •
Но ещё больше любят возвращать результат • Но коды ошибок - это как-то сложно • Поэтому… is_success, msg = do_stuff() -
Bittensor • Блокчейн, много $$$ • Очень любят исключения •
Но ещё больше любят возвращать результат • Но коды ошибок - это как-то сложно • Поэтому… try: is_success, msg = do_stuff() if not is_success: exc_class = parse_error(msg) raise exc_class(msg) except Exception: # handle exception -
Bittensor • Блокчейн, много $$$ • Очень любят исключения •
Но ещё больше любят возвращать результат • Но коды ошибок - это как-то сложно • Поэтому… try: is_success, msg = do_stuff() if not is_success: exc_class = parse_error(msg) raise exc_class(msg) except Exception: # handle exception -
Это обычный bash set -euxo pipefail SCRIPT_DIR="$( cd "$( dirname
"${BASH_SOURCE[0]}" )" &> /dev/null && pwd )" -
Это обычный код • Посылаем задание • После - замеряем
время, за сколько нам придёт ответ • Что может пойти не так? before_time = now() await send_request(job) start_time = now() response = await ws.recv() response_time = now() score = response_time - start_time -
Это обычный код • Посылаем задание • После - замеряем
время, за сколько нам придёт ответ • Что может пойти не так? before_time = now() await send_request(job) start_time = now() response = await ws.recv() response_time = now() score = response_time - start_time -
Это обычный npm • Хотите установить фреймворк? • Подождите пару
минут, пока скачаются сотни зависимостей • Не переживайте! Вряд ли хоть в одной из них есть уязвимости > npx create-next-app added 360 packages in 3m > npx create-remix 631 > npx create-gatsby 864 > npx create-react-app 1480 -
Это обычный npm • Хотите установить фреймворк? • Подождите пару
минут, пока скачаются сотни зависимостей • Не переживайте! Вряд ли хоть в одной из них есть уязвимости > npx create-next-app added 360 packages in 3m > npx create-remix 631 > npx create-gatsby 864 > npx create-react-app 1480 -
Это обычный npm • Хотите установить фреймворк? • Подождите пару
минут, пока скачаются сотни зависимостей • Не переживайте! Вряд ли хоть в одной из них есть уязвимости > npx create-next-app added 360 packages in 3m > npx create-remix 631 > npx create-gatsby 864 > npx create-react-app 1480 -
Это обычный npm • Хотите установить фреймворк? • Подождите пару
минут, пока скачаются сотни зависимостей • Не переживайте! Вряд ли хоть в одной из них есть уязвимости > npx create-next-app added 360 packages in 3m > npx create-remix 631 > npx create-gatsby 864 > npx create-react-app 1480 -
Бэкап postgres • Делаем бэкап: pg_dump postgres > dump.sql •
Восстанавливаемся из бэкапа: pg_restore postgres < dump.sql -
Бэкап postgres • Делаем бэкап: pg_dump postgres > dump.sql •
Восстанавливаемся из бэкапа: pg_restore postgres < dump.sql pg_restore: error: input file does not appear to be a valid archive -
Бэкап postgres • Делаем бэкап: pg_dump postgres > dump.sql •
Восстанавливаемся из бэкапа: pg_restore postgres < dump.sql pg_restore: error: input file does not appear to be a valid archive • psql postgres < dump.sql -
Dockerfile args • В Docker при сборке контейнера можно передавать
параметры • docker build --build-arg VERSION=123 FROM alpine AS base RUN echo "Base image: $VERSION" FROM base ARG VERSION RUN echo "Child image: $VERSION" #5 Base image: #6 Child image: 123 1 2 -
Dockerfile args • В Docker при сборке контейнера можно передавать
параметры • docker build --build-arg VERSION=123 FROM alpine AS base ARG VERSION RUN echo "Base image: $VERSION" FROM base RUN echo "Child image: $VERSION" #5 Base image: 123 #6 Child image: 123 1 2 -
Dockerfile args • В Docker при сборке контейнера можно передавать
параметры • docker build --build-arg VERSION=123 ARG VERSION FROM alpine:{$VERSION} AS base RUN echo "Base image: $VERSION" FROM base RUN echo "Child image: $VERSION" #5 Base image: #6 Child image: 1 2 -
Dockerfile args • В Docker при сборке контейнера можно передавать
параметры • docker build --build-arg VERSION=123 ARG VERSION FROM alpine:{$VERSION} AS base RUN echo "Base image: $VERSION" FROM base RUN echo "Child image: $VERSION" #5 Base image: #6 Child image: 1 2 -
Dockerfile args • В Docker при сборке контейнера можно передавать
параметры • docker build --build-arg VERSION=123 ARG VERSION FROM alpine:{$VERSION} AS base ARG VERSION RUN echo "Base image: $VERSION" FROM base RUN echo "Child image: $VERSION" #5 Base image: 123 #6 Child image: 123 1 2 -
Javascript • Да, всему этому есть логическое объяснение • Но
я не хочу это знать! > [1, 2, 3] == [1, 2, 3] false > [1, 2, 3] === [1, 2, 3] false > JSON.stringify([1, 2, 3]) == JSON.stringify([1, 2, 3]) true > [-5, -2, 2, 1].sort() [-2, -5, 1, 2] > ('b' + 'a' + + 'a' + 'a') .toLowerCase() 'banana' -
Javascript • Да, всему этому есть логическое объяснение • Но
я не хочу это знать! > [1, 2, 3] == [1, 2, 3] false > [1, 2, 3] === [1, 2, 3] false > JSON.stringify([1, 2, 3]) == JSON.stringify([1, 2, 3]) true > [-5, -2, 2, 1].sort() [-2, -5, 1, 2] > ('b' + 'a' + + 'a' + 'a') .toLowerCase() 'banana' -
Javascript • Да, всему этому есть логическое объяснение • Но
я не хочу это знать! > [1, 2, 3] == [1, 2, 3] false > [1, 2, 3] === [1, 2, 3] false > JSON.stringify([1, 2, 3]) == JSON.stringify([1, 2, 3]) true > [-5, -2, 2, 1].sort() [-2, -5, 1, 2] > ('b' + 'a' + + 'a' + 'a') .toLowerCase() 'banana' -
Javascript • Да, всему этому есть логическое объяснение • Но
я не хочу это знать! > [1, 2, 3] == [1, 2, 3] false > [1, 2, 3] === [1, 2, 3] false > JSON.stringify([1, 2, 3]) == JSON.stringify([1, 2, 3]) true > [-5, -2, 2, 1].sort() [-2, -5, 1, 2] > ('b' + 'a' + + 'a' + 'a') .toLowerCase() 'banana' -
Javascript • Да, всему этому есть логическое объяснение • Но
я не хочу это знать! > [1, 2, 3] == [1, 2, 3] false > [1, 2, 3] === [1, 2, 3] false > JSON.stringify([1, 2, 3]) == JSON.stringify([1, 2, 3]) true > [-5, -2, 2, 1].sort() [-2, -5, 1, 2] > ('b' + 'a' + + 'a' + 'a') .toLowerCase() 'banana' -
Javascript • Да, всему этому есть логическое объяснение • Но
я не хочу это знать! > [1, 2, 3] == [1, 2, 3] false > [1, 2, 3] === [1, 2, 3] false > JSON.stringify([1, 2, 3]) == JSON.stringify([1, 2, 3]) true > [-5, -2, 2, 1].sort() [-2, -5, 1, 2] > ('b' + 'a' + + 'a' + 'a') .toLowerCase() 'banana' -
Javascript • Да, всему этому есть логическое объяснение • Но
я не хочу это знать! > [1, 2, 3] == [1, 2, 3] false > [1, 2, 3] === [1, 2, 3] false > JSON.stringify([1, 2, 3]) == JSON.stringify([1, 2, 3]) true > [-5, -2, 2, 1].sort() [-2, -5, 1, 2] > ('b' + 'a' + + 'a' + 'a') .toLowerCase() 'banana' -
Javascript • Да, всему этому есть логическое объяснение • Но
я не хочу это знать! > [1, 2, 3] == [1, 2, 3] false > [1, 2, 3] === [1, 2, 3] false > JSON.stringify([1, 2, 3]) == JSON.stringify([1, 2, 3]) true > [-5, -2, 2, 1].sort() [-2, -5, 1, 2] > ('b' + 'a' + + 'a' + 'a') .toLowerCase() 'banana' -
Javascript • Да, всему этому есть логическое объяснение • Но
я не хочу это знать! > [1, 2, 3] == [1, 2, 3] false > [1, 2, 3] === [1, 2, 3] false > JSON.stringify([1, 2, 3]) == JSON.stringify([1, 2, 3]) true > [-5, -2, 2, 1].sort() [-2, -5, 1, 2] > ('b' + 'a' + + 'a' + 'a') .toLowerCase() 'banana' -
Javascript • Да, всему этому есть логическое объяснение • Но
я не хочу это знать! > [1, 2, 3] == [1, 2, 3] false > [1, 2, 3] === [1, 2, 3] false > JSON.stringify([1, 2, 3]) == JSON.stringify([1, 2, 3]) true > [-5, -2, 2, 1].sort() [-2, -5, 1, 2] > ('b' + 'a' + + 'a' + 'a') .toLowerCase() 'banana' -
Javascript • Да, всему этому есть логическое объяснение • Но
я не хочу это знать! > [1, 2, 3] == [1, 2, 3] false > [1, 2, 3] === [1, 2, 3] false > JSON.stringify([1, 2, 3]) == JSON.stringify([1, 2, 3]) true > [-5, -2, 2, 1].sort() [-2, -5, 1, 2] > ('b' + 'a' + + 'a' + 'a') .toLowerCase() 'banana' -
Javascript • Да, всему этому есть логическое объяснение • Но
я не хочу это знать! > new Date(0) Thu Jan 01 1970 03:00:00 GMT+0300 (Moscow Standard Time) new Date('0') Sat Jan 01 2000 00:00:00 GMT+0300 (Moscow Standard Time) > new Date('2024-01-01') Mon Jan 01 2024 03:00:00 GMT+0300 (Moscow Standard Time) > new Date('2024/01/01') Mon Jan 01 2024 00:00:00 GMT+0300 (Moscow Standard Time) -
Javascript • Да, всему этому есть логическое объяснение • Но
я не хочу это знать! > new Date(0) Thu Jan 01 1970 03:00:00 GMT+0300 (Moscow Standard Time) new Date('0') Sat Jan 01 2000 00:00:00 GMT+0300 (Moscow Standard Time) > new Date('2024-01-01') Mon Jan 01 2024 03:00:00 GMT+0300 (Moscow Standard Time) > new Date('2024/01/01') Mon Jan 01 2024 00:00:00 GMT+0300 (Moscow Standard Time) -
Javascript • Да, всему этому есть логическое объяснение • Но
я не хочу это знать! > new Date(0) Thu Jan 01 1970 03:00:00 GMT+0300 (Moscow Standard Time) new Date('0') Sat Jan 01 2000 00:00:00 GMT+0300 (Moscow Standard Time) > new Date('2024-01-01') Mon Jan 01 2024 03:00:00 GMT+0300 (Moscow Standard Time) > new Date('2024/01/01') Mon Jan 01 2024 00:00:00 GMT+0300 (Moscow Standard Time) -
Javascript • Да, всему этому есть логическое объяснение • Но
я не хочу это знать! > new Date(0) Thu Jan 01 1970 03:00:00 GMT+0300 (Moscow Standard Time) new Date('0') Sat Jan 01 2000 00:00:00 GMT+0300 (Moscow Standard Time) > new Date('2024-01-01') Mon Jan 01 2024 03:00:00 GMT+0300 (Moscow Standard Time) > new Date('2024/01/01') Mon Jan 01 2024 00:00:00 GMT+0300 (Moscow Standard Time) -
Javascript • Да, всему этому есть логическое объяснение • Но
я не хочу это знать! > new Date(0) Thu Jan 01 1970 03:00:00 GMT+0300 (Moscow Standard Time) new Date('0') Sat Jan 01 2000 00:00:00 GMT+0300 (Moscow Standard Time) > new Date('2024-01-01') Mon Jan 01 2024 03:00:00 GMT+0300 (Moscow Standard Time) > new Date('2024/01/01') Mon Jan 01 2024 00:00:00 GMT+0300 (Moscow Standard Time) -
Javascript • Да, всему этому есть логическое объяснение • Но
я не хочу это знать! > new Date(0) Thu Jan 01 1970 03:00:00 GMT+0300 (Moscow Standard Time) new Date('0') Sat Jan 01 2000 00:00:00 GMT+0300 (Moscow Standard Time) > new Date('2024-01-01') Mon Jan 01 2024 03:00:00 GMT+0300 (Moscow Standard Time) > new Date('2024/01/01') Mon Jan 01 2024 00:00:00 GMT+0300 (Moscow Standard Time) -
Javascript • Да, всему этому есть логическое объяснение • Но
я не хочу это знать! > new Date(0) Thu Jan 01 1970 03:00:00 GMT+0300 (Moscow Standard Time) new Date('0') Sat Jan 01 2000 00:00:00 GMT+0300 (Moscow Standard Time) > new Date('2024-01-01') Mon Jan 01 2024 03:00:00 GMT+0300 (Moscow Standard Time) > new Date('2024/01/01') Mon Jan 01 2024 00:00:00 GMT+0300 (Moscow Standard Time) -
Javascript • Да, всему этому есть логическое объяснение • Но
я не хочу это знать! > new Date(0) Thu Jan 01 1970 03:00:00 GMT+0300 (Moscow Standard Time) new Date('0') Sat Jan 01 2000 00:00:00 GMT+0300 (Moscow Standard Time) > new Date('2024-01-01') Mon Jan 01 2024 03:00:00 GMT+0300 (Moscow Standard Time) > new Date('2024/01/01') Mon Jan 01 2024 00:00:00 GMT+0300 (Moscow Standard Time) -
Javascript • Да, всему этому есть логическое объяснение • Но
я не хочу это знать! > new Date(0) Thu Jan 01 1970 03:00:00 GMT+0300 (Moscow Standard Time) new Date('0') Sat Jan 01 2000 00:00:00 GMT+0300 (Moscow Standard Time) > new Date('2024-01-01') Mon Jan 01 2024 03:00:00 GMT+0300 (Moscow Standard Time) > new Date('2024/01/01') Mon Jan 01 2024 00:00:00 GMT+0300 (Moscow Standard Time) -
Python: скобки • Ну да, ну да, вот наш питон-то
простой и логичный! {'a': 1} # это словарь dict(a=1) # это то же самое {'a'} # это множество (set) {} # это не пустое множество, это пустой словарь set() # а вот это пустое множество -
Python: скобки • Ну да, ну да, вот наш питон-то
простой и логичный! {'a': 1} # это словарь dict(a=1) # это то же самое {'a'} # это множество (set) {} # это не пустое множество, это пустой словарь set() # а вот это пустое множество -
Python: скобки • Ну да, ну да, вот наш питон-то
простой и логичный! {'a': 1} # это словарь dict(a=1) # это то же самое {'a'} # это множество (set) {} # это не пустое множество, это пустой словарь set() # а вот это пустое множество -
Python: скобки • Ну да, ну да, вот наш питон-то
простой и логичный! {'a': 1} # это словарь dict(a=1) # это то же самое {'a'} # это множество (set) {} # это не пустое множество, это пустой словарь set() # а вот это пустое множество -
Python: скобки • Ну да, ну да, вот наш питон-то
простой и логичный! {'a': 1} # это словарь dict(a=1) # это то же самое {'a'} # это множество (set) {} # это не пустое множество, это пустой словарь set() # а вот это пустое множество -
Python: скобки • Ну да, ну да, вот наш питон-то
простой и логичный! {'a': 1} # это словарь dict(a=1) # это то же самое {'a'} # это множество (set) {} # это не пустое множество, это пустой словарь set() # а вот это пустое множество -
Python: скобки • Ну да, ну да, вот наш питон-то
простой и логичный! {'a': 1} # это словарь dict(a=1) # это то же самое {'a'} # это множество (set) {} # это не пустое множество, это пустой словарь set() # а вот это пустое множество -
Python: скобки • Ну да, ну да, вот наш питон-то
простой и логичный! {'a': 1} # это словарь dict(a=1) # это то же самое {'a'} # это множество (set) {} # это не пустое множество, это пустой словарь set() # а вот это пустое множество -
Python: скобки • Ну да, ну да, вот наш питон-то
простой и логичный! {'a': 1} # это словарь dict(a=1) # это то же самое {'a'} # это множество (set) {} # это не пустое множество, это пустой словарь set() # а вот это пустое множество -
Python: скобки • Ну да, ну да, вот наш питон-то
простой и логичный! 1 # это просто число (int) (1+2) # это число (1, 2) # это кортеж (tuple) (1) # это тоже просто число 1, # это тоже кортеж () # это пустой кортеж (,) # SyntaxError -
Python: скобки • Ну да, ну да, вот наш питон-то
простой и логичный! 1 # это просто число (int) (1+2) # это число (1, 2) # это кортеж (tuple) (1) # это тоже просто число 1, # это тоже кортеж () # это пустой кортеж (,) # SyntaxError -
Python: скобки • Ну да, ну да, вот наш питон-то
простой и логичный! 1 # это просто число (int) (1+2) # это число (1, 2) # это кортеж (tuple) (1) # это тоже просто число 1, # это тоже кортеж () # это пустой кортеж (,) # SyntaxError -
Python: скобки • Ну да, ну да, вот наш питон-то
простой и логичный! 1 # это просто число (int) (1+2) # это число (1, 2) # это кортеж (tuple) (1) # это тоже просто число 1, # это тоже кортеж () # это пустой кортеж (,) # SyntaxError -
Python: скобки • Ну да, ну да, вот наш питон-то
простой и логичный! 1 # это просто число (int) (1+2) # это число (1, 2) # это кортеж (tuple) (1) # это тоже просто число 1, # это тоже кортеж () # это пустой кортеж (,) # SyntaxError -
Python: скобки • Ну да, ну да, вот наш питон-то
простой и логичный! 1 # это просто число (int) (1+2) # это число (1, 2) # это кортеж (tuple) (1) # это тоже просто число 1, # это тоже кортеж () # это пустой кортеж (,) # SyntaxError -
Python: скобки • Ну да, ну да, вот наш питон-то
простой и логичный! 1 # это просто число (int) (1+2) # это число (1, 2) # это кортеж (tuple) (1) # это тоже просто число 1, # это тоже кортеж () # это пустой кортеж (,) # SyntaxError -
Python: скобки • Ну да, ну да, вот наш питон-то
простой и логичный! 1 # это просто число (int) (1+2) # это число (1, 2) # это кортеж (tuple) (1) # это тоже просто число 1, # это тоже кортеж () # это пустой кортеж (,) # SyntaxError -
Python: скобки • Ну да, ну да, вот наш питон-то
простой и логичный! 1 # это просто число (int) (1+2) # это число (1, 2) # это кортеж (tuple) (1) # это тоже просто число 1, # это тоже кортеж () # это пустой кортеж (,) # SyntaxError -
Python: скобки • Ну да, ну да, вот наш питон-то
простой и логичный! 1 # это просто число (int) (1+2) # это число (1, 2) # это кортеж (tuple) (1) # это тоже просто число 1, # это тоже кортеж () # это пустой кортеж (,) # SyntaxError -
Python: скобки • Ну да, ну да, вот наш питон-то
простой и логичный! 1 # это просто число (int) (1+2) # это число (1, 2) # это кортеж (tuple) (1) # это тоже просто число 1, # это тоже кортеж () # это пустой кортеж (,) # SyntaxError -
Python: скобки • Ну да, ну да, вот наш питон-то
простой и логичный! 1 # это просто число (int) (1+2) # это число (1, 2) # это кортеж (tuple) (1) # это тоже просто число 1, # это тоже кортеж () # это пустой кортеж (,) # SyntaxError -
Python: скобки • Ну да, ну да, вот наш питон-то
простой и логичный! 1 # это просто число (int) (1+2) # это число (1, 2) # это кортеж (tuple) (1) # это тоже просто число 1, # это тоже кортеж () # это пустой кортеж (,) # SyntaxError -
Python: скобки • Ну да, ну да, вот наш питон-то
простой и логичный! 1 # это просто число (int) (1+2) # это число (1, 2) # это кортеж (tuple) (1) # это тоже просто число 1, # это тоже кортеж () # это пустой кортеж (,) # SyntaxError -
Python: скобки • Ну да, ну да, вот наш питон-то
простой и логичный! [] # это пустой список [1] # это список с одним элементом [1, 2, 3] # это список с 3 элементами [i for i in range(3)] # это тоже список с 3 элементами () # это пустой кортеж (1) # это просто число (1, 2, 3) # это (ха-ха) кортеж (i for i in range(3)) # это не кортеж, это генератор :D -
Python: скобки • Ну да, ну да, вот наш питон-то
простой и логичный! [] # это пустой список [1] # это список с одним элементом [1, 2, 3] # это список с 3 элементами [i for i in range(3)] # это тоже список с 3 элементами () # это пустой кортеж (1) # это просто число (1, 2, 3) # это (ха-ха) кортеж (i for i in range(3)) # это не кортеж, это генератор :D -
Python: скобки • Ну да, ну да, вот наш питон-то
простой и логичный! [] # это пустой список [1] # это список с одним элементом [1, 2, 3] # это список с 3 элементами [i for i in range(3)] # это тоже список с 3 элементами () # это пустой кортеж (1) # это просто число (1, 2, 3) # это (ха-ха) кортеж (i for i in range(3)) # это не кортеж, это генератор :D -
Python: скобки • Ну да, ну да, вот наш питон-то
простой и логичный! [] # это пустой список [1] # это список с одним элементом [1, 2, 3] # это список с 3 элементами [i for i in range(3)] # это тоже список с 3 элементами () # это пустой кортеж (1) # это просто число (1, 2, 3) # это (ха-ха) кортеж (i for i in range(3)) # это не кортеж, это генератор :D -
Python: скобки • Ну да, ну да, вот наш питон-то
простой и логичный! [] # это пустой список [1] # это список с одним элементом [1, 2, 3] # это список с 3 элементами [i for i in range(3)] # это тоже список с 3 элементами () # это пустой кортеж (1) # это просто число (1, 2, 3) # это (ха-ха) кортеж (i for i in range(3)) # это не кортеж, это генератор :D -
Python: скобки • Ну да, ну да, вот наш питон-то
простой и логичный! [] # это пустой список [1] # это список с одним элементом [1, 2, 3] # это список с 3 элементами [i for i in range(3)] # это тоже список с 3 элементами () # это пустой кортеж (1) # это просто число (1, 2, 3) # это (ха-ха) кортеж (i for i in range(3)) # это не кортеж, это генератор :D -
Python: скобки • Ну да, ну да, вот наш питон-то
простой и логичный! [] # это пустой список [1] # это список с одним элементом [1, 2, 3] # это список с 3 элементами [i for i in range(3)] # это тоже список с 3 элементами () # это пустой кортеж (1) # это просто число (1, 2, 3) # это (ха-ха) кортеж (i for i in range(3)) # это не кортеж, это генератор :D -
Python: скобки • Ну да, ну да, вот наш питон-то
простой и логичный! [] # это пустой список [1] # это список с одним элементом [1, 2, 3] # это список с 3 элементами [i for i in range(3)] # это тоже список с 3 элементами () # это пустой кортеж (1) # это просто число (1, 2, 3) # это (ха-ха) кортеж (i for i in range(3)) # это не кортеж, это генератор :D -
Python: скобки • Ну да, ну да, вот наш питон-то
простой и логичный! [] # это пустой список [1] # это список с одним элементом [1, 2, 3] # это список с 3 элементами [i for i in range(3)] # это тоже список с 3 элементами () # это пустой кортеж (1) # это просто число (1, 2, 3) # это (ха-ха) кортеж (i for i in range(3)) # это не кортеж, это генератор :D -
Python: скобки • Ну да, ну да, вот наш питон-то
простой и логичный! [] # это пустой список [1] # это список с одним элементом [1, 2, 3] # это список с 3 элементами [i for i in range(3)] # это тоже список с 3 элементами () # это пустой кортеж (1) # это просто число (1, 2, 3) # это (ха-ха) кортеж (i for i in range(3)) # это не кортеж, это генератор :D -
Python: скобки • Ну да, ну да, вот наш питон-то
простой и логичный! [] # это пустой список [1] # это список с одним элементом [1, 2, 3] # это список с 3 элементами [i for i in range(3)] # это тоже список с 3 элементами () # это пустой кортеж (1) # это просто число (1, 2, 3) # это кортеж (i for i in range(3)) # это не кортеж, это генератор :D -
Python: скобки • Ну да, ну да, вот наш питон-то
простой и логичный! [] # это пустой список [1] # это список с одним элементом [1, 2, 3] # это список с 3 элементами [i for i in range(3)] # это тоже список с 3 элементами () # это пустой кортеж (1) # это просто число (1, 2, 3) # это кортеж (i for i in range(3)) # это не кортеж, это генератор -
Python: скобки • Ну да, ну да, вот наш питон-то
простой и логичный! [] # это пустой список [1] # это список с одним элементом [1, 2, 3] # это список с 3 элементами [i for i in range(3)] # это тоже список с 3 элементами () # это пустой кортеж (1) # это просто число (1, 2, 3) # это кортеж (i for i in range(3)) # это не кортеж, это генератор -
Python: не даст отстрелить ногу • Удобно, что питон отслеживает
потенциально опасные места и не даёт нам делать плохие вещи data = {1: 2} for key, value in data.items(): data[key+1] = value+1 RuntimeError: dictionary changed size during iteration data = [1, 2] for value in data: data.append(value+1) Всё ок! Прощай, RAM :) -
Python: не даст отстрелить ногу • Удобно, что питон отслеживает
потенциально опасные места и не даёт нам делать плохие вещи data = {1: 2} for key, value in data.items(): data[key+1] = value+1 RuntimeError: dictionary changed size during iteration data = [1, 2] for value in data: data.append(value+1) Всё ок! Прощай, RAM :) -
Python: не даст отстрелить ногу • Удобно, что питон отслеживает
потенциально опасные места и не даёт нам делать плохие вещи data = {1: 2} for key, value in data.items(): data[key+1] = value+1 RuntimeError: dictionary changed size during iteration data = [1, 2] for value in data: data.append(value+1) Всё ок! Прощай, RAM :) -
Python: не даст отстрелить ногу • Удобно, что питон отслеживает
потенциально опасные места и не даёт нам делать плохие вещи data = {1: 2} for key, value in data.items(): data[key+1] = value+1 RuntimeError: dictionary changed size during iteration data = [1, 2] for value in data: data.append(value+1) Всё ок! Прощай, RAM :) -
Pytest > ls bot.py config.py history.py knowledge.py logs.py __main__.py models.py
__pycache__/ shell.py tests/ tools.py utils.py -
Pytest > ls bot.py config.py history.py knowledge.py logs.py __main__.py models.py
__pycache__/ shell.py tests/ tools.py utils.py > pdm run pytest . ERROR collecting src/tests/test_bot.py ImportError while importing test module '/home/user/workspace/project/src/tests/test_bot.py'. Hint: make sure your test modules/packages have valid Python names. Traceback: .pyenv/versions/3.11.4/lib/python3.11/importlib/__init__.py:126: in import_module return _bootstrap._gcd_import(name[level:], package, level) tests/test_bot.py:3: in <module> from ..bot import message_handler E ImportError: attempted relative import beyond top-level package -
Dataclass @dataclass class Base: a: str class Child(Base): b: str
> Base() TypeError: Base.__init__() missing 1 required positional argument: 'a' > Base(a=’test’) Base(a='test') > Child(a=’test’) Child(a='test') > Child(a=’test’, b=’test’) TypeError: Base.__init__() got an unexpected keyword argument 'b' -
Dataclass @dataclass class Base: a: str class Child(Base): b: str
> Base() TypeError: Base.__init__() missing 1 required positional argument: 'a' > Base(a=’test’) Base(a='test') > Child(a=’test’) Child(a='test') > Child(a=’test’, b=’test’) TypeError: Base.__init__() got an unexpected keyword argument 'b' -
Dataclass @dataclass class Base: a: str class Child(Base): b: str
> Base() TypeError: Base.__init__() missing 1 required positional argument: 'a' > Base(a=’test’) Base(a='test') > Child(a=’test’) Child(a='test') > Child(a=’test’, b=’test’) TypeError: Base.__init__() got an unexpected keyword argument 'b' -
Dataclass @dataclass class Base: a: str class Child(Base): b: str
> Base() TypeError: Base.__init__() missing 1 required positional argument: 'a' > Base(a=’test’) Base(a='test') > Child(a=’test’) Child(a='test') > Child(a=’test’, b=’test’) TypeError: Base.__init__() got an unexpected keyword argument 'b' -
Dataclass @dataclass class Base: a: str class Child(Base): b: str
> Base() TypeError: Base.__init__() missing 1 required positional argument: 'a' > Base(a=’test’) Base(a='test') > Child(a=’test’) Child(a='test') > Child(a=’test’, b=’test’) TypeError: Base.__init__() got an unexpected keyword argument 'b' -
Dataclass @dataclass class Base: a: str @dataclass class Child(Base): b:
str > Base() TypeError: Base.__init__() missing 1 required positional argument: 'a' > Base(a=’test’) Base(a='test') > Child(a=’test’) TypeError: Child.__init__() missing 1 required positional argument: 'b' > Child(a=’test’, b=’test’) Child(a='test', b='test2') -
Pull request • Создаю как обычно PR в master •
Ловлю конфликт с файлом, которого у меня нет • Но который есть в master master -
Pull request • Создаю как обычно PR в master •
Ловлю конфликт с файлом, которого у меня нет • Но который есть в master master -
Pull request # ci.yml test: steps: - uses: actions/checkout@v3 with:
fetch-depth: 0 master -
PgBouncer • Приложения можно подключать к базе напрямую • Но
если их много, то слишком много соединений с БД App Postgres App App App App App -
PgBouncer • Приложения можно подключать к базе напрямую • Но
если их много, то слишком много соединений с БД • Решение - PgBouncer, который управляет пулом соединений App Postgres App App App App App PgBouncer -
PgBouncer • Делаем бэкап: pg_dump postgres > dump.sql -- dump.sql
SET statement_timeout = 0; SET lock_timeout = 0; SET idle_in_transaction_session_timeout = 0; SET client_encoding = 'UTF8'; SET standard_conforming_strings = on; SELECT pg_catalog.set_config( 'search_path', '', false); SET check_function_bodies = false; SET xmloption = content; SET client_min_messages = warning; SET row_security = off; ... -
PgBouncer • Делаем бэкап: pg_dump postgres > dump.sql • Восстанавливаемся
из бэкапа: psql postgres < dump.sql -- dump.sql SET statement_timeout = 0; SET lock_timeout = 0; SET idle_in_transaction_session_timeout = 0; SET client_encoding = 'UTF8'; SET standard_conforming_strings = on; SELECT pg_catalog.set_config( 'search_path', '', false); SET check_function_bodies = false; SET xmloption = content; SET client_min_messages = warning; SET row_security = off; ... -
PgBouncer • SELECT pg_catalog.set_config( 'search_path', '', false); • “Забудь всё,
что ты знал до этого” App Postgres App App psql App PgBouncer -
PgBouncer • SELECT pg_catalog.set_config( 'search_path', '', false); • “Забудь всё,
что ты знал до этого” App Postgres App App App PgBouncer -
PgBouncer • SELECT pg_catalog.set_config( 'search_path', '', false); • “Забудь всё,
что ты знал до этого” App Postgres App App psql App PgBouncer -
PDM > pdm add django-attachments~=1.5 django-bleach~=0.6.1 django-bootstrap3~=12.1.0 django-cacheops~=7.0.2 django-ckeditor~=5.9.0 django-contrib-comments~=1.9.2
django-cors-headers~=3.7.0 django-debug-toolbar~=3.5.0 django-elasticsearch-dsl~=7.1.1 django-filter~=2.3.0 Adding packages to default dependencies: django-attachments~=1.5, django-bleach~=0.6.1, django-bootstrap3~=12.1.0, django-cacheops~=7.0.2, django-ckeditor~=5.9.0, django-contrib-comments~=1.9.2, django-cors-headers~=3.7.0, django-debug-toolbar~=3.5.0, django-elasticsearch-dsl~=7.1.1, django-filter~=2.3.0 -
PDM > pdm add django-attachments~=1.5 django-bleach~=0.6.1 django-bootstrap3~=12.1.0 django-cacheops~=7.0.2 django-ckeditor~=5.9.0 django-contrib-comments~=1.9.2
django-cors-headers~=3.7.0 django-debug-toolbar~=3.5.0 django-elasticsearch-dsl~=7.1.1 django-filter~=2.3.0 Adding packages to default dependencies: django-attachments~=1.5, django-bleach~=0.6.1, django-bootstrap3~=12.1.0, django-cacheops~=7.0.2, django-ckeditor~=5.9.0, django-contrib-comments~=1.9.2, django-cors-headers~=3.7.0, django-debug-toolbar~=3.5.0, django-elasticsearch-dsl~=7.1.1, django-filter~=2.3.0 0:00:09 🔒 Lock failed. ERROR: -
PDM > pdm add django-attachments~=1.5 django-bleach~=0.6.1 django-bootstrap3~=12.1.0 django-cacheops~=7.0.2 django-ckeditor~=5.9.0 django-contrib-comments~=1.9.2
django-cors-headers~=3.7.0 django-debug-toolbar~=3.5.0 django-elasticsearch-dsl~=7.1.1 django-filter~=2.3.0 Adding packages to default dependencies: django-attachments~=1.5, django-bleach~=0.6.1, django-bootstrap3~=12.1.0, django-cacheops~=7.0.2, django-ckeditor~=5.9.0, django-contrib-comments~=1.9.2, django-cors-headers~=3.7.0, django-debug-toolbar~=3.5.0, django-elasticsearch-dsl~=7.1.1, django-filter~=2.3.0 0:00:09 🔒 Lock failed. ERROR: 0:00:09 🔒 Lock failed. -
PDM > pdm add django-attachments~=1.5 django-bleach~=0.6.1 django-bootstrap3~=12.1.0 django-cacheops~=7.0.2 django-ckeditor~=5.9.0 django-contrib-comments~=1.9.2
django-cors-headers~=3.7.0 django-debug-toolbar~=3.5.0 django-elasticsearch-dsl~=7.1.1 django-filter~=2.3.0 Adding packages to default dependencies: django-attachments~=1.5, django-bleach~=0.6.1, django-bootstrap3~=12.1.0, django-cacheops~=7.0.2, django-ckeditor~=5.9.0, django-contrib-comments~=1.9.2, django-cors-headers~=3.7.0, django-debug-toolbar~=3.5.0, django-elasticsearch-dsl~=7.1.1, django-filter~=2.3.0 0:00:09 🔒 Lock failed. ERROR: 0:00:09 🔒 Lock failed. See /home/user/.local/state/pdm/log/pdm-lock-4aauctl8.log for detailed debug log. [ResolutionImpossible]: Unable to find a resolution WARNING: Add '-v' to see the detailed traceback -
Мой любимый def parse_json_markdown(json_string: str, *, parser: Callable[[str], Any] =
parse_partial_json) -> dict: """ Parse a JSON string from a Markdown string. Args: json_string: The Markdown string. Returns: The parsed JSON object as a Python dictionary. """ -
Celery flower, что ты умеешь? > celery flower --help Usage:
celery flower [OPTIONS] [TORNADO_ARGV]... Web based tool for monitoring and administrating Celery clusters. Options: --help Show this message and exit. -
ChatGPT jobs: linter: steps: - uses: actions/checkout@v3 - name: Set
up Python ${{ env.PYTHON_DEFAULT_VERSION }} uses: actions/setup-python@v4 - name: Install dependencies run: python -m pip install --upgrade nox 'pdm>=2.12,<3' - name: Run linters run: nox -vs lint -
Ruff last_weights = Weights.objects.order_by('-created_at').first() if ( last_weights and last_weights.revealed_at is
None and last_weights.block <= current_block_number - (reveal_weights_interval - reveal_in_advance) ): -
Ruff last_weights = Weights.objects.order_by('-created_at').first() if ( last_weights and last_weights.revealed_at is
None and last_weights.block <= current_block_number - (reveal_weights_interval - reveal_in_advance) ): -
Pytest: рецепт успеха > pytest -W ignore::DeprecationWarning -s -x -vv
tests -k test_set_scores == test session starts == platform linux -- Python 3.11.4, pytest-8.2.2, pluggy-1.5.0 rootdir: /home/user/workspace/ configfile: pytest.ini plugins: xdist-3.6.1, anyio-4.4.0, django-constance-3.1.0, asyncio-0.23.7 asyncio: mode=Mode.STRICT collected 1 item / 1 deselected / 0 selected == 1 deselected in 0.21s == -
React • В документации вот такой код const [squares, setSquares]
= useState(Array(9).fill(null)); function handleClick() { const nextSquares = squares.slice(); nextSquares[0] = "X"; setSquares(nextSquares); } X -
React • В документации вот такой код • Минут пять
убиваю, чтобы понять, зачем делать слайс и менять в нём только первый элемент • Так нихрена и не понял • Ладно, читаю дальше const [squares, setSquares] = useState(Array(9).fill(null)); function handleClick() { const nextSquares = squares.slice(); nextSquares[0] = "X"; setSquares(nextSquares); } X -
React “Now you can add X’s to the board… but
only to the upper left square. Your `handleClick` function is hardcoded to update the index for the upper left square (`0`). Let’s update `handleClick` to be able to update any square.” const [squares, setSquares] = useState(Array(9).fill(null)); function handleClick() { const nextSquares = squares.slice(); nextSquares[0] = "X"; setSquares(nextSquares); } X -
Github Кто-то нас форкнул 10 лет назад Случайно коммитим ключ
В ужасе удаляем свой репо -
Beer Meetup • Прихожу в бар • Сижу полчаса наедине
с выпивкой • Никого нет -
Beer Meetup • Прихожу в бар • Сижу полчаса наедине
с выпивкой • Никого нет • Приходят какие-то девушки -
Beer Meetup • Прихожу в бар • Сижу полчаса наедине
с выпивкой • Никого нет • Приходят какие-то девушки • Я им затираю про питон, они ничего не понимают -
Beer Meetup • Прихожу в бар • Сижу полчаса наедине
с выпивкой • Никого нет • Приходят какие-то девушки • Я им затираю про питон, они ничего не понимают • Проверяю календарь -
Beer Meetup • Прихожу в бар • Сижу полчаса наедине
с выпивкой • Никого нет • Приходят какие-то девушки • Я им затираю про питон, они ничего не понимают • Проверяю календарь • Я перепутал даты и пришёл ровно на неделю раньше