Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Moscow Python Meetup №94. Александр Гончаров (...

Moscow Python Meetup №94. Александр Гончаров (SlashHash LLC). Это вообще не просто!

Давайте уже расскажем всем правду: программирование — это хаос, абсурд и нелогичность. Доклад о наболевшем.

Видео: https://moscowpython.ru/meetup/94/its-not-easy/

Moscow Python: http://moscowpython.ru
Курсы Learn Python: http://learn.python.ru
Moscow Python Podcast: http://podcast.python.ru
Заявки на доклады: https://bit.ly/mp-speaker

Avatar for Moscow Python Meetup

Moscow Python Meetup

September 20, 2024
Tweet

More Decks by Moscow Python Meetup

Other Decks in Programming

Transcript

  1. 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'
  2. 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'
  3. 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'
  4. 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'
  5. 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'
  6. 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'
  7. 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'
  8. 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'
  9. 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'
  10. 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'
  11. 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'
  12. 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'
  13. 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'
  14. 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'
  15. 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
  16. 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
  17. 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
  18. Django • Всё покрыто тестами # settings.py SUBSCRIPTION = {

    ‘duration’: timedelta(days=30), ‘price’: Decimal(100), } # service.py subscriptions = getattr( settings, ‘SUBSCRIPTIONS’, DEFAULT_SETTINGS )
  19. Django • Всё покрыто тестами • Выкатываю в прод -

    работает не так, как ожидал # settings.py SUBSCRIPTION = { ‘duration’: timedelta(days=30), ‘price’: Decimal(100), } # service.py subscriptions = getattr( settings, ‘SUBSCRIPTIONS’, DEFAULT_SETTINGS )
  20. Django • Всё покрыто тестами • Выкатываю в прод -

    работает не так, как ожидал • Никаких ошибок нет # settings.py SUBSCRIPTION = { ‘duration’: timedelta(days=30), ‘price’: Decimal(100), } # service.py subscriptions = getattr( settings, ‘SUBSCRIPTIONS’, DEFAULT_SETTINGS )
  21. Django • Всё покрыто тестами • Выкатываю в прод -

    работает не так, как ожидал • Никаких ошибок нет • В чём ошибка? # settings.py SUBSCRIPTION = { ‘duration’: timedelta(days=30), ‘price’: Decimal(100), } # service.py subscriptions = getattr( settings, ‘SUBSCRIPTIONS’, DEFAULT_SETTINGS )
  22. Django • Всё покрыто тестами • Выкатываю в прод -

    работает не так, как ожидал • Никаких ошибок нет • В чём ошибка? • Проверяю - забыл одну букву # settings.py SUBSCRIPTIONS = { ‘duration’: timedelta(days=30), ‘price’: Decimal(100), } # service.py subscriptions = getattr( settings, ‘SUBSCRIPTIONS’, DEFAULT_SETTINGS )
  23. 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'}]
  24. 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'}]
  25. 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'}]
  26. Sqlalchemy • Пытаюсь записать несколько строк в БД • Получаю

    ошибку, что такая строка уже существует • А строки разные! • Смотрю, что уже есть в таблице - а там ничего!
  27. Sqlalchemy class Tag(BigIntBase): name: Mapped[str] __table_args__ = ( Index( "ix_tag_name",

    func.lower('name'), unique=True), ) • Пытаюсь записать несколько строк в БД • Получаю ошибку, что такая строка уже существует • А строки разные! • Смотрю, что уже есть в таблице - а там ничего! • А потому что “name” - это не название колонки, а строка!
  28. Лучшее - враг хорошего • Однажды я решил, что использовать

    tuple[int, int] для интервалов - это не по- сеньорски epoch = (100, 200) jobs = Jobs.objects.filter( block__gte=epoch[0], block__lt=epoch[1], ) .order_by("block")
  29. Лучшее - враг хорошего • Однажды я решил, что использовать

    tuple[int, int] для интервалов - это не по- сеньорски • Есть же специальный тип: range epoch = (100, 200) jobs = Jobs.objects.filter( block__gte=epoch[0], block__lt=epoch[1], ) .order_by("block")
  30. Лучшее - враг хорошего • Однажды я решил, что использовать

    tuple[int, int] для интервалов - это не по- сеньорски • Есть же специальный тип: range • Время рефакторинга! epoch = (100, 200) jobs = Jobs.objects.filter( block__gte=epoch[0], block__lt=epoch[1], ) .order_by("block")
  31. Лучшее - враг хорошего • Однажды я решил, что использовать

    tuple[int, int] для интервалов - это не по- сеньорски • Есть же специальный тип: range • Время рефакторинга! • Всё сломалось epoch = range(100, 201) jobs = Jobs.objects.filter( block__gte=epoch[0], block__lt=epoch[1], ) .order_by("block")
  32. Лучшее - враг хорошего • Однажды я решил, что использовать

    tuple[int, int] для интервалов - это не по- сеньорски • Есть же специальный тип: range • Время рефакторинга! • Всё сломалось • А потому что [1] теперь не то, чем было! epoch = range(100, 201) jobs = Jobs.objects.filter( block__gte=epoch[0], block__lt=epoch[1], ) .order_by("block")
  33. Лучшее - враг хорошего • Однажды я решил, что использовать

    tuple[int, int] для интервалов - это не по- сеньорски • Есть же специальный тип: range • Время рефакторинга! • Всё сломалось • А потому что [1] теперь не то, чем было! epoch = range(100, 201) jobs = Jobs.objects.filter( block__gte=epoch.start, block__lt=epoch.stop, ) .order_by("block")
  34. #!/bin/bash • Почему нельзя ставить флаги после “#!” ? #!/bin/bash

    -e false echo "Shouldn’t execute" > ./script.sh + false > bash script.sh Shouldn't execute
  35. #!/bin/bash • Почему нельзя ставить флаги после “#!” ? #!/bin/bash

    -e false echo "Shouldn’t execute" > ./script.sh (nothing) > bash script.sh Shouldn't execute
  36. #!/bin/bash • Почему нельзя ставить флаги после “#!” ? #!/bin/bash

    -e false echo "Shouldn’t execute" > ./script.sh (nothing) > bash script.sh Shouldn't execute
  37. #!/bin/bash • Почему нельзя ставить флаги после “#!” ? #!/bin/bash

    set -e false echo "Shouldn’t execute" > ./script.sh (nothing) > bash script.sh (nothing)
  38. Зачем вообще версии? 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
  39. Зачем вообще версии? 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 …
  40. У нас есть git! • Мы как волшебники - можем

    путешествовать во времени и создавать параллельные вселенные
  41. У нас есть git! • Мы как волшебники - можем

    путешествовать во времени и создавать параллельные вселенные • Просто смотрим на ветки VCS - и всегда всё понятно
  42. У нас есть git! • Мы как волшебники - можем

    путешествовать во времени и создавать параллельные вселенные • Просто смотрим на ветки VCS - и всегда всё понятно
  43. У нас есть git! • Мы как волшебники - можем

    путешествовать во времени и создавать параллельные вселенные • Просто смотрим на ветки VCS - и всегда всё понятно
  44. У нас есть git! • Мы как волшебники - можем

    путешествовать во времени и создавать параллельные вселенные • Просто смотрим на ветки VCS - и всегда всё понятно
  45. У нас есть git! • Мы как волшебники - можем

    путешествовать во времени и создавать параллельные вселенные • Просто смотрим на ветки VCS - и всегда всё понятно
  46. У нас есть git! • Мы как волшебники - можем

    путешествовать во времени и создавать параллельные вселенные • Просто смотрим на ветки VCS - и всегда всё понятно
  47. У нас есть git! • Мы как волшебники - можем

    путешествовать во времени и создавать параллельные вселенные • Просто смотрим на ветки VCS - и всегда всё понятно
  48. У нас есть git! • Мы как волшебники - можем

    путешествовать во времени и создавать параллельные вселенные • Просто смотрим на ветки VCS - и всегда всё понятно
  49. У нас есть git! • Мы как волшебники - можем

    путешествовать во времени и создавать параллельные вселенные • Просто смотрим на ветки VCS - и всегда всё понятно • А если непонятно - наши коллеги всегда напишут понятные сообщения
  50. У нас есть git! • Мы как волшебники - можем

    путешествовать во времени и создавать параллельные вселенные • Просто смотрим на ветки VCS - и всегда всё понятно • А если непонятно - наши коллеги всегда напишут понятные сообщения
  51. У нас есть git! • Мы как волшебники - можем

    путешествовать во времени и создавать параллельные вселенные • Просто смотрим на ветки VCS - и всегда всё понятно • А если непонятно - наши коллеги всегда напишут понятные сообщения
  52. У нас есть git! • Мы как волшебники - можем

    путешествовать во времени и создавать параллельные вселенные • Просто смотрим на ветки VCS - и всегда всё понятно • А если непонятно - наши коллеги всегда напишут понятные сообщения
  53. У нас есть git! • Мы как волшебники - можем

    путешествовать во времени и создавать параллельные вселенные • Просто смотрим на ветки VCS - и всегда всё понятно • А если непонятно - наши коллеги всегда напишут понятные сообщения
  54. У нас есть git! • Мы как волшебники - можем

    путешествовать во времени и создавать параллельные вселенные • Просто смотрим на ветки VCS - и всегда всё понятно • А если непонятно - наши коллеги всегда напишут понятные сообщения
  55. У нас есть git! • Мы как волшебники - можем

    путешествовать во времени и создавать параллельные вселенные • Просто смотрим на ветки VCS - и всегда всё понятно • А если непонятно - наши коллеги всегда напишут понятные сообщения
  56. У нас есть git! • Мы как волшебники - можем

    путешествовать во времени и создавать параллельные вселенные • Просто смотрим на ветки VCS - и всегда всё понятно • А если непонятно - наши коллеги всегда напишут понятные сообщения
  57. У нас есть git! • Мы как волшебники - можем

    путешествовать во времени и создавать параллельные вселенные • Просто смотрим на ветки VCS - и всегда всё понятно • А если непонятно - наши коллеги всегда напишут понятные сообщения
  58. У нас есть git! • Мы как волшебники - можем

    путешествовать во времени и создавать параллельные вселенные • Просто смотрим на ветки VCS - и всегда всё понятно • А если непонятно - наши коллеги всегда напишут понятные сообщения
  59. У нас есть git! • Мы как волшебники - можем

    путешествовать во времени и создавать параллельные вселенные • Просто смотрим на ветки VCS - и всегда всё понятно • А если непонятно - наши коллеги всегда напишут понятные сообщения
  60. У нас есть git! • Мы как волшебники - можем

    путешествовать во времени и создавать параллельные вселенные • Просто смотрим на ветки VCS - и всегда всё понятно • А если непонятно - наши коллеги всегда напишут понятные сообщения
  61. У нас есть git! • Мы как волшебники - можем

    путешествовать во времени и создавать параллельные вселенные • Просто смотрим на ветки VCS - и всегда всё понятно • А если непонятно - наши коллеги всегда напишут понятные сообщения
  62. Langchain: усидеть на двух стульях Патч века: - historic_messages =

    config["configurable"]["message_history"].messages + historic_messages = await config["configurable"]["message_history"].aget_messages() Почему? • Копипаста • Метод называется “messages”, а не “get_messages”
  63. Bittensor • Блокчейн, много $$$ • Очень любят исключения •

    Но ещё больше любят возвращать результат
  64. Bittensor • Блокчейн, много $$$ • Очень любят исключения •

    Но ещё больше любят возвращать результат • Но коды ошибок - это как-то сложно
  65. Bittensor • Блокчейн, много $$$ • Очень любят исключения •

    Но ещё больше любят возвращать результат • Но коды ошибок - это как-то сложно • Поэтому…
  66. Bittensor • Блокчейн, много $$$ • Очень любят исключения •

    Но ещё больше любят возвращать результат • Но коды ошибок - это как-то сложно • Поэтому… is_success, msg = do_stuff()
  67. Bittensor • Блокчейн, много $$$ • Очень любят исключения •

    Но ещё больше любят возвращать результат • Но коды ошибок - это как-то сложно • Поэтому… try: is_success, msg = do_stuff() if not is_success: exc_class = parse_error(msg) raise exc_class(msg) except Exception: # handle exception
  68. Bittensor • Блокчейн, много $$$ • Очень любят исключения •

    Но ещё больше любят возвращать результат • Но коды ошибок - это как-то сложно • Поэтому… try: is_success, msg = do_stuff() if not is_success: exc_class = parse_error(msg) raise exc_class(msg) except Exception: # handle exception
  69. Bittensor • Блокчейн, много $$$ • Очень любят исключения •

    Но ещё больше любят возвращать результат • Но коды ошибок - это как-то сложно • Поэтому… • Но и это ещё не всё class Subtensor: def __init__(...): # Attempt to connect to chosen endpoint try: self.connect(...) except ConnectionRefusedError: _logger.error(...) exit(1)
  70. Bittensor • Блокчейн, много $$$ • Очень любят исключения •

    Но ещё больше любят возвращать результат • Но коды ошибок - это как-то сложно • Поэтому… • Но и это ещё не всё class Subtensor: def __init__(...): # Attempt to connect to chosen endpoint try: self.connect(...) except ConnectionRefusedError: _logger.error(...) exit(1)
  71. Bittensor • Блокчейн, много $$$ • Очень любят исключения •

    Но ещё больше любят возвращать результат • Но коды ошибок - это как-то сложно • Поэтому… • Но и это ещё не всё class Subtensor: def __init__(...): # Attempt to connect to chosen endpoint try: self.connect(...) except ConnectionRefusedError: _logger.error(...) exit(1)
  72. Это обычный код • Посылаем задание • После - замеряем

    время, за сколько нам придёт ответ • Что может пойти не так? before_time = now() await send_request(job) start_time = now() response = await ws.recv() response_time = now() score = response_time - start_time
  73. Это обычный код • Посылаем задание • После - замеряем

    время, за сколько нам придёт ответ • Что может пойти не так? before_time = now() await send_request(job) start_time = now() response = await ws.recv() response_time = now() score = response_time - start_time
  74. Это обычный npm • Хотите установить фреймворк? • Подождите пару

    минут, пока скачаются сотни зависимостей • Не переживайте! Вряд ли хоть в одной из них есть уязвимости > npx create-next-app added 360 packages in 3m > npx create-remix 631 > npx create-gatsby 864 > npx create-react-app 1480
  75. Это обычный npm • Хотите установить фреймворк? • Подождите пару

    минут, пока скачаются сотни зависимостей • Не переживайте! Вряд ли хоть в одной из них есть уязвимости > npx create-next-app added 360 packages in 3m > npx create-remix 631 > npx create-gatsby 864 > npx create-react-app 1480
  76. Это обычный npm • Хотите установить фреймворк? • Подождите пару

    минут, пока скачаются сотни зависимостей • Не переживайте! Вряд ли хоть в одной из них есть уязвимости > npx create-next-app added 360 packages in 3m > npx create-remix 631 > npx create-gatsby 864 > npx create-react-app 1480
  77. Это обычный npm • Хотите установить фреймворк? • Подождите пару

    минут, пока скачаются сотни зависимостей • Не переживайте! Вряд ли хоть в одной из них есть уязвимости > npx create-next-app added 360 packages in 3m > npx create-remix 631 > npx create-gatsby 864 > npx create-react-app 1480
  78. Бэкап postgres • Делаем бэкап: pg_dump postgres > dump.sql •

    Восстанавливаемся из бэкапа: pg_restore postgres < dump.sql
  79. Бэкап postgres • Делаем бэкап: pg_dump postgres > dump.sql •

    Восстанавливаемся из бэкапа: pg_restore postgres < dump.sql pg_restore: error: input file does not appear to be a valid archive
  80. Бэкап 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
  81. 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
  82. 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
  83. 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
  84. 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
  85. 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
  86. 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'
  87. 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'
  88. 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'
  89. 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'
  90. 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'
  91. 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'
  92. 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'
  93. 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'
  94. 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'
  95. 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'
  96. 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'
  97. 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)
  98. 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)
  99. 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)
  100. 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)
  101. 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)
  102. 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)
  103. 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)
  104. 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)
  105. 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)
  106. Python: скобки • Ну да, ну да, вот наш питон-то

    простой и логичный! {'a': 1} # это словарь dict(a=1) # это то же самое {'a'} # это множество (set) {} # это не пустое множество, это пустой словарь set() # а вот это пустое множество
  107. Python: скобки • Ну да, ну да, вот наш питон-то

    простой и логичный! {'a': 1} # это словарь dict(a=1) # это то же самое {'a'} # это множество (set) {} # это не пустое множество, это пустой словарь set() # а вот это пустое множество
  108. Python: скобки • Ну да, ну да, вот наш питон-то

    простой и логичный! {'a': 1} # это словарь dict(a=1) # это то же самое {'a'} # это множество (set) {} # это не пустое множество, это пустой словарь set() # а вот это пустое множество
  109. Python: скобки • Ну да, ну да, вот наш питон-то

    простой и логичный! {'a': 1} # это словарь dict(a=1) # это то же самое {'a'} # это множество (set) {} # это не пустое множество, это пустой словарь set() # а вот это пустое множество
  110. Python: скобки • Ну да, ну да, вот наш питон-то

    простой и логичный! {'a': 1} # это словарь dict(a=1) # это то же самое {'a'} # это множество (set) {} # это не пустое множество, это пустой словарь set() # а вот это пустое множество
  111. Python: скобки • Ну да, ну да, вот наш питон-то

    простой и логичный! {'a': 1} # это словарь dict(a=1) # это то же самое {'a'} # это множество (set) {} # это не пустое множество, это пустой словарь set() # а вот это пустое множество
  112. Python: скобки • Ну да, ну да, вот наш питон-то

    простой и логичный! {'a': 1} # это словарь dict(a=1) # это то же самое {'a'} # это множество (set) {} # это не пустое множество, это пустой словарь set() # а вот это пустое множество
  113. Python: скобки • Ну да, ну да, вот наш питон-то

    простой и логичный! {'a': 1} # это словарь dict(a=1) # это то же самое {'a'} # это множество (set) {} # это не пустое множество, это пустой словарь set() # а вот это пустое множество
  114. Python: скобки • Ну да, ну да, вот наш питон-то

    простой и логичный! {'a': 1} # это словарь dict(a=1) # это то же самое {'a'} # это множество (set) {} # это не пустое множество, это пустой словарь set() # а вот это пустое множество
  115. Python: скобки • Ну да, ну да, вот наш питон-то

    простой и логичный! 1 # это просто число (int) (1+2) # это число (1, 2) # это кортеж (tuple) (1) # это тоже просто число 1, # это тоже кортеж () # это пустой кортеж (,) # SyntaxError
  116. Python: скобки • Ну да, ну да, вот наш питон-то

    простой и логичный! 1 # это просто число (int) (1+2) # это число (1, 2) # это кортеж (tuple) (1) # это тоже просто число 1, # это тоже кортеж () # это пустой кортеж (,) # SyntaxError
  117. Python: скобки • Ну да, ну да, вот наш питон-то

    простой и логичный! 1 # это просто число (int) (1+2) # это число (1, 2) # это кортеж (tuple) (1) # это тоже просто число 1, # это тоже кортеж () # это пустой кортеж (,) # SyntaxError
  118. Python: скобки • Ну да, ну да, вот наш питон-то

    простой и логичный! 1 # это просто число (int) (1+2) # это число (1, 2) # это кортеж (tuple) (1) # это тоже просто число 1, # это тоже кортеж () # это пустой кортеж (,) # SyntaxError
  119. Python: скобки • Ну да, ну да, вот наш питон-то

    простой и логичный! 1 # это просто число (int) (1+2) # это число (1, 2) # это кортеж (tuple) (1) # это тоже просто число 1, # это тоже кортеж () # это пустой кортеж (,) # SyntaxError
  120. Python: скобки • Ну да, ну да, вот наш питон-то

    простой и логичный! 1 # это просто число (int) (1+2) # это число (1, 2) # это кортеж (tuple) (1) # это тоже просто число 1, # это тоже кортеж () # это пустой кортеж (,) # SyntaxError
  121. Python: скобки • Ну да, ну да, вот наш питон-то

    простой и логичный! 1 # это просто число (int) (1+2) # это число (1, 2) # это кортеж (tuple) (1) # это тоже просто число 1, # это тоже кортеж () # это пустой кортеж (,) # SyntaxError
  122. Python: скобки • Ну да, ну да, вот наш питон-то

    простой и логичный! 1 # это просто число (int) (1+2) # это число (1, 2) # это кортеж (tuple) (1) # это тоже просто число 1, # это тоже кортеж () # это пустой кортеж (,) # SyntaxError
  123. Python: скобки • Ну да, ну да, вот наш питон-то

    простой и логичный! 1 # это просто число (int) (1+2) # это число (1, 2) # это кортеж (tuple) (1) # это тоже просто число 1, # это тоже кортеж () # это пустой кортеж (,) # SyntaxError
  124. Python: скобки • Ну да, ну да, вот наш питон-то

    простой и логичный! 1 # это просто число (int) (1+2) # это число (1, 2) # это кортеж (tuple) (1) # это тоже просто число 1, # это тоже кортеж () # это пустой кортеж (,) # SyntaxError
  125. Python: скобки • Ну да, ну да, вот наш питон-то

    простой и логичный! 1 # это просто число (int) (1+2) # это число (1, 2) # это кортеж (tuple) (1) # это тоже просто число 1, # это тоже кортеж () # это пустой кортеж (,) # SyntaxError
  126. Python: скобки • Ну да, ну да, вот наш питон-то

    простой и логичный! 1 # это просто число (int) (1+2) # это число (1, 2) # это кортеж (tuple) (1) # это тоже просто число 1, # это тоже кортеж () # это пустой кортеж (,) # SyntaxError
  127. Python: скобки • Ну да, ну да, вот наш питон-то

    простой и логичный! 1 # это просто число (int) (1+2) # это число (1, 2) # это кортеж (tuple) (1) # это тоже просто число 1, # это тоже кортеж () # это пустой кортеж (,) # SyntaxError
  128. Python: скобки • Ну да, ну да, вот наш питон-то

    простой и логичный! 1 # это просто число (int) (1+2) # это число (1, 2) # это кортеж (tuple) (1) # это тоже просто число 1, # это тоже кортеж () # это пустой кортеж (,) # SyntaxError
  129. Python: скобки • Ну да, ну да, вот наш питон-то

    простой и логичный! [] # это пустой список [1] # это список с одним элементом [1, 2, 3] # это список с 3 элементами [i for i in range(3)] # это тоже список с 3 элементами () # это пустой кортеж (1) # это просто число (1, 2, 3) # это (ха-ха) кортеж (i for i in range(3)) # это не кортеж, это генератор :D
  130. Python: скобки • Ну да, ну да, вот наш питон-то

    простой и логичный! [] # это пустой список [1] # это список с одним элементом [1, 2, 3] # это список с 3 элементами [i for i in range(3)] # это тоже список с 3 элементами () # это пустой кортеж (1) # это просто число (1, 2, 3) # это (ха-ха) кортеж (i for i in range(3)) # это не кортеж, это генератор :D
  131. Python: скобки • Ну да, ну да, вот наш питон-то

    простой и логичный! [] # это пустой список [1] # это список с одним элементом [1, 2, 3] # это список с 3 элементами [i for i in range(3)] # это тоже список с 3 элементами () # это пустой кортеж (1) # это просто число (1, 2, 3) # это (ха-ха) кортеж (i for i in range(3)) # это не кортеж, это генератор :D
  132. Python: скобки • Ну да, ну да, вот наш питон-то

    простой и логичный! [] # это пустой список [1] # это список с одним элементом [1, 2, 3] # это список с 3 элементами [i for i in range(3)] # это тоже список с 3 элементами () # это пустой кортеж (1) # это просто число (1, 2, 3) # это (ха-ха) кортеж (i for i in range(3)) # это не кортеж, это генератор :D
  133. Python: скобки • Ну да, ну да, вот наш питон-то

    простой и логичный! [] # это пустой список [1] # это список с одним элементом [1, 2, 3] # это список с 3 элементами [i for i in range(3)] # это тоже список с 3 элементами () # это пустой кортеж (1) # это просто число (1, 2, 3) # это (ха-ха) кортеж (i for i in range(3)) # это не кортеж, это генератор :D
  134. Python: скобки • Ну да, ну да, вот наш питон-то

    простой и логичный! [] # это пустой список [1] # это список с одним элементом [1, 2, 3] # это список с 3 элементами [i for i in range(3)] # это тоже список с 3 элементами () # это пустой кортеж (1) # это просто число (1, 2, 3) # это (ха-ха) кортеж (i for i in range(3)) # это не кортеж, это генератор :D
  135. Python: скобки • Ну да, ну да, вот наш питон-то

    простой и логичный! [] # это пустой список [1] # это список с одним элементом [1, 2, 3] # это список с 3 элементами [i for i in range(3)] # это тоже список с 3 элементами () # это пустой кортеж (1) # это просто число (1, 2, 3) # это (ха-ха) кортеж (i for i in range(3)) # это не кортеж, это генератор :D
  136. Python: скобки • Ну да, ну да, вот наш питон-то

    простой и логичный! [] # это пустой список [1] # это список с одним элементом [1, 2, 3] # это список с 3 элементами [i for i in range(3)] # это тоже список с 3 элементами () # это пустой кортеж (1) # это просто число (1, 2, 3) # это (ха-ха) кортеж (i for i in range(3)) # это не кортеж, это генератор :D
  137. Python: скобки • Ну да, ну да, вот наш питон-то

    простой и логичный! [] # это пустой список [1] # это список с одним элементом [1, 2, 3] # это список с 3 элементами [i for i in range(3)] # это тоже список с 3 элементами () # это пустой кортеж (1) # это просто число (1, 2, 3) # это (ха-ха) кортеж (i for i in range(3)) # это не кортеж, это генератор :D
  138. Python: скобки • Ну да, ну да, вот наш питон-то

    простой и логичный! [] # это пустой список [1] # это список с одним элементом [1, 2, 3] # это список с 3 элементами [i for i in range(3)] # это тоже список с 3 элементами () # это пустой кортеж (1) # это просто число (1, 2, 3) # это (ха-ха) кортеж (i for i in range(3)) # это не кортеж, это генератор :D
  139. Python: скобки • Ну да, ну да, вот наш питон-то

    простой и логичный! [] # это пустой список [1] # это список с одним элементом [1, 2, 3] # это список с 3 элементами [i for i in range(3)] # это тоже список с 3 элементами () # это пустой кортеж (1) # это просто число (1, 2, 3) # это кортеж (i for i in range(3)) # это не кортеж, это генератор :D
  140. Python: скобки • Ну да, ну да, вот наш питон-то

    простой и логичный! [] # это пустой список [1] # это список с одним элементом [1, 2, 3] # это список с 3 элементами [i for i in range(3)] # это тоже список с 3 элементами () # это пустой кортеж (1) # это просто число (1, 2, 3) # это кортеж (i for i in range(3)) # это не кортеж, это генератор
  141. Python: скобки • Ну да, ну да, вот наш питон-то

    простой и логичный! [] # это пустой список [1] # это список с одним элементом [1, 2, 3] # это список с 3 элементами [i for i in range(3)] # это тоже список с 3 элементами () # это пустой кортеж (1) # это просто число (1, 2, 3) # это кортеж (i for i in range(3)) # это не кортеж, это генератор
  142. 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 :)
  143. 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 :)
  144. 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 :)
  145. 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) Всё ок!
  146. 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
  147. 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'
  148. 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'
  149. 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'
  150. 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'
  151. 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'
  152. 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')
  153. Pull request • Создаю как обычно PR в master •

    Ловлю конфликт с файлом, которого у меня нет • Но который есть в master master
  154. Pull request • Создаю как обычно PR в master •

    Ловлю конфликт с файлом, которого у меня нет • Но который есть в master master
  155. PgBouncer • Приложения можно подключать к базе напрямую • Но

    если их много, то слишком много соединений с БД App Postgres App App App App App
  156. PgBouncer • Приложения можно подключать к базе напрямую • Но

    если их много, то слишком много соединений с БД • Решение - PgBouncer, который управляет пулом соединений App Postgres App App App App App PgBouncer
  157. 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; ...
  158. 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; ...
  159. PgBouncer • SELECT pg_catalog.set_config( 'search_path', '', false); • “Забудь всё,

    что ты знал до этого” App Postgres App App psql App PgBouncer
  160. PgBouncer • SELECT pg_catalog.set_config( 'search_path', '', false); • “Забудь всё,

    что ты знал до этого” App Postgres App App App PgBouncer
  161. PgBouncer • SELECT pg_catalog.set_config( 'search_path', '', false); • “Забудь всё,

    что ты знал до этого” App Postgres App App psql App PgBouncer
  162. 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
  163. 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:
  164. 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.
  165. 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
  166. Мой любимый 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. """
  167. Vscode: почему?! • Пора уже разобраться • Всё, что до

    синтаксической ошибки - работает • Всё, что после - не работает Б р о Н е б р о
  168. 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.
  169. 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
  170. 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) ):
  171. 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) ):
  172. Ruff calls = [ ("archive", dump.netuid, block) for block in

    list(chain.from_iterable(dumpable_blocks))[::-1] if block != 1673 ] Что получаем Откуда Фильтр
  173. Ruff calls = [ ("archive", dump.netuid, block) for block in

    list(chain.from_iterable(dumpable_blocks))[::-1] if block != 1 ]
  174. 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 ==
  175. React • В документации вот такой код const [squares, setSquares]

    = useState(Array(9).fill(null)); function handleClick() { const nextSquares = squares.slice(); nextSquares[0] = "X"; setSquares(nextSquares); } X
  176. React • В документации вот такой код • Минут пять

    убиваю, чтобы понять, зачем делать слайс и менять в нём только первый элемент • Так нихрена и не понял • Ладно, читаю дальше const [squares, setSquares] = useState(Array(9).fill(null)); function handleClick() { const nextSquares = squares.slice(); nextSquares[0] = "X"; setSquares(nextSquares); } X
  177. React “Теперь вы можете добавлять крестики на доску… но только

    в верхний левый квадрат. Ваша функция "handleClick" жестко запрограммирована для обновления индекса для верхнего левого квадрата (0). Давайте обновим "handleClick", чтобы иметь возможность обновлять любой квадрат.” const [squares, setSquares] = useState(Array(9).fill(null)); function handleClick() { const nextSquares = squares.slice(); nextSquares[0] = "X"; setSquares(nextSquares); } X
  178. Beer Meetup • Прихожу в бар • Сижу полчаса наедине

    с выпивкой • Никого нет • Приходят какие-то девушки
  179. Beer Meetup • Прихожу в бар • Сижу полчаса наедине

    с выпивкой • Никого нет • Приходят какие-то девушки • Я им затираю про питон, они ничего не понимают
  180. Beer Meetup • Прихожу в бар • Сижу полчаса наедине

    с выпивкой • Никого нет • Приходят какие-то девушки • Я им затираю про питон, они ничего не понимают • Проверяю календарь
  181. Beer Meetup • Прихожу в бар • Сижу полчаса наедине

    с выпивкой • Никого нет • Приходят какие-то девушки • Я им затираю про питон, они ничего не понимают • Проверяю календарь • Я перепутал даты и пришёл ровно на неделю раньше