Advertisement
Guest User

Untitled

a guest
Oct 18th, 2019
89
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.59 KB | None | 0 0
  1. import itertools
  2.  
  3. tests_passed = {
  4. 'simple end of line':
  5. [ b'One\nSSH>',
  6. b'no!',
  7. ],
  8. 'simple begining of line':
  9. [ b'SSH>',
  10. ],
  11. 'simple empty lines':
  12. [ b'\n',
  13. b'\n',
  14. b'SSH>',
  15. b'no!',
  16. ],
  17. 'last character cut':
  18. [ b'One\nSSH',
  19. b'>',
  20. ],
  21. 'last two characters cut':
  22. [ b'One\nSS',
  23. b'H>',
  24. ],
  25. 'cut after first':
  26. [ b'One\nS',
  27. b'SH>',
  28. ],
  29. }
  30. tests_to_do = {
  31. 'cut by a new line':
  32. [ b'One\nS\n',
  33. b'SH>',
  34. b'this should show\n',
  35. b'SSH>',
  36. ],
  37. 'all cut':
  38. [ b'One\nS',
  39. b'S',
  40. b'H',
  41. b'>',
  42. b'no!',
  43. ],
  44. 'false alsert':
  45. [ b'One\nSS H>',
  46. b'\nSSH>',
  47. ],
  48. 'false alsert on two lines':
  49. [ b'One\nSS',
  50. b' H> '
  51. b'Yes\nSSH>',
  52. ],
  53. 'false alert all cut':
  54. [ b'One\nS',
  55. b'S',
  56. b'H',
  57. b' >',
  58. b'SSH>',
  59. ],
  60. }
  61.  
  62. tests = {}
  63. tests.update(tests_passed)
  64. tests.update(tests_to_do)
  65.  
  66. prompts_that_work = [
  67. ]
  68. prompts = [
  69. 'SSH>',
  70. 'SS*>',
  71. 'S*H>',
  72. 'S*>',
  73. '*>',
  74. '*SH>',
  75. '*S*>',
  76. 'SSH*',
  77. 'S.H*',
  78. '....',
  79. #'...*' This one does not work...
  80. ]
  81.  
  82. def fake_read(name):
  83. #print(f'Testing "{name}"')
  84. for line in tests[name]:
  85. yield line
  86. #print(f'Test "{name}" complete!\n')
  87.  
  88.  
  89. def position_of_next_character_to_match(prompt, marker):
  90. for pos in range(marker+1, len(prompt)):
  91. if prompt[pos] != '*':
  92. marker = pos
  93. break
  94. return min(len(prompt), marker)
  95.  
  96.  
  97. def forward_to_character_following(iterator, character):
  98. for c in iterator:
  99. if c == ord(character):
  100. break
  101. return iterator
  102.  
  103.  
  104. def forward_to_begining_of_new_line(iterator):
  105. return forward_to_character_following(iterator, '\n')
  106.  
  107.  
  108. def find_wildcard_stop_character(marker):
  109. try:
  110. after_wildcard = next(marker)
  111. #Collapse a series of ***** into a single star, making SS******> the same as SS*> (both match SSH>)
  112. while after_wildcard == '*':
  113. after_wildcard = next(marker)
  114.  
  115. return after_wildcard
  116. except StopIteration:
  117. #The prompt ends with a wildcard...
  118. pass
  119.  
  120.  
  121. def eat_next_character(iterator):
  122. loop = True
  123. byte = None
  124. try:
  125. byte = next(iterator)
  126. except StopIteration:
  127. loop = False
  128.  
  129. return byte, loop
  130.  
  131. def new_test(name, prompt):
  132.  
  133. received_chunks = []
  134.  
  135. reader = fake_read(name)
  136.  
  137. data = next(reader)
  138. marker = iter(prompt)
  139.  
  140. looking_for = next(marker)
  141. match_anything = looking_for == '.'
  142. if looking_for == '*':
  143. #Make a copy of the iterator. Will also server as a flag
  144. #that we are in wildcard mode
  145. marker, saved_marker = itertools.tee(marker)
  146. #and start looking for the remainder of the prompt
  147. #as if it was what we were looking for all along
  148. looking_for = find_wildcard_stop_character(marker)
  149. else:
  150. saved_marker = None
  151.  
  152. partial_match = False
  153.  
  154. while data:
  155. received_chunks.append(data)
  156.  
  157. #For every character in the string
  158. iterator = iter(data)
  159.  
  160. #Possible states:
  161. #0: Looking for next character after new line
  162. #1: Looking for the next character in the prompt string
  163. #2: Looging for the next charcter that would stop the non-greedy wildcard search
  164. loop = True
  165.  
  166. byte = next(iterator)
  167. #We expect the prompt to start a new line, so go looging for it
  168. #find_begining_of_new_line(iterator):
  169. while loop: #We cannot use a for loop because we might have to test a character twice
  170. # If tne character at marker the next one we are looking for? It can be
  171. # - The exact char
  172. # - Any character because the prompt specification had a . in it
  173. if chr(byte) == looking_for or match_anything:
  174. partial_match = True
  175.  
  176. try:
  177. # Increment the counter optimistically
  178. looking_for = next(marker)
  179. #Will we match the next char as is?
  180. match_anything = looking_for == '.'
  181. #If we were in wildcard mode, it's over because we found the character
  182. #that made us break out of it
  183. #but maybe there is another wild card right after it
  184. if looking_for == '*':
  185. #We start a new search for the remainder of the prompt
  186. partial_match = False
  187. marker, saved_marker = itertools.tee(marker)
  188. looking_for = find_wildcard_stop_character(marker)
  189.  
  190. # If there are no more character to find
  191. except StopIteration:
  192. # found it!
  193. data = None #Signal to get out of the while loop
  194. break #Get out of the for loop
  195.  
  196. #If we reach here, we haven't found it all yet, continue
  197. byte, loop = eat_next_character(iterator)
  198.  
  199. elif saved_marker:
  200. #We've set looking_for to the character that will get us out the wildcard loop
  201. #so if we get here this is just any other charcter, there is nothing to do but
  202. #iterate and see.
  203. marker, saved_marker = itertools.tee(saved_marker)
  204. #We already visited the position in saved_marker. We know it is not a special
  205. #character and that it will not raise. But we could be at end of line of the marker
  206. try:
  207. looking_for = next(marker)
  208. except StopIteration:
  209. # found it!
  210. data = None #Signal to get out of the while loop
  211. break #Get out of the for loop
  212.  
  213. #We failed to match this character, but maybe it is the start of
  214. #a new prompt. Let's *not* advance the iterator and try again, now
  215. #that we reset the prompt iterator
  216. if not partial_match:
  217. byte, loop = eat_next_character(iterator)
  218. else:
  219. #But that's a one time thing
  220. partial_match = False
  221. else:
  222. #Start to search from begining of prompt again
  223. marker = iter(prompt)
  224. looking_for = next(marker)
  225. match_anything = looking_for == '.'
  226. partial_match = False
  227. #If the character that did not match happens to be a new line
  228. #then we must let the loop iterate, or else it will skip valid
  229. #characters after the \n looking for another one. For example,
  230. #if we parsing through "\nSSH>\n". Without that if, the call to
  231. #forward_to_begining_of_new_line will skip over the SSH we are
  232. #looking for!
  233. if chr(byte) != '\n':
  234. byte,loop = eat_next_character(forward_to_begining_of_new_line(iterator))
  235. else:
  236. byte, loop = eat_next_character(iterator)
  237. else:
  238. #We read all the data without finding anything
  239. data = next(reader)
  240.  
  241.  
  242. lines = b''.join(received_chunks).decode('utf-8').split('\n')
  243.  
  244. return lines
  245.  
  246.  
  247.  
  248. for name in tests.keys():
  249. for prompt in prompts:
  250. print(f"Result for [{name},{prompt}] ", end='')
  251. print(f"{new_test(name, prompt)}")
  252. print('---------------------------------')
  253. print()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement