filtered-openstack-security.res 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438
  1. cloudbridge.test.test_security_service.CloudSecurityServiceTestCase
  2. Test output
  3. ..........
  4. ----------------------------------------------------------------------
  5. Ran 10 tests in 64.346s
  6. OK
  7. Wrote profile results to run_single.py.lprof
  8. Timer unit: 1e-06 s
  9. Total time: 13.7187 s
  10. Function: create at line 250
  11. Line # Hits Time Per Hit % Time Line Contents
  12. ==============================================================
  13. 250 @cb_helpers.deprecated_alias(network_id='network')
  14. 251 @dispatch(event="provider.security.vm_firewalls.create",
  15. 252 priority=BaseVMFirewallService.STANDARD_EVENT_PRIORITY)
  16. 253 @profile
  17. 254 def create(self, label, network, description=None):
  18. 255 16 214.0 13.4 0.0 OpenStackVMFirewall.assert_valid_resource_label(label)
  19. 256 6 12.0 2.0 0.0 net_id = network.id if isinstance(network, Network) else network
  20. 257 # We generally simulate a network being associated with a firewall
  21. 258 # by storing the supplied value in the firewall description field that
  22. 259 # is not modifiable after creation; however, because of some networking
  23. 260 # specificity in Nectar, we must also allow an empty network id value.
  24. 261 6 2.0 0.3 0.0 if not net_id:
  25. 262 net_id = ""
  26. 263 6 5.0 0.8 0.0 if not description:
  27. 264 description = ""
  28. 265 6 8.0 1.3 0.0 description += " [{}{}]".format(OpenStackVMFirewall._network_id_tag,
  29. 266 6 20.0 3.3 0.0 net_id)
  30. 267 6 8942449.0 1490408.2 65.2 sg = self.provider.os_conn.network.create_security_group(
  31. 268 6 4775806.0 795967.7 34.8 name=label, description=description)
  32. 269 6 16.0 2.7 0.0 if sg:
  33. 270 6 153.0 25.5 0.0 return OpenStackVMFirewall(self.provider, sg)
  34. 271 return None
  35. Total time: 12.5863 s
  36. Function: get_or_create_default at line 1155
  37. Line # Hits Time Per Hit % Time Line Contents
  38. ==============================================================
  39. 1155 @profile
  40. 1156 def get_or_create_default(self, zone):
  41. 1157 """
  42. 1158 Subnet zone is not supported by OpenStack and is thus ignored.
  43. 1159 """
  44. 1160 6 11.0 1.8 0.0 try:
  45. 1161 6 12586255.0 2097709.2 100.0 sn = self.find(label=OpenStackSubnet.CB_DEFAULT_SUBNET_LABEL)
  46. 1162 6 8.0 1.3 0.0 if sn:
  47. 1163 6 14.0 2.3 0.0 return sn[0]
  48. 1164 # No default subnet look for default network, then create subnet
  49. 1165 net = self.provider.networking.networks.get_or_create_default()
  50. 1166 sn = self.provider.networking.subnets.create(
  51. 1167 label=OpenStackSubnet.CB_DEFAULT_SUBNET_LABEL,
  52. 1168 cidr_block=OpenStackSubnet.CB_DEFAULT_SUBNET_IPV4RANGE,
  53. 1169 network=net, zone=zone)
  54. 1170 router = self.provider.networking.routers.get_or_create_default(
  55. 1171 net)
  56. 1172 router.attach_subnet(sn)
  57. 1173 gateway = net.gateways.get_or_create()
  58. 1174 router.attach_gateway(gateway)
  59. 1175 return sn
  60. 1176 except NeutronClientException:
  61. 1177 return None
  62. Total time: 12.5242 s
  63. Function: find at line 308
  64. Line # Hits Time Per Hit % Time Line Contents
  65. ==============================================================
  66. 308 @dispatch(event="provider.networking.subnets.find",
  67. 309 priority=BaseCloudService.STANDARD_EVENT_PRIORITY)
  68. 310 @profile
  69. 311 def find(self, network=None, **kwargs):
  70. 312 6 5.0 0.8 0.0 if not network:
  71. 313 6 3.0 0.5 0.0 obj_list = self
  72. 314 else:
  73. 315 obj_list = network.subnets
  74. 316 6 4.0 0.7 0.0 filters = ['label']
  75. 317 6 12523991.0 2087331.8 100.0 matches = cb_helpers.generic_find(filters, kwargs, obj_list)
  76. 318 6 192.0 32.0 0.0 return ClientPagedResultList(self._provider, list(matches))
  77. Total time: 12.466 s
  78. Function: list at line 1118
  79. Line # Hits Time Per Hit % Time Line Contents
  80. ==============================================================
  81. 1118 @dispatch(event="provider.networking.subnets.list",
  82. 1119 priority=BaseSubnetService.STANDARD_EVENT_PRIORITY)
  83. 1120 @profile
  84. 1121 def list(self, network=None, limit=None, marker=None):
  85. 1122 6 6.0 1.0 0.0 if network:
  86. 1123 network_id = (network.id if isinstance(network, OpenStackNetwork)
  87. 1124 else network)
  88. 1125 subnets = [subnet for subnet in self if network_id ==
  89. 1126 subnet.network_id]
  90. 1127 else:
  91. 1128 6 5.0 0.8 0.0 subnets = [OpenStackSubnet(self.provider, subnet) for subnet in
  92. 1129 6 12465724.0 2077620.7 100.0 self.provider.neutron.list_subnets().get('subnets', [])]
  93. 1130 6 23.0 3.8 0.0 return ClientPagedResultList(self.provider, subnets,
  94. 1131 6 274.0 45.7 0.0 limit=limit, marker=marker)
  95. Total time: 8.52707 s
  96. Function: create at line 190
  97. Line # Hits Time Per Hit % Time Line Contents
  98. ==============================================================
  99. 190 @dispatch(event="provider.security.key_pairs.create",
  100. 191 priority=BaseKeyPairService.STANDARD_EVENT_PRIORITY)
  101. 192 @profile
  102. 193 def create(self, name, public_key_material=None):
  103. 194 14 144.0 10.3 0.0 OpenStackKeyPair.assert_valid_resource_name(name)
  104. 195 4 6556322.0 1639080.5 76.9 existing_kp = self.find(name=name)
  105. 196 4 4.0 1.0 0.0 if existing_kp:
  106. 197 1 1.0 1.0 0.0 raise DuplicateResourceException(
  107. 198 1 5.0 5.0 0.0 'Keypair already exists with name {0}'.format(name))
  108. 199
  109. 200 3 3.0 1.0 0.0 private_key = None
  110. 201 3 3.0 1.0 0.0 if not public_key_material:
  111. 202 2 159987.0 79993.5 1.9 public_key_material, private_key = cb_helpers.generate_key_pair()
  112. 203
  113. 204 3 21.0 7.0 0.0 kp = self.provider.nova.keypairs.create(name,
  114. 205 3 1810523.0 603507.7 21.2 public_key=public_key_material)
  115. 206 3 53.0 17.7 0.0 cb_kp = OpenStackKeyPair(self.provider, kp)
  116. 207 3 9.0 3.0 0.0 cb_kp.material = private_key
  117. 208 3 0.0 0.0 0.0 return cb_kp
  118. Total time: 7.93536 s
  119. Function: find at line 172
  120. Line # Hits Time Per Hit % Time Line Contents
  121. ==============================================================
  122. 172 @dispatch(event="provider.security.key_pairs.find",
  123. 173 priority=BaseKeyPairService.STANDARD_EVENT_PRIORITY)
  124. 174 @profile
  125. 175 def find(self, **kwargs):
  126. 176 7 11.0 1.6 0.0 name = kwargs.pop('name', None)
  127. 177
  128. 178 # All kwargs should have been popped at this time.
  129. 179 7 9.0 1.3 0.0 if len(kwargs) > 0:
  130. 180 1 1.0 1.0 0.0 raise InvalidParamException(
  131. 181 1 0.0 0.0 0.0 "Unrecognised parameters for search: %s. Supported "
  132. 182 1 14.0 14.0 0.0 "attributes: %s" % (kwargs, 'name'))
  133. 183
  134. 184 6 7935006.0 1322501.0 100.0 keypairs = self.provider.nova.keypairs.findall(name=name)
  135. 185 6 18.0 3.0 0.0 results = [OpenStackKeyPair(self.provider, kp)
  136. 186 6 41.0 6.8 0.0 for kp in keypairs]
  137. 187 6 53.0 8.8 0.0 log.debug("Searching for %s in: %s", name, keypairs)
  138. 188 6 210.0 35.0 0.0 return ClientPagedResultList(self.provider, results)
  139. Total time: 4.68369 s
  140. Function: refresh at line 1172
  141. Line # Hits Time Per Hit % Time Line Contents
  142. ==============================================================
  143. 1172 @profile
  144. 1173 def refresh(self):
  145. 1174 13 174.0 13.4 0.0 self._vm_firewall = self._provider.os_conn.network.get_security_group(
  146. 1175 13 4683518.0 360270.6 100.0 self.id)
  147. Total time: 4.02541 s
  148. Function: create at line 299
  149. Line # Hits Time Per Hit % Time Line Contents
  150. ==============================================================
  151. 299 @dispatch(event="provider.security.vm_firewall_rules.create",
  152. 300 priority=BaseVMFirewallRuleService.STANDARD_EVENT_PRIORITY)
  153. 301 @profile
  154. 302 def create(self, firewall, direction, protocol=None, from_port=None,
  155. 303 to_port=None, cidr=None, src_dest_fw=None):
  156. 304 5 7.0 1.4 0.0 src_dest_fw_id = (src_dest_fw.id if isinstance(src_dest_fw,
  157. 305 5 22.0 4.4 0.0 OpenStackVMFirewall)
  158. 306 4 2.0 0.5 0.0 else src_dest_fw)
  159. 307
  160. 308 5 4.0 0.8 0.0 try:
  161. 309 5 9.0 1.8 0.0 if direction == TrafficDirection.INBOUND:
  162. 310 5 4.0 0.8 0.0 os_direction = 'ingress'
  163. 311 elif direction == TrafficDirection.OUTBOUND:
  164. 312 os_direction = 'egress'
  165. 313 else:
  166. 314 raise InvalidValueException("direction", direction)
  167. 315 # pylint:disable=protected-access
  168. 316 5 47.0 9.4 0.0 rule = self.provider.os_conn.network.create_security_group_rule(
  169. 317 5 53.0 10.6 0.0 security_group_id=firewall.id,
  170. 318 5 5.0 1.0 0.0 direction=os_direction,
  171. 319 5 4.0 0.8 0.0 port_range_max=to_port,
  172. 320 5 3.0 0.6 0.0 port_range_min=from_port,
  173. 321 5 5.0 1.0 0.0 protocol=protocol,
  174. 322 5 5.0 1.0 0.0 remote_ip_prefix=cidr,
  175. 323 5 1943972.0 388794.4 48.3 remote_group_id=src_dest_fw_id)
  176. 324 4 1391281.0 347820.2 34.6 firewall.refresh()
  177. 325 4 304324.0 76081.0 7.6 return OpenStackVMFirewallRule(firewall, rule.to_dict())
  178. 326 1 3.0 3.0 0.0 except HttpException as e:
  179. 327 1 366160.0 366160.0 9.1 firewall.refresh()
  180. 328 # 409=Conflict, raised for duplicate rule
  181. 329 1 3.0 3.0 0.0 if e.status_code == 409:
  182. 330 1 2.0 2.0 0.0 existing = self.find(firewall, direction=direction,
  183. 331 1 0.0 0.0 0.0 protocol=protocol, from_port=from_port,
  184. 332 1 1.0 1.0 0.0 to_port=to_port, cidr=cidr,
  185. 333 1 19471.0 19471.0 0.5 src_dest_fw_id=src_dest_fw_id)
  186. 334 1 24.0 24.0 0.0 return existing[0]
  187. 335 else:
  188. 336 raise e
  189. Total time: 3.07443 s
  190. Function: delete at line 338
  191. Line # Hits Time Per Hit % Time Line Contents
  192. ==============================================================
  193. 338 @dispatch(event="provider.security.vm_firewall_rules.delete",
  194. 339 priority=BaseVMFirewallRuleService.STANDARD_EVENT_PRIORITY)
  195. 340 @profile
  196. 341 def delete(self, firewall, rule):
  197. 342 4 33.0 8.2 0.0 rule_id = (rule.id if isinstance(rule, OpenStackVMFirewallRule)
  198. 343 else rule)
  199. 344 4 1656371.0 414092.8 53.9 self.provider.os_conn.network.delete_security_group_rule(rule_id)
  200. 345 4 1418026.0 354506.5 46.1 firewall.refresh()
  201. Total time: 2.89585 s
  202. Function: list at line 154
  203. Line # Hits Time Per Hit % Time Line Contents
  204. ==============================================================
  205. 154 @dispatch(event="provider.security.key_pairs.list",
  206. 155 priority=BaseKeyPairService.STANDARD_EVENT_PRIORITY)
  207. 156 @profile
  208. 157 def list(self, limit=None, marker=None):
  209. 158 """
  210. 159 List all key pairs associated with this account.
  211. 160
  212. 161 :rtype: ``list`` of :class:`.KeyPair`
  213. 162 :return: list of KeyPair objects
  214. 163 """
  215. 164 4 2895613.0 723903.2 100.0 keypairs = self.provider.nova.keypairs.list()
  216. 165 4 13.0 3.2 0.0 results = [OpenStackKeyPair(self.provider, kp)
  217. 166 4 51.0 12.8 0.0 for kp in keypairs]
  218. 167 4 7.0 1.8 0.0 log.debug("Listing all key pairs associated with OpenStack "
  219. 168 4 32.0 8.0 0.0 "Account: %s", results)
  220. 169 4 9.0 2.2 0.0 return ClientPagedResultList(self.provider, results,
  221. 170 4 127.0 31.8 0.0 limit=limit, marker=marker)
  222. Total time: 2.59937 s
  223. Function: get at line 226
  224. Line # Hits Time Per Hit % Time Line Contents
  225. ==============================================================
  226. 226 @dispatch(event="provider.security.vm_firewalls.get",
  227. 227 priority=BaseVMFirewallService.STANDARD_EVENT_PRIORITY)
  228. 228 @profile
  229. 229 def get(self, vm_firewall_id):
  230. 230 7 8.0 1.1 0.0 try:
  231. 231 7 7.0 1.0 0.0 return OpenStackVMFirewall(
  232. 232 7 13.0 1.9 0.0 self.provider,
  233. 233 7 61.0 8.7 0.0 self.provider.os_conn.network
  234. 234 7 2599251.0 371321.6 100.0 .get_security_group(vm_firewall_id))
  235. 235 1 4.0 4.0 0.0 except (ResourceNotFound, NotFoundException):
  236. 236 1 9.0 9.0 0.0 log.debug("Firewall %s not found.", vm_firewall_id)
  237. 237 1 20.0 20.0 0.0 return None
  238. Total time: 2.56676 s
  239. Function: list at line 239
  240. Line # Hits Time Per Hit % Time Line Contents
  241. ==============================================================
  242. 239 @dispatch(event="provider.security.vm_firewalls.list",
  243. 240 priority=BaseVMFirewallService.STANDARD_EVENT_PRIORITY)
  244. 241 @profile
  245. 242 def list(self, limit=None, marker=None):
  246. 243 firewalls = [
  247. 244 7 12.0 1.7 0.0 OpenStackVMFirewall(self.provider, fw)
  248. 245 7 2566492.0 366641.7 100.0 for fw in self.provider.os_conn.network.security_groups()]
  249. 246
  250. 247 7 23.0 3.3 0.0 return ClientPagedResultList(self.provider, firewalls,
  251. 248 7 236.0 33.7 0.0 limit=limit, marker=marker)
  252. Total time: 2.56556 s
  253. Function: get at line 139
  254. Line # Hits Time Per Hit % Time Line Contents
  255. ==============================================================
  256. 139 @dispatch(event="provider.security.key_pairs.get",
  257. 140 priority=BaseKeyPairService.STANDARD_EVENT_PRIORITY)
  258. 141 @profile
  259. 142 def get(self, key_pair_id):
  260. 143 """
  261. 144 Returns a KeyPair given its id.
  262. 145 """
  263. 146 4 33.0 8.2 0.0 log.debug("Returning KeyPair with the id %s", key_pair_id)
  264. 147 4 2.0 0.5 0.0 try:
  265. 148 4 3.0 0.8 0.0 return OpenStackKeyPair(
  266. 149 4 2565479.0 641369.8 100.0 self.provider, self.provider.nova.keypairs.get(key_pair_id))
  267. 150 1 4.0 4.0 0.0 except NovaNotFound:
  268. 151 1 9.0 9.0 0.0 log.debug("KeyPair %s was not found.", key_pair_id)
  269. 152 1 32.0 32.0 0.0 return None
  270. Total time: 2.45924 s
  271. Function: delete at line 273
  272. Line # Hits Time Per Hit % Time Line Contents
  273. ==============================================================
  274. 273 @dispatch(event="provider.security.vm_firewalls.delete",
  275. 274 priority=BaseVMFirewallService.STANDARD_EVENT_PRIORITY)
  276. 275 @profile
  277. 276 def delete(self, vm_firewall):
  278. 277 6 10.0 1.7 0.0 fw = (vm_firewall if isinstance(vm_firewall, OpenStackVMFirewall)
  279. 278 else self.get(vm_firewall))
  280. 279 6 5.0 0.8 0.0 if fw:
  281. 280 # pylint:disable=protected-access
  282. 281 6 2459225.0 409870.8 100.0 fw._vm_firewall.delete(self.provider.os_conn.session)
  283. Total time: 2.39136 s
  284. Function: get at line 1035
  285. Line # Hits Time Per Hit % Time Line Contents
  286. ==============================================================
  287. 1035 @dispatch(event="provider.networking.networks.get",
  288. 1036 priority=BaseNetworkService.STANDARD_EVENT_PRIORITY)
  289. 1037 @profile
  290. 1038 def get(self, network_id):
  291. 1039 6 16.0 2.7 0.0 network = (n for n in self if n.id == network_id)
  292. 1040 6 2391344.0 398557.3 100.0 return next(network, None)
  293. Total time: 2.3219 s
  294. Function: label at line 1159
  295. Line # Hits Time Per Hit % Time Line Contents
  296. ==============================================================
  297. 1159 @label.setter
  298. 1160 # pylint:disable=arguments-differ
  299. 1161 @profile
  300. 1162 def label(self, value):
  301. 1163 11 202.0 18.4 0.0 self.assert_valid_resource_label(value)
  302. 1164 3 33.0 11.0 0.0 self._provider.os_conn.network.update_security_group(
  303. 1165 3 1108031.0 369343.7 47.7 self.id, name=value or "")
  304. 1166 3 1213633.0 404544.3 52.3 self.refresh()
  305. Total time: 2.31848 s
  306. Function: list at line 1042
  307. Line # Hits Time Per Hit % Time Line Contents
  308. ==============================================================
  309. 1042 @dispatch(event="provider.networking.networks.list",
  310. 1043 priority=BaseNetworkService.STANDARD_EVENT_PRIORITY)
  311. 1044 @profile
  312. 1045 def list(self, limit=None, marker=None):
  313. 1046 6 8.0 1.3 0.0 networks = [OpenStackNetwork(self.provider, network)
  314. 1047 6 2317780.0 386296.7 100.0 for network in self.provider.neutron.list_networks()
  315. 1048 6 433.0 72.2 0.0 .get('networks') if network]
  316. 1049 6 12.0 2.0 0.0 return ClientPagedResultList(self.provider, networks,
  317. 1050 6 243.0 40.5 0.0 limit=limit, marker=marker)
  318. Total time: 2.28191 s
  319. Function: delete at line 210
  320. Line # Hits Time Per Hit % Time Line Contents
  321. ==============================================================
  322. 210 @dispatch(event="provider.security.key_pairs.delete",
  323. 211 priority=BaseKeyPairService.STANDARD_EVENT_PRIORITY)
  324. 212 @profile
  325. 213 def delete(self, key_pair):
  326. 214 3 5.0 1.7 0.0 keypair = (key_pair if isinstance(key_pair, OpenStackKeyPair)
  327. 215 1 517605.0 517605.0 22.7 else self.get(key_pair))
  328. 216 3 4.0 1.3 0.0 if keypair:
  329. 217 # pylint:disable=protected-access
  330. 218 3 1764294.0 588098.0 77.3 keypair._key_pair.delete()
  331. Total time: 0.725505 s
  332. Function: find at line 81
  333. Line # Hits Time Per Hit % Time Line Contents
  334. ==============================================================
  335. 81 @dispatch(event="provider.security.vm_firewalls.find",
  336. 82 priority=BaseCloudService.STANDARD_EVENT_PRIORITY)
  337. 83 @profile
  338. 84 def find(self, **kwargs):
  339. 85 3 3.0 1.0 0.0 obj_list = self
  340. 86 3 3.0 1.0 0.0 filters = ['label']
  341. 87 3 725442.0 241814.0 100.0 matches = cb_helpers.generic_find(filters, kwargs, obj_list)
  342. 88
  343. 89 # All kwargs should have been popped at this time.
  344. 90 2 3.0 1.5 0.0 if len(kwargs) > 0:
  345. 91 raise InvalidParamException(
  346. 92 "Unrecognised parameters for search: %s. Supported "
  347. 93 "attributes: %s" % (kwargs, ", ".join(filters)))
  348. 94
  349. 95 2 3.0 1.5 0.0 return ClientPagedResultList(self.provider,
  350. 96 2 51.0 25.5 0.0 matches if matches else [])
  351. Total time: 0.407367 s
  352. Function: list at line 289
  353. Line # Hits Time Per Hit % Time Line Contents
  354. ==============================================================
  355. 289 @dispatch(event="provider.security.vm_firewall_rules.list",
  356. 290 priority=BaseVMFirewallRuleService.STANDARD_EVENT_PRIORITY)
  357. 291 @profile
  358. 292 def list(self, firewall, limit=None, marker=None):
  359. 293 # pylint:disable=protected-access
  360. 294 16 28.0 1.8 0.0 rules = [OpenStackVMFirewallRule(firewall, r)
  361. 295 16 406870.0 25429.4 99.9 for r in firewall._vm_firewall.security_group_rules]
  362. 296 16 35.0 2.2 0.0 return ClientPagedResultList(self.provider, rules,
  363. 297 16 434.0 27.1 0.1 limit=limit, marker=marker)
  364. Total time: 0.012727 s
  365. Function: find at line 121
  366. Line # Hits Time Per Hit % Time Line Contents
  367. ==============================================================
  368. 121 @dispatch(event="provider.security.vm_firewall_rules.find",
  369. 122 priority=BaseCloudService.STANDARD_EVENT_PRIORITY)
  370. 123 @profile
  371. 124 def find(self, firewall, **kwargs):
  372. 125 4 11.0 2.8 0.1 obj_list = firewall.rules
  373. 126 4 4.0 1.0 0.0 filters = ['name', 'direction', 'protocol', 'from_port', 'to_port',
  374. 127 4 4.0 1.0 0.0 'cidr', 'src_dest_fw', 'src_dest_fw_id']
  375. 128 4 12632.0 3158.0 99.3 matches = cb_helpers.generic_find(filters, kwargs, obj_list)
  376. 129 3 76.0 25.3 0.6 return ClientPagedResultList(self._provider, list(matches))
  377. Total time: 0.00037 s
  378. Function: get at line 111
  379. Line # Hits Time Per Hit % Time Line Contents
  380. ==============================================================
  381. 111 @dispatch(event="provider.security.vm_firewall_rules.get",
  382. 112 priority=BaseCloudService.STANDARD_EVENT_PRIORITY)
  383. 113 @profile
  384. 114 def get(self, firewall, rule_id):
  385. 115 2 366.0 183.0 98.9 matches = [rule for rule in firewall.rules if rule.id == rule_id]
  386. 116 2 2.0 1.0 0.5 if matches:
  387. 117 1 1.0 1.0 0.3 return matches[0]
  388. 118 else:
  389. 119 1 1.0 1.0 0.3 return None