Conditions | 36 |
Total Lines | 123 |
Code Lines | 84 |
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.bgp.message.update.Update.messages() 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 | # encoding: utf-8 |
||
106 | def messages(self, negotiated, include_withdraw=True): |
||
107 | # sort the nlris |
||
108 | |||
109 | nlris = [] |
||
110 | mp_nlris = {} |
||
111 | |||
112 | for nlri in sorted(self.nlris): |
||
113 | if nlri.family() in negotiated.families: |
||
114 | if ( |
||
115 | nlri.afi == AFI.ipv4 |
||
116 | and nlri.safi in [SAFI.unicast, SAFI.multicast] |
||
117 | and nlri.nexthop.afi == AFI.ipv4 |
||
118 | ): |
||
119 | nlris.append(nlri) |
||
120 | else: |
||
121 | mp_nlris.setdefault(nlri.family(), {}).setdefault(nlri.action, []).append(nlri) |
||
122 | |||
123 | if not nlris and not mp_nlris: |
||
124 | return |
||
125 | |||
126 | # If all we have is MP_UNREACH_NLRI, we do not need the default |
||
127 | # attributes. See RFC4760 that states the following: |
||
128 | # |
||
129 | # An UPDATE message that contains the MP_UNREACH_NLRI is not required |
||
130 | # to carry any other path attributes. |
||
131 | # |
||
132 | include_defaults = True |
||
133 | |||
134 | if mp_nlris and not nlris: |
||
135 | for family, actions in mp_nlris.items(): |
||
136 | afi, safi = family |
||
137 | if safi not in (SAFI.unicast, SAFI.multicast): |
||
138 | break |
||
139 | if set(actions.keys()) != {OUT.WITHDRAW}: |
||
140 | break |
||
141 | # no break |
||
142 | else: |
||
143 | include_defaults = False |
||
144 | |||
145 | attr = self.attributes.pack(negotiated, include_defaults) |
||
146 | |||
147 | # Withdraws/NLRIS (IPv4 unicast and multicast) |
||
148 | msg_size = negotiated.msg_size - 19 - 2 - 2 - len(attr) # 2 bytes for each of the two prefix() header |
||
149 | |||
150 | if msg_size < 0: |
||
151 | # raise Notify(6,0,'attributes size is so large we can not even pack one NLRI') |
||
152 | log.critical('attributes size is so large we can not even pack one NLRI', 'parser') |
||
153 | return |
||
154 | |||
155 | if msg_size == 0 and (nlris or mp_nlris): |
||
156 | # raise Notify(6,0,'attributes size is so large we can not even pack one NLRI') |
||
157 | log.critical('attributes size is so large we can not even pack one NLRI', 'parser') |
||
158 | return |
||
159 | |||
160 | withdraws = b'' |
||
161 | announced = b'' |
||
162 | for nlri in nlris: |
||
163 | packed = nlri.pack(negotiated) |
||
164 | if len(announced + withdraws + packed) <= msg_size: |
||
165 | if nlri.action == OUT.ANNOUNCE: |
||
166 | announced += packed |
||
167 | elif include_withdraw: |
||
168 | withdraws += packed |
||
169 | continue |
||
170 | |||
171 | if not withdraws and not announced: |
||
172 | # raise Notify(6,0,'attributes size is so large we can not even pack one NLRI') |
||
173 | log.critical('attributes size is so large we can not even pack one NLRI', 'parser') |
||
174 | return |
||
175 | |||
176 | if announced: |
||
177 | yield self._message(Update.prefix(withdraws) + Update.prefix(attr) + announced) |
||
178 | else: |
||
179 | yield self._message(Update.prefix(withdraws) + Update.prefix(b'') + announced) |
||
180 | |||
181 | if nlri.action == OUT.ANNOUNCE: |
||
182 | announced = packed |
||
183 | withdraws = b'' |
||
184 | elif include_withdraw: |
||
185 | withdraws = packed |
||
186 | announced = b'' |
||
187 | else: |
||
188 | withdraws = b'' |
||
189 | announced = b'' |
||
190 | |||
191 | if announced or withdraws: |
||
192 | if announced: |
||
193 | yield self._message(Update.prefix(withdraws) + Update.prefix(attr) + announced) |
||
194 | else: |
||
195 | yield self._message(Update.prefix(withdraws) + Update.prefix(b'') + announced) |
||
196 | |||
197 | for family in mp_nlris.keys(): |
||
198 | afi, safi = family |
||
199 | mp_reach = b'' |
||
200 | mp_unreach = b'' |
||
201 | mp_announce = MPRNLRI(afi, safi, mp_nlris[family].get(OUT.ANNOUNCE, [])) |
||
202 | mp_withdraw = MPURNLRI(afi, safi, mp_nlris[family].get(OUT.WITHDRAW, [])) |
||
203 | |||
204 | for mprnlri in mp_announce.packed_attributes(negotiated, msg_size - len(withdraws + announced)): |
||
205 | if mp_reach: |
||
206 | yield self._message(Update.prefix(withdraws) + Update.prefix(attr + mp_reach) + announced) |
||
207 | announced = b'' |
||
208 | withdraws = b'' |
||
209 | mp_reach = mprnlri |
||
210 | |||
211 | if include_withdraw: |
||
212 | for mpurnlri in mp_withdraw.packed_attributes( |
||
213 | negotiated, msg_size - len(withdraws + announced + mp_reach) |
||
214 | ): |
||
215 | if mp_unreach: |
||
216 | yield self._message( |
||
217 | Update.prefix(withdraws) + Update.prefix(attr + mp_unreach + mp_reach) + announced |
||
218 | ) |
||
219 | mp_reach = b'' |
||
220 | announced = b'' |
||
221 | withdraws = b'' |
||
222 | mp_unreach = mpurnlri |
||
223 | |||
224 | yield self._message( |
||
225 | Update.prefix(withdraws) + Update.prefix(attr + mp_unreach + mp_reach) + announced |
||
226 | ) # yield mpr/mpur per family |
||
227 | withdraws = b'' |
||
228 | announced = b'' |
||
229 | |||
308 |