Python-ELMO is a Python library which offers an encapsulation of the binary tool ELMO, in order to manipulate it easily in Python and SageMath script.
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

protocol.py 3.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. import os
  2. import json
  3. class ClosureException(Exception):
  4. pass
  5. # https://stackoverflow.com/questions/20007319/how-to-do-a-large-text-file-transfer-in-python
  6. class SocketTool:
  7. @classmethod
  8. def convert_to_bytes(cl, no):
  9. result = bytearray()
  10. result.append(no & 255)
  11. for i in range(3):
  12. no = no >> 8
  13. result.append(no & 255)
  14. return result
  15. @classmethod
  16. def bytes_to_number(cl, b):
  17. import sys
  18. b = b if (sys.version_info > (3, 0)) else map(ord, b)
  19. res = 0
  20. for i in range(4):
  21. res += b[i] << (i*8)
  22. return res
  23. @classmethod
  24. def send_file(cl, s, filename, mode='rb'):
  25. length = os.path.getsize(filename)
  26. s.send(cl.convert_to_bytes(length)) # has to be 4 bytes
  27. with open(filename, mode) as infile:
  28. d = infile.read(1024*64) # We send by pack of 64 ko
  29. while d:
  30. s.send(d)
  31. d = infile.read(1024*64)
  32. @classmethod
  33. def get_file(cl, s):
  34. size = s.recv(4) # assuming that the size won't be bigger then 1GB
  35. size = cl.bytes_to_number(size)
  36. current_size = 0
  37. buffer = b''
  38. while current_size < size:
  39. data = s.recv(1024*64)
  40. if not data:
  41. break
  42. if len(data) + current_size > size:
  43. data = data[:size-current_size] # trim additional data
  44. buffer += data
  45. # you can stream here to disk
  46. current_size += len(data)
  47. # you have entire file in memory
  48. return buffer
  49. @classmethod
  50. def send_data(cl, s, data):
  51. data = json.dumps(data)
  52. data = data.encode('utf-8')
  53. s.send(cl.convert_to_bytes(len(data))) # has to be 4 bytes
  54. for i in range(0, len(data), 1024*64):
  55. s.send(data[i:i+1024*64])
  56. @classmethod
  57. def get_data(cl, s):
  58. import sys
  59. exception_class = json.decoder.JSONDecodeError if (sys.version_info > (3, 0)) else ValueError
  60. try:
  61. data = cl.get_file(s)
  62. data = data.decode('utf-8')
  63. data = json.loads(data)
  64. return data
  65. except exception_class:
  66. return None
  67. @classmethod
  68. def send_ack(cl, s, positive=True):
  69. data = 'OK' if positive else 'NO'
  70. s.send(data.encode('ascii'))
  71. @classmethod
  72. def get_ack(cl, s):
  73. data = s.recv(2).decode('ascii')
  74. return (data == 'OK')
  75. class Protocol:
  76. def __init__(self, clientsocket):
  77. self.clientsocket = clientsocket
  78. def send_file(self, filename, mode='rb'):
  79. SocketTool.send_file(self.clientsocket, filename, mode)
  80. def get_file(self):
  81. return SocketTool.get_file(self.clientsocket)
  82. def send_data(self, data):
  83. SocketTool.send_data(self.clientsocket, data)
  84. def get_data(self):
  85. return SocketTool.get_data(self.clientsocket)
  86. def send_ack(self, positive=True):
  87. SocketTool.send_ack(self.clientsocket, positive)
  88. def send_nack(self, positive=True):
  89. SocketTool.send_ack(self.clientsocket, not positive)
  90. def get_ack(self):
  91. return SocketTool.get_ack(self.clientsocket)
  92. def please_assert(self, condition):
  93. if not condition:
  94. self.send_nack()
  95. self.clientsocket.close()
  96. raise ClosureException
  97. def get_object_or_nack(self, model, **kwargs):
  98. try:
  99. return model.objects.get(**kwargs)
  100. except model.DoesNotExist:
  101. self.send_nack()
  102. self.clientsocket.close()
  103. raise ClosureException
  104. def close(self):
  105. self.clientsocket.close()