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

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 • Прихожу в бар • Сижу полчаса наедине

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