Взаимодействие на основе патчей. Работа с сетью

Ещё про работу с историей

Статья на Хабре про стратегии git merge

Раздельное добавление ханков

Работа с патчами и наборами патчей

Немного о формате

Патчи и Git:

Патч или набор с точки зрения GIT — это сериализация коммитов, превращение их в пригодный для передачи формат.

BTW: difflib

Простейший сетевой сервер

Тупой аналог netcat с помощью socket:

   1 import sys
   2 import socket
   3 
   4 with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
   5     s.connect((sys.argv[1], int(sys.argv[2]) if len(sys.argv) > 2 else 1337))
   6     while msg := sys.stdin.readline():
   7         s.sendall(msg.strip().encode())
   8         print(s.recv(1024).decode())

Посмотрим в примеры. В частности, echo-сервер:

   1 import asyncio
   2 
   3 async def echo(reader, writer):
   4     while data := await reader.readline():
   5         writer.write(data.swapcase())
   6     writer.close()
   7     await writer.wait_closed()
   8 
   9 async def main():
  10     server = await asyncio.start_server(echo, '0.0.0.0', 1337)
  11     async with server:
  12         await server.serve_forever()
  13 
  14 asyncio.run(main())

Используем Streams для написания «общего чата».

   1 #!/usr/bin/env python3
   2 import asyncio
   3 
   4 clients = {}
   5 
   6 async def chat(reader, writer):
   7     me = "{}:{}".format(*writer.get_extra_info('peername'))
   8     print(me)
   9     clients[me] = asyncio.Queue()
  10     send = asyncio.create_task(reader.readline())
  11     receive = asyncio.create_task(clients[me].get())
  12     while not reader.at_eof():
  13         done, pending = await asyncio.wait([send, receive], return_when=asyncio.FIRST_COMPLETED)
  14         for q in done:
  15             if q is send:
  16                 send = asyncio.create_task(reader.readline())
  17                 for out in clients.values():
  18                     if out is not clients[me]:
  19                         await out.put(f"{me} {q.result().decode().strip()}")
  20             elif q is receive:
  21                 receive = asyncio.create_task(clients[me].get())
  22                 writer.write(f"{q.result()}\n".encode())
  23                 await writer.drain()
  24     send.cancel()
  25     receive.cancel()
  26     print(me, "DONE")
  27     del clients[me]
  28     writer.close()
  29     await writer.wait_closed()
  30 
  31 async def main():
  32     server = await asyncio.start_server(chat, '0.0.0.0', 1337)
  33     async with server:
  34         await server.serve_forever()
  35 
  36 asyncio.run(main())

Д/З

  1. Почитать про asyncio

  2. Превратить «общий чат» в «коровий» следующим образом:
    • Вводимые строки состоят из команды с возможными параметрами
    • Вместо get_extra_info('peername') уникальным идентификатором пользователя является название коровы из Streams

      • Пока пользователь не зарегистрировался, он не имеет право ни писать, ни получать сообщения
    • Сообщения оформляются с помощью cowsay() из модуля python-cowsay

    • Команды:
      • who — просмотр зарегистрированных пользователей

      • cows — просмотр свободных имён коров

      • login название_коровы — зарегистрироваться под именем название_коровы

      • say название_коровы текст сообщения — послать сообщение пользователю название_коровы

      • yield текст сообщения — послать сообщение всем зарегистрированным пользователям

      • quit — отключиться

  3. {2} (необязательный пункт — оказалось, что это непросто) Написать более продвинутый аналог netcat для соединения с «коровьим чатом»

    • Клиент должен принимать и отправлять строки асинхронно

    • Использовать Streams

    • Использовать readline или cmd (можно подставлять команды)

      • необязательно: complete_login() и complete_say() могут ходить на сервер, выполнять там , соответственно, cows и who и подставлять соответствующие списки

    • Если не делать этого пункта, вместо клиента можно пользоваться либо системным netcat, либо простым скриптом

  4. Разработку вести согласно дисциплине оформления коммитов в подкаталоге 05_DiffPatchNet отчётного репозитория по Д/З

  5. Предполагается, что модуль python-cowsay устанавливается в окружение с помощью pipenv, в каталоге должен присутствовать соответствующий Pipfile

LecturesCMC/PythonDevelopment2023/05_DiffPatchNet (последним исправлял пользователь FrBrGeorge 2023-05-31 16:04:20)