| Conditions | 46 | 
| Total Lines | 270 | 
| Code Lines | 191 | 
| 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 main_client.runClient() 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 | #  | 
            ||
| 177 | def runClient(options):  | 
            ||
| 178 | |||
| 179 | # log initialization  | 
            ||
| 180 |     log.message("Starting Outer Space Client", ige.version.versionString) | 
            ||
| 181 |     log.debug("sys.path =", sys.path) | 
            ||
| 182 |     log.debug("os.name =", os.name) | 
            ||
| 183 |     log.debug("sys.platform =", sys.platform) | 
            ||
| 184 |     log.debug("os.getcwd() =", os.getcwd()) | 
            ||
| 185 |     log.debug("sys.frozen =", getattr(sys, "frozen", None)) | 
            ||
| 186 | |||
| 187 | # create required directories  | 
            ||
| 188 | if not os.path.exists(options.configDir):  | 
            ||
| 189 | os.makedirs(options.configDir)  | 
            ||
| 190 |     log.debug("options.configDir =", options.configDir) | 
            ||
| 191 | |||
| 192 | running = 1  | 
            ||
| 193 | first = True  | 
            ||
| 194 | #while running:  | 
            ||
| 195 | if not first:  | 
            ||
| 196 | reload(osci)  | 
            ||
| 
                                                                                                    
                        
                         | 
                |||
| 197 | # parse configuration  | 
            ||
| 198 | if first:  | 
            ||
| 199 | import osci.gdata as gdata  | 
            ||
| 200 | else:  | 
            ||
| 201 | reload(gdata)  | 
            ||
| 202 | |||
| 203 | gdata.config = Config(os.path.join(options.configDir, options.configFilename))  | 
            ||
| 204 | gdata.config.game.server = options.server  | 
            ||
| 205 | |||
| 206 | setDefaults(gdata, options)  | 
            ||
| 207 | |||
| 208 | language = gdata.config.client.language  | 
            ||
| 209 | import gettext  | 
            ||
| 210 |     log.debug('OSCI', 'Installing translation for:', language) | 
            ||
| 211 | if language == 'en':  | 
            ||
| 212 |         log.debug('OSCI', 'English is native - installing null translations') | 
            ||
| 213 | tran = gettext.NullTranslations()  | 
            ||
| 214 | else:  | 
            ||
| 215 | try:  | 
            ||
| 216 |             tran = gettext.translation('OSPACE', resources.get('translations'), languages = [language]) | 
            ||
| 217 | except IOError:  | 
            ||
| 218 |             log.warning('OSCI', 'Cannot find catalog for', language) | 
            ||
| 219 |             log.message('OSCI', 'Installing null translations') | 
            ||
| 220 | tran = gettext.NullTranslations()  | 
            ||
| 221 | |||
| 222 | tran.install(unicode = 1)  | 
            ||
| 223 | |||
| 224 | |||
| 225 | #initialize pygame and prepare screen  | 
            ||
| 226 | if (gdata.config.defaults.sound == "yes") or (gdata.config.defaults.music == "yes"):  | 
            ||
| 227 | pygame.mixer.pre_init(44100, -16, 2, 4096)  | 
            ||
| 228 | |||
| 229 | os.environ['SDL_VIDEO_ALLOW_SCREENSAVER'] = '1'  | 
            ||
| 230 | os.environ['SDL_DEBUG'] = '1'  | 
            ||
| 231 | pygame.init()  | 
            ||
| 232 | |||
| 233 | flags = pygame.SWSURFACE  | 
            ||
| 234 | |||
| 235 | DEFAULT_SCRN_SIZE = (800, 600)  | 
            ||
| 236 | gdata.scrnSize = DEFAULT_SCRN_SIZE  | 
            ||
| 237 | if gdata.config.display.resolution == "FULLSCREEN":  | 
            ||
| 238 | gdata.scrnSize = (0, 0)  | 
            ||
| 239 | flags |= pygame.FULLSCREEN  | 
            ||
| 240 | elif gdata.config.display.resolution is not None:  | 
            ||
| 241 |             width, height = gdata.config.display.resolution.split('x') | 
            ||
| 242 | gdata.scrnSize = (int(width), int(height))  | 
            ||
| 243 | |||
| 244 | if gdata.config.display.depth == None:  | 
            ||
| 245 | # guess best depth  | 
            ||
| 246 | bestdepth = pygame.display.mode_ok(gdata.scrnSize, flags)  | 
            ||
| 247 | else:  | 
            ||
| 248 | bestdepth = int(gdata.config.display.depth)  | 
            ||
| 249 | |||
| 250 | # initialize screen  | 
            ||
| 251 | try:  | 
            ||
| 252 | screen = pygame.display.set_mode(gdata.scrnSize, flags, bestdepth)  | 
            ||
| 253 | # gdata.scrnSize is used everywhere to setup windows  | 
            ||
| 254 | gdata.scrnSize = screen.get_size()  | 
            ||
| 255 | except pygame.error:  | 
            ||
| 256 | # for example if fullscreen is selected with resolution bigger than display  | 
            ||
| 257 | # TODO: as of now, fullscreen has automatic resolution  | 
            ||
| 258 | gdata.scrnSize = DEFAULT_SCRN_SIZE  | 
            ||
| 259 | screen = pygame.display.set_mode(gdata.scrnSize, flags, bestdepth)  | 
            ||
| 260 | gdata.screen = screen  | 
            ||
| 261 |     log.debug('OSCI', 'Driver:', pygame.display.get_driver()) | 
            ||
| 262 |     log.debug('OSCI', 'Using depth:', bestdepth) | 
            ||
| 263 |     log.debug('OSCI', 'Display info:', pygame.display.Info()) | 
            ||
| 264 | |||
| 265 | pygame.mouse.set_visible(1)  | 
            ||
| 266 | |||
| 267 |     pygame.display.set_caption(_('Outer Space %s') % ige.version.versionString) | 
            ||
| 268 | |||
| 269 | # set icon  | 
            ||
| 270 |     pygame.display.set_icon(pygame.image.load(resources.get('icon48.png')).convert_alpha()) | 
            ||
| 271 | |||
| 272 | # UI stuff  | 
            ||
| 273 | if first:  | 
            ||
| 274 | import pygameui as ui  | 
            ||
| 275 | else:  | 
            ||
| 276 | reload(ui)  | 
            ||
| 277 | |||
| 278 | setSkinTheme(gdata, ui)  | 
            ||
| 279 | |||
| 280 | app = ui.Application(update, theme = ui.SkinableTheme)  | 
            ||
| 281 | app.background = defineBackground()  | 
            ||
| 282 | app.draw(gdata.screen)  | 
            ||
| 283 | app.windowSurfaceFlags = pygame.SWSURFACE | pygame.SRCALPHA  | 
            ||
| 284 | gdata.app = app  | 
            ||
| 285 | |||
| 286 | pygame.event.clear()  | 
            ||
| 287 | |||
| 288 | # resources  | 
            ||
| 289 | import osci.res  | 
            ||
| 290 | |||
| 291 | osci.res.initialize()  | 
            ||
| 292 | |||
| 293 | # load resources  | 
            ||
| 294 | import osci.dialog  | 
            ||
| 295 | dlg = osci.dialog.ProgressDlg(gdata.app)  | 
            ||
| 296 | osci.res.loadResources(dlg)  | 
            ||
| 297 | dlg.hide()  | 
            ||
| 298 | osci.res.prepareUIIcons(ui.SkinableTheme.themeIcons)  | 
            ||
| 299 | |||
| 300 | |||
| 301 | while running:  | 
            ||
| 302 | if first:  | 
            ||
| 303 | import osci.client, osci.handler  | 
            ||
| 304 | from igeclient.IClient import IClientException  | 
            ||
| 305 | else:  | 
            ||
| 306 | reload(osci.client)  | 
            ||
| 307 | reload(osci.handler)  | 
            ||
| 308 | osci.client.initialize(gdata.config.game.server, osci.handler, options)  | 
            ||
| 309 | |||
| 310 | # create initial dialogs  | 
            ||
| 311 | if first:  | 
            ||
| 312 | import osci.dialog  | 
            ||
| 313 | else:  | 
            ||
| 314 | reload(osci.dialog)  | 
            ||
| 315 | gdata.savePassword = gdata.config.game.lastpasswordcrypted != None  | 
            ||
| 316 | |||
| 317 | if options.login and options.password:  | 
            ||
| 318 | gdata.config.game.lastlogin = options.login  | 
            ||
| 319 | gdata.config.game.lastpassword = options.password  | 
            ||
| 320 | gdata.config.game.lastpasswordcrypted = binascii.b2a_base64(options.password).strip()  | 
            ||
| 321 | gdata.config.game.autologin = 'yes'  | 
            ||
| 322 | gdata.savePassword = 'no'  | 
            ||
| 323 | |||
| 324 | loginDlg = osci.dialog.LoginDlg(gdata.app)  | 
            ||
| 325 | updateDlg = osci.dialog.UpdateDlg(gdata.app)  | 
            ||
| 326 | |||
| 327 | # event loop  | 
            ||
| 328 | update()  | 
            ||
| 329 | |||
| 330 | lastSave = time.clock()  | 
            ||
| 331 | # set counter to -1 to trigger Update dialog (see "if" below)  | 
            ||
| 332 | counter = -1  | 
            ||
| 333 | needsRefresh = False  | 
            ||
| 334 | session = 1  | 
            ||
| 335 | first = False  | 
            ||
| 336 | while running and session:  | 
            ||
| 337 | try:  | 
            ||
| 338 | counter += 1  | 
            ||
| 339 | if counter == 0:  | 
            ||
| 340 | # display initial dialog in the very first cycle  | 
            ||
| 341 | updateDlg.display(caller = loginDlg, options = options)  | 
            ||
| 342 | # process as many events as possible before updating  | 
            ||
| 343 | evt = pygame.event.wait()  | 
            ||
| 344 | evts = pygame.event.get()  | 
            ||
| 345 | evts.insert(0, evt)  | 
            ||
| 346 | |||
| 347 | forceKeepAlive = False  | 
            ||
| 348 | saveDB = False  | 
            ||
| 349 | |||
| 350 | for evt in evts:  | 
            ||
| 351 | if evt.type == pygame.QUIT:  | 
            ||
| 352 | running = 0  | 
            ||
| 353 | break  | 
            ||
| 354 | if evt.type == (ui.USEREVENT) and evt.action == "localExit":  | 
            ||
| 355 | session = False  | 
            ||
| 356 | break  | 
            ||
| 357 | if evt.type == pygame.ACTIVEEVENT:  | 
            ||
| 358 | if evt.gain == 1 and evt.state == 6:  | 
            ||
| 359 | # pygame desktop window focus event  | 
            ||
| 360 | needsRefresh = True  | 
            ||
| 361 | if evt.type == pygame.KEYUP and evt.key == pygame.K_F12:  | 
            ||
| 362 | if not pygame.key.get_mods() & pygame.KMOD_CTRL:  | 
            ||
| 363 | running = 0  | 
            ||
| 364 | break  | 
            ||
| 365 | if evt.type == pygame.KEYUP and evt.key == pygame.K_F9:  | 
            ||
| 366 | forceKeepAlive = True  | 
            ||
| 367 | evt = gdata.app.processEvent(evt)  | 
            ||
| 368 | |||
| 369 | if gdata.app.needsUpdate() or needsRefresh:  | 
            ||
| 370 | needsRefresh = False  | 
            ||
| 371 | update()  | 
            ||
| 372 | # keep alive connection  | 
            ||
| 373 | osci.client.keepAlive(forceKeepAlive)  | 
            ||
| 374 | |||
| 375 | # save DB every 4 hours in case of a computer crash  | 
            ||
| 376 | # using "counter" to limit calls to time.clock() to approximately every 10-15 minutes  | 
            ||
| 377 | if counter > 5000:  | 
            ||
| 378 | # set this to zero so we don't display Update dialog  | 
            ||
| 379 | counter = 0  | 
            ||
| 380 | if time.clock() - lastSave > 14400:  | 
            ||
| 381 | saveDB = True  | 
            ||
| 382 | if saveDB:  | 
            ||
| 383 | osci.client.saveDB()  | 
            ||
| 384 | lastSave = time.clock();  | 
            ||
| 385 | |||
| 386 | except IClientException, e:  | 
            ||
| 387 | osci.client.reinitialize()  | 
            ||
| 388 | gdata.app.setStatus(e.args[0])  | 
            ||
| 389 | loginDlg.display(message = e.args[0])  | 
            ||
| 390 | except Exception, e:  | 
            ||
| 391 |                 log.warning('OSCI', 'Exception in event loop') | 
            ||
| 392 | if not isinstance(e, SystemExit) and not isinstance(e, KeyboardInterrupt):  | 
            ||
| 393 |                     log.debug("Processing exception") | 
            ||
| 394 | # handle exception  | 
            ||
| 395 | import traceback, StringIO  | 
            ||
| 396 | fh = StringIO.StringIO()  | 
            ||
| 397 | exctype, value, tb = sys.exc_info()  | 
            ||
| 398 | funcs = [entry[2] for entry in traceback.extract_tb(tb)]  | 
            ||
| 399 | faultID = "%06d-%03d" % (  | 
            ||
| 400 |                         hash("/".join(funcs)) % 1000000, | 
            ||
| 401 | traceback.extract_tb(tb)[-1][1] % 1000,  | 
            ||
| 402 | )  | 
            ||
| 403 | del tb  | 
            ||
| 404 | # high level info  | 
            ||
| 405 | print >>fh, "Exception ID:", faultID  | 
            ||
| 406 | print >>fh  | 
            ||
| 407 | print >>fh, "%s: %s" % (exctype, value)  | 
            ||
| 408 | print >>fh  | 
            ||
| 409 | print >>fh, "--- EXCEPTION DATA ---"  | 
            ||
| 410 | # dump exception  | 
            ||
| 411 | traceback.print_exc(file = fh)  | 
            ||
| 412 | excDlg = osci.dialog.ExceptionDlg(gdata.app)  | 
            ||
| 413 | excDlg.display(faultID, fh.getvalue())  | 
            ||
| 414 | del excDlg # reference to the dialog holds app's intance  | 
            ||
| 415 | fh.close()  | 
            ||
| 416 | del fh  | 
            ||
| 417 | else:  | 
            ||
| 418 | break  | 
            ||
| 419 | |||
| 420 | # write configuration  | 
            ||
| 421 |         log.debug("Saving configuration.") | 
            ||
| 422 | # Save highlights  | 
            ||
| 423 | hl = ""  | 
            ||
| 424 | for playerID in gdata.playersHighlightColors.keys():  | 
            ||
| 425 | color = gdata.playersHighlightColors[playerID]  | 
            ||
| 426 | r = hex(color[0])  | 
            ||
| 427 | g = hex(color[1])  | 
            ||
| 428 | b = hex(color[2])  | 
            ||
| 429 | hl = "%s %s:%s,%s,%s" % (hl,playerID,r,g,b)  | 
            ||
| 430 | gdata.config.defaults.colors = hl  | 
            ||
| 431 | # Save objects  | 
            ||
| 432 | of = ""  | 
            ||
| 433 | for keyNum in gdata.objectFocus.keys():  | 
            ||
| 434 | objid = gdata.objectFocus[keyNum]  | 
            ||
| 435 | of = "%s %s:%s" % (of,keyNum,objid)  | 
            ||
| 436 | gdata.config.defaults.objectkeys = of  | 
            ||
| 437 | #  | 
            ||
| 438 | if gdata.savePassword == False:  | 
            ||
| 439 | gdata.config.game.lastpasswordcrypted = None  | 
            ||
| 440 | gdata.config.save()  | 
            ||
| 441 | |||
| 442 | # logout  | 
            ||
| 443 | osci.client.logout()  | 
            ||
| 444 | |||
| 445 |     log.debug("Shut down") | 
            ||
| 446 | return osci.client  | 
            ||
| 447 |