Tue, 31 Dec 2013 18:03:31 +0100
First implementation for the BackgroundService.
3159
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
1 | # -*- coding: utf-8 -*- |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
2 | |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
3 | # Copyright (c) 2013 - 2014 Detlev Offenbach <detlev@die-offenbachs.de> |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
4 | # |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
5 | |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
6 | """ |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
7 | Module implementing a Qt free version of a background client for the various |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
8 | checkers and other python interpreter dependent functions. |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
9 | """ |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
10 | |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
11 | from __future__ import unicode_literals |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
12 | try: |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
13 | bytes = unicode #__IGNORE_WARNING__ |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
14 | except NameError: |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
15 | pass |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
16 | |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
17 | import json |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
18 | import os |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
19 | import socket |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
20 | import struct |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
21 | import sys |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
22 | from zlib import adler32 |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
23 | |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
24 | if __name__ == '__main__': |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
25 | # Add Eric basepath to sys.path to be able to import modules which are |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
26 | # laying not only below Utilities |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
27 | path = os.path.dirname(sys.argv[0]) |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
28 | path = os.path.dirname(path) |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
29 | sys.path.append(path) |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
30 | |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
31 | from Plugins.CheckerPlugins.SyntaxChecker import SyntaxCheck |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
32 | |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
33 | |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
34 | class BackgroundClient(object): |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
35 | """ |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
36 | Class implementing the main part of the background client. |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
37 | """ |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
38 | def __init__(self, host, port): |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
39 | """ |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
40 | Constructor of the BackgroundClient class. |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
41 | |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
42 | @param host ip address the background service is listening |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
43 | @param port port of the background service |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
44 | """ |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
45 | self.connection = socket.create_connection((host, port)) |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
46 | ver = b'2' if sys.version_info[0] == 2 else b'3' |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
47 | self.connection.sendall(ver) |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
48 | self.connection.settimeout(0.25) |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
49 | |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
50 | def __send(self, fx, fn, data): |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
51 | """ |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
52 | Private method to send a job response back to the BackgroundService. |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
53 | |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
54 | @param fx remote function name to execute (str) |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
55 | @param fn filename for identification (str) |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
56 | @param data return value(s) (any basic datatype) |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
57 | """ |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
58 | packedData = json.dumps([fx, fn, data]) |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
59 | if sys.version_info[0] == 3: |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
60 | packedData = bytes(packedData, 'utf-8') |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
61 | header = struct.pack( |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
62 | b'!II', len(packedData), adler32(packedData) & 0xffffffff) |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
63 | self.connection.sendall(header) |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
64 | self.connection.sendall(packedData) |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
65 | |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
66 | def run(self): |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
67 | """ |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
68 | Implement the main loop of the client. |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
69 | """ |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
70 | while True: |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
71 | try: |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
72 | header = self.connection.recv(8) # __IGNORE_EXCEPTION__ |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
73 | except socket.timeout: |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
74 | continue |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
75 | except socket.error: |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
76 | # Leave main loop if connection was closed. |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
77 | break |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
78 | # Leave main loop if connection was closed. |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
79 | if not header: |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
80 | break |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
81 | |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
82 | length, datahash = struct.unpack(b'!II', header) |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
83 | |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
84 | packedData = b'' |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
85 | while len(packedData) < length: |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
86 | packedData += self.connection.recv(length - len(packedData)) |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
87 | |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
88 | assert adler32(packedData) & 0xffffffff == datahash, \ |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
89 | 'Hashes not equal' |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
90 | if sys.version_info[0] == 3: |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
91 | packedData = packedData.decode('utf-8') |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
92 | fx, fn, data = json.loads(packedData) |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
93 | if fx == 'syntax': |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
94 | ret = SyntaxCheck.syntaxAndPyflakesCheck(fn, *data) |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
95 | elif fx == 'style': |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
96 | print(data) |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
97 | elif fx == 'indent': |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
98 | pass |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
99 | else: |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
100 | continue |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
101 | |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
102 | self.__send(fx, fn, ret) |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
103 | |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
104 | self.connection.close() |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
105 | sys.exit() |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
106 | |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
107 | def __unhandled_exception(self, exctype, excval, exctb): |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
108 | """ |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
109 | Private method called to report an uncaught exception. |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
110 | |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
111 | @param exctype the type of the exception |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
112 | @param excval data about the exception |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
113 | @param exctb traceback for the exception |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
114 | """ |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
115 | # TODO: Wrap arguments so they can be serialized by JSON |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
116 | self.__send( |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
117 | 'exception', '?', [str(exctype), str(excval), str(exctb)]) |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
118 | |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
119 | if __name__ == '__main__': |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
120 | if len(sys.argv) != 3: |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
121 | print('Host and port parameters are missing. Abort.') |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
122 | sys.exit(1) |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
123 | |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
124 | host, port = sys.argv[1:] |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
125 | backgroundClient = BackgroundClient(host, int(port)) |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
126 | # set the system exception handling function to ensure, that |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
127 | # we report on all unhandled exceptions |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
128 | sys.excepthook = backgroundClient._BackgroundClient__unhandled_exception |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
129 | # Start the main loop |
02cb2adb4868
First implementation for the BackgroundService.
T.Rzepka <Tobias.Rzepka@gmail.com>
parents:
diff
changeset
|
130 | backgroundClient.run() |