Conditions | 21 |
Total Lines | 115 |
Code Lines | 81 |
Lines | 0 |
Ratio | 0 % |
Changes | 0 |
Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.
For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.
Commonly applied refactorings include:
If many parameters/temporary variables are present:
Complex classes like exabgp.reactor.api.transcoder.Transcoder._from_json() often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
1 | from __future__ import print_function |
||
61 | def _from_json(self, json_string): |
||
62 | try: |
||
63 | parsed = json.loads(json_string) |
||
64 | except ValueError: |
||
65 | print('invalid JSON message', file=sys.stderr) |
||
66 | sys.exit(1) |
||
67 | |||
68 | if parsed.get('exabgp', '0.0.0') != json_version: |
||
69 | print('invalid json version', json_string, file=sys.stderr) |
||
70 | sys.exit(1) |
||
71 | |||
72 | content = parsed.get('type', '') |
||
73 | |||
74 | if not content: |
||
75 | print('invalid json content', json_string, file=sys.stderr) |
||
76 | sys.exit(1) |
||
77 | |||
78 | neighbor = _FakeNeighbor( |
||
79 | parsed['neighbor']['address']['local'], |
||
80 | parsed['neighbor']['address']['peer'], |
||
81 | parsed['neighbor']['asn']['local'], |
||
82 | parsed['neighbor']['asn']['peer'], |
||
83 | ) |
||
84 | |||
85 | if content == 'state': |
||
86 | self._state() |
||
87 | return json_string |
||
88 | |||
89 | direction = parsed['neighbor']['direction'] |
||
90 | category = parsed['neighbor']['message']['category'] |
||
91 | header = parsed['neighbor']['message']['header'] |
||
92 | body = parsed['neighbor']['message']['body'] |
||
93 | data = b''.join(bytes([int(body[_ : _ + 2], 16)]) for _ in range(0, len(body), 2)) |
||
94 | |||
95 | if content == 'open': |
||
96 | message = Open.unpack_message(data) |
||
97 | self._open(direction, message) |
||
98 | return self.encoder.open(neighbor, direction, message, None, header, body) |
||
99 | |||
100 | if content == 'keepalive': |
||
101 | return self.encoder.keepalive(neighbor, direction, None, header, body) |
||
102 | |||
103 | if content == 'notification': |
||
104 | # XXX: Use the code of the Notifcation class here .. |
||
105 | message = Notification.unpack_message(data) |
||
106 | |||
107 | if (message.code, message.subcode) != (6, 2): |
||
108 | message.data = data if not len([_ for _ in data if _ not in string.printable]) else hexstring(data) |
||
109 | return self.encoder.notification(neighbor, direction, message, None, header, body) |
||
110 | |||
111 | if len(data) == 0: |
||
112 | # shutdown without shutdown communication (the old fashioned way) |
||
113 | message.data = '' |
||
114 | return self.encoder.notification(neighbor, direction, message, None, header, body) |
||
115 | |||
116 | # draft-ietf-idr-shutdown or the peer was using 6,2 with data |
||
117 | |||
118 | shutdown_length = data[0] |
||
119 | data = data[1:] |
||
120 | |||
121 | if shutdown_length == 0: |
||
122 | message.data = "empty Shutdown Communication." |
||
123 | # move offset past length field |
||
124 | return self.encoder.notification(neighbor, direction, message, None, header, body) |
||
125 | |||
126 | if len(data) < shutdown_length: |
||
127 | message.data = "invalid Shutdown Communication (buffer underrun) length : %i [%s]" % ( |
||
128 | shutdown_length, |
||
129 | hexstring(data), |
||
130 | ) |
||
131 | return self.encoder.notification(neighbor, direction, message, None, header, body) |
||
132 | |||
133 | if shutdown_length > 128: |
||
134 | message.data = "invalid Shutdown Communication (too large) length : %i [%s]" % ( |
||
135 | shutdown_length, |
||
136 | hexstring(data), |
||
137 | ) |
||
138 | return self.encoder.notification(neighbor, direction, message, None, header, body) |
||
139 | |||
140 | try: |
||
141 | message.data = 'Shutdown Communication: "%s"' % data[:shutdown_length].decode('utf-8').replace( |
||
142 | '\r', ' ' |
||
143 | ).replace('\n', ' ') |
||
144 | except UnicodeDecodeError: |
||
145 | message.data = "invalid Shutdown Communication (invalid UTF-8) length : %i [%s]" % ( |
||
146 | shutdown_length, |
||
147 | hexstring(data), |
||
148 | ) |
||
149 | return self.encoder.notification(neighbor, direction, message, None, header, body) |
||
150 | |||
151 | trailer = data[shutdown_length:] |
||
152 | if trailer: |
||
153 | message.data += ", trailing data: " + hexstring(trailer) |
||
154 | |||
155 | return self.encoder.notification(neighbor, direction, message, None, header, body) |
||
156 | |||
157 | if not self.negotiated: |
||
158 | print('invalid message sequence, open not exchange not complete', json_string, file=sys.stderr) |
||
159 | sys.exit(1) |
||
160 | |||
161 | message = Message.unpack(category, data, self.negotiated) |
||
162 | |||
163 | if content == 'update': |
||
164 | return self.encoder.update(neighbor, direction, message, None, header, body) |
||
165 | |||
166 | if content == 'eor': # XXX: Should not be required |
||
167 | return self.encoder.update(neighbor, direction, message, None, header, body) |
||
168 | |||
169 | if content == 'refresh': |
||
170 | return self.json.refresh(neighbor, direction, message, None, header, body) |
||
171 | |||
172 | if content == 'operational': |
||
173 | return self.json.refresh(neighbor, direction, message, None, header, body) |
||
174 | |||
175 | raise RuntimeError('the programer is a monkey and forgot a JSON message type') |
||
176 |