More coverage exclusions.
[super-star-trek.git] / sst
diff --git a/sst b/sst
index 6bb244fb66b2b4c686931b20d2b61a178096a499..3b23fac6a16b76b3cb50a080d31aa8398522c0a1 100755 (executable)
--- a/sst
+++ b/sst
@@ -18,7 +18,7 @@ on how to modify (and how not to modify!) this code.
 
 # pylint: disable=multiple-imports
 import os, sys, math, curses, time, pickle, copy, gettext, getpass
-import getopt, socket, locale, getpass
+import getopt, socket
 import codecs
 
 # This import only works on Unixes.  The intention is to enable
@@ -26,7 +26,7 @@ import codecs
 try:
     # pylint: disable=unused-import
     import readline
-except ImportError:
+except ImportError:  # pragma: no cover
     pass
 
 version = "2.7"
@@ -101,7 +101,7 @@ FOREVER     = 1e30          # Time for the indefinite future
 MAXBURST       = 3             # Max # of torps you can launch in one turn
 MINCMDR        = 10            # Minimum number of Klingon commanders
 DOCKFAC                = 0.25          # Repair faster when docked
-PHASEFAC       = 2.0           # Unclear what this is, it was in the C version
+PHASEFAC       = 2.0           # Phaser attenuation factor
 
 ALGERON                = 2311          # Date of the Treaty of Algeron
 
@@ -155,17 +155,17 @@ class Coord:
         return Coord(self.i*other, self.j*other)
     def __rmul__(self, other):
         return Coord(self.i*other, self.j*other)
-    def __div__(self, other):
+    def __div__(self, other):  # pragma: no cover
         return Coord(self.i/other, self.j/other)
-    def __truediv__(self, other):
+    def __truediv__(self, other):  # pragma: no cover
         return Coord(self.i/other, self.j/other)
-    def __floordiv__(self, other):
+    def __floordiv__(self, other):  # pragma: no cover
         return Coord(self.i//other, self.j//other)
     def __mod__(self, other):
         return Coord(self.i % other, self.j % other)
-    def __rtruediv__(self, other):
+    def __rtruediv__(self, other):  # pragma: no cover
         return Coord(self.i/other, self.j/other)
-    def __rfloordiv__(self, other):
+    def __rfloordiv__(self, other):  # pragma: no cover
         return Coord(self.i//other, self.j//other)
     def roundtogrid(self):
         return Coord(int(round(self.i)), int(round(self.j)))
@@ -195,14 +195,9 @@ class Coord:
         return self.roundtogrid() // QUADSIZE
     def sector(self):
         return self.roundtogrid() % QUADSIZE
-    def scatter(self):
-        s = Coord()
-        s.i = self.i + rnd.integer(-1, 2)
-        s.j = self.j + rnd.integer(-1, 2)
-        return s
     def __str__(self):
         if self.i is None or self.j is None:
-            return "Nowhere"
+            return "Nowhere"  # pragma: no cover
         if (game.options & OPTION_ALPHAMERIC):
             return letterize(self.i + 1) + str(self.j + 1)
         return "%s - %s" % (self.i+1, self.j+1)
@@ -240,7 +235,7 @@ class Quadrant:
         self.charted = False
         self.status = "secure"        # Could be "secure", "distressed", "enslaved"
     def __str__(self):
-        return "<Quadrant: %(klingons)d>" % self.__dict__
+        return "<Quadrant: %(klingons)d>" % self.__dict__  # pragma: no cover
     __repr__ = __str__
 
 class Page:
@@ -249,7 +244,7 @@ class Page:
         self.starbase = False
         self.klingons = None
     def __repr__(self):
-        return "<%s,%s,%s>" % (self.klingons, self.starbase, self.stars)
+        return "<%s,%s,%s>" % (self.klingons, self.starbase, self.stars)  # pragma: no cover
 
 def fill2d(size, fillfun):
     "Fill an empty list in 2D."
@@ -388,7 +383,7 @@ NEVENTS = 12
 
 # Abstract out the event handling -- underlying data structures will change
 # when we implement stateful events
-def findevent(evtype):
+def findevent(evtype):  # pragma: no cover
     return game.future[evtype]
 
 class Enemy:
@@ -421,7 +416,7 @@ class Enemy:
                 game.enemies.remove(self)
         return motion
     def __repr__(self):
-        return "<%s,%s.%f>" % (self.type, self.location, self.power)        # For debugging
+        return "<%s,%s,%f>" % (self.type, self.location, self.power)  # pragma: no cover
 
 class Gamestate:
     def __init__(self):
@@ -773,7 +768,7 @@ def movebaddy(enemy):
 def moveklings():
     "Sequence Klingon tactical movement."
     if game.idebug:
-        prout("== MOVCOM")
+        prout("== MOVCOM")        # pragma: no cover
     # Figure out which Klingon is the commander (or Supercommander)
     # and do move
     tacmoves = []
@@ -973,7 +968,7 @@ def movetholian():
     elif game.tholian.location.i == QUADSIZE-1 and game.tholian.location.j == 0:
         tid.i = 0
         tid.j = 0
-    else:
+    else:  # pragma: no cover
         # something is wrong!
         game.tholian.move(None)
         prout("***Internal error: Tholian in a bad spot.")
@@ -1226,10 +1221,10 @@ def randdevice():
         wsum += w
         if idx < wsum:
             return i
-    return None        # we should never get here
+    return None                # pragma: no cover
 
 def collision(rammed, enemy):
-    "Collision handling for rammong events."
+    "Collision handling for ramming events."
     prouts(_("***RED ALERT!  RED ALERT!"))
     skip(1)
     prout(_("***COLLISION IMMINENT."))
@@ -1246,12 +1241,12 @@ def collision(rammed, enemy):
         proutn(_(" (original position)"))
     skip(1)
     deadkl(enemy.location, enemy.type, game.sector)
-    proutn("***" + crmshp() + " heavily damaged.")
+    prout("***" + crmshp() + " heavily damaged.")
     icas = rnd.integer(10, 30)
     prout(_("***Sickbay reports %d casualties") % icas)
     game.casual += icas
     game.state.crew -= icas
-    # In the pre-SST2K version, all devices got equiprobably damaged,
+    # In the pre-SST2K versions, all devices got equiprobably damaged,
     # which was silly.  Instead, pick up to half the devices at
     # random according to our weighting table,
     ncrits = rnd.integer(NDEVICES//2)
@@ -1370,7 +1365,7 @@ def torpedo(origin, bearing, dispersion, number, nburst):
                             tenemy.kdist = tenemy.kavgd = (game.sector-tenemy.location).distance()
                         sortenemies()
                     break
-            else:
+            else:                # pragma: no cover
                 prout("Internal error, no enemy where expected!")
                 raise SystemExit(1)
             return None
@@ -1521,7 +1516,7 @@ def attack(torps_ok):
     chgfac = 1.0
     where = "neither"
     if game.idebug:
-        prout("=== ATTACK!")
+        prout("=== ATTACK!")                # pragma: no cover
     # Tholian gets to move before attacking
     if game.tholian:
         movetholian()
@@ -2375,7 +2370,7 @@ def events():
             game.isatb = 0
         else:
             game.battle.invalidate()
-    if game.idebug:
+    if game.idebug:                # pragma: no cover
         prout("=== EVENTS from %.2f to %.2f:" % (game.state.date, fintim))
         for i in range(1, NEVENTS):
             if   i == FSNOVA:  proutn("=== Supernova       ")
@@ -2405,7 +2400,7 @@ def events():
             if game.future[l].date < datemin:
                 evcode = l
                 if game.idebug:
-                    prout("== Event %d fires" % evcode)
+                    prout("== Event %d fires" % evcode)                # pragma: no cover
                 datemin = game.future[l].date
         xtime = datemin-game.state.date
         if game.iscloaked:
@@ -2607,7 +2602,7 @@ def events():
                     break
             else:
                 # can't seem to find one; ignore this call
-                if game.idebug:
+                if game.idebug:                # pragma: no cover
                     prout("=== Couldn't find location for distress event.")
                 continue
             # got one!!  Schedule its enslavement
@@ -2893,7 +2888,7 @@ def supernova(w):
                     break
             if num <=0:
                 break
-        if game.idebug:
+        if game.idebug:                # pragma: no cover
             proutn("=== Super nova here?")
             if ja():
                 nq = game.quadrant
@@ -3172,13 +3167,14 @@ def finish(ifin):
         prout(_("Your starship is now an expanding cloud of subatomic particles"))
     elif ifin == FMATERIALIZE:
         prout(_("Starbase was unable to re-materialize your starship."))
-        prout(_("Sic transit gloria mundi"))
+        prout(_("Sic transit gloria mundi."))
     elif ifin == FPHASER:
         prout(_("The %s has been cremated by its own phasers.") % crmshp())
     elif ifin == FLOST:
         prout(_("You and your landing party have been"))
         prout(_("converted to energy, dissipating through space."))
     elif ifin == FMINING:
+        # This does not seem to be reachable from any code path.
         prout(_("You are left with your landing party on"))
         prout(_("a wild jungle planet inhabited by primitive cannibals."))
         skip(1)
@@ -3191,6 +3187,7 @@ def finish(ifin):
         prout(_("That was a great shot."))
         skip(1)
     elif ifin == FSSC:
+        # This does not seem to be reachable from any code path.
         prout(_("The Galileo is instantly annihilated by the supernova."))
         prout(_("You and your mining party are atomized."))
         skip(1)
@@ -3410,11 +3407,6 @@ curwnd = None
 
 def iostart():
     global stdscr, rows
-    # for some recent versions of python2, the following enables UTF8
-    # for the older ones we probably need to set C locale, and python3
-    # has no problems at all
-    if sys.version_info[0] < 3:
-        locale.setlocale(locale.LC_ALL, "")
     gettext.bindtextdomain("sst", "/usr/local/share/locale")
     gettext.textdomain("sst")
     if not (game.options & OPTION_CURSES):
@@ -3423,7 +3415,7 @@ def iostart():
             rows = ln_env
         else:
             rows = 25
-    else:
+    else:      # pragma: no cover
         stdscr = curses.initscr()
         stdscr.keypad(True)
         curses.nonl()
@@ -3454,7 +3446,7 @@ def iostart():
 
 def ioend():
     "Wrap up I/O."
-    if game.options & OPTION_CURSES:
+    if game.options & OPTION_CURSES:   # pragma: no cover
         stdscr.keypad(False)
         curses.echo()
         curses.nocbreak()
@@ -3462,7 +3454,7 @@ def ioend():
 
 def waitfor():
     "Wait for user action -- OK to do nothing if on a TTY"
-    if game.options & OPTION_CURSES:
+    if game.options & OPTION_CURSES:   # pragma: no cover
         stdscr.getch()
 
 def announce():
@@ -3476,7 +3468,7 @@ def pause_game():
     else:
         prompt = _("[PRESS ENTER TO CONTINUE]")
 
-    if game.options & OPTION_CURSES:
+    if game.options & OPTION_CURSES:   # pragma: no cover
         drawmaps(0)
         setwnd(prompt_window)
         prompt_window.clear()
@@ -3497,7 +3489,7 @@ def pause_game():
 def skip(i):
     "Skip i lines.  Pause game if this would cause a scrolling event."
     for _dummy in range(i):
-        if game.options & OPTION_CURSES:
+        if game.options & OPTION_CURSES:       # pragma: no cover
             (y, _x) = curwnd.getyx()
             try:
                 curwnd.move(y+1, 0)
@@ -3513,7 +3505,7 @@ def skip(i):
 
 def proutn(proutntline):
     "Utter a line with no following line feed."
-    if game.options & OPTION_CURSES:
+    if game.options & OPTION_CURSES:   # pragma: no cover
         (y, x) = curwnd.getyx()
         (my, _mx) = curwnd.getmaxyx()
         if curwnd == message_window and y >= my - 2:
@@ -3537,7 +3529,7 @@ def prouts(proutsline):
         if not replayfp or replayfp.closed:        # Don't slow down replays
             time.sleep(0.03)
         proutn(c)
-        if game.options & OPTION_CURSES:
+        if game.options & OPTION_CURSES:       # pragma: no cover
             curwnd.refresh()
         else:
             sys.stdout.flush()
@@ -3546,7 +3538,7 @@ def prouts(proutsline):
 
 def cgetline():
     "Get a line of input."
-    if game.options & OPTION_CURSES:
+    if game.options & OPTION_CURSES:   # pragma: no cover
         linein = codecs.decode(curwnd.getstr()) + "\n"
         curwnd.refresh()
     else:
@@ -3554,7 +3546,7 @@ def cgetline():
             while True:
                 linein = replayfp.readline()
                 proutn(linein)
-                if linein == '':
+                if linein == '':    # pragma: no cover
                     prout("*** Replay finished")
                     replayfp.close()
                     break
@@ -3573,7 +3565,7 @@ def cgetline():
 def setwnd(wnd):
     "Change windows -- OK for this to be a no-op in tty mode."
     global curwnd
-    if game.options & OPTION_CURSES:
+    if game.options & OPTION_CURSES:   # pragma: no cover
         if game.cdebug and logfp:
             if wnd == fullscreen_window:
                 legend = "fullscreen"
@@ -3601,21 +3593,21 @@ def setwnd(wnd):
 
 def clreol():
     "Clear to end of line -- can be a no-op in tty mode"
-    if game.options & OPTION_CURSES:
+    if game.options & OPTION_CURSES:   # pragma: no cover
         curwnd.clrtoeol()
         curwnd.refresh()
 
 def clrscr():
     "Clear screen -- can be a no-op in tty mode."
     global linecount
-    if game.options & OPTION_CURSES:
+    if game.options & OPTION_CURSES:   # pragma: no cover
         curwnd.clear()
         curwnd.move(0, 0)
         curwnd.refresh()
     linecount = 0
 
 def textcolor(color=DEFAULT):
-    if (game.options & OPTION_COLOR) and (game.options & OPTION_CURSES):
+    if (game.options & OPTION_COLOR) and (game.options & OPTION_CURSES):       # pragma: no cover
         if color == DEFAULT:
             curwnd.attrset(0)
         elif color ==  BLACK:
@@ -3652,7 +3644,7 @@ def textcolor(color=DEFAULT):
             curwnd.attron(curses.color_pair(curses.COLOR_WHITE) | curses.A_BOLD)
 
 def highvideo():
-    if (game.options & OPTION_COLOR) and (game.options & OPTION_CURSES):
+    if (game.options & OPTION_COLOR) and (game.options & OPTION_CURSES):       # pragma: no cover
         curwnd.attron(curses.A_REVERSE)
 
 #
@@ -3661,7 +3653,7 @@ def highvideo():
 
 def drawmaps(mode):
     "Hook to be called after moving to redraw maps."
-    if game.options & OPTION_CURSES:
+    if game.options & OPTION_CURSES:   # pragma: no cover
         if mode == 1:
             sensor()
         setwnd(srscan_window)
@@ -3680,7 +3672,7 @@ def drawmaps(mode):
             lrscan_window.move(0, 0)
             lrscan(silent=False)
 
-def put_srscan_sym(w, sym):
+def put_srscan_sym(w, sym):    # pragma: no cover
     "Emit symbol for short-range scan."
     srscan_window.move(w.i+1, w.j*2+2)
     srscan_window.addch(sym)
@@ -3688,7 +3680,7 @@ def put_srscan_sym(w, sym):
 
 def boom(w):
     "Enemy fall down, go boom."
-    if game.options & OPTION_CURSES:
+    if game.options & OPTION_CURSES:   # pragma: no cover
         drawmaps(0)
         setwnd(srscan_window)
         srscan_window.attron(curses.A_REVERSE)
@@ -3703,12 +3695,12 @@ def boom(w):
 
 def warble():
     "Sound and visual effects for teleportation."
-    if game.options & OPTION_CURSES:
+    if game.options & OPTION_CURSES:   # pragma: no cover
         drawmaps(2)
         setwnd(message_window)
         #sound(50)
     prouts("     . . . . .     ")
-    if game.options & OPTION_CURSES:
+    if game.options & OPTION_CURSES:   # pragma: no cover
         #curses.delay_output(1000)
         #nosound()
         pass
@@ -3726,7 +3718,7 @@ def tracktorpedo(w, step, i, n, iquad):
         elif step in {4, 9}:
             skip(1)
         proutn("%s   " % w)
-    else:
+    else:      # pragma: no cover
         if not damaged(DSRSENS) or game.condition=="docked":
             if i != 0 and step == 1:
                 drawmaps(2)
@@ -3750,7 +3742,7 @@ def tracktorpedo(w, step, i, n, iquad):
 
 def makechart():
     "Display the current galaxy chart."
-    if game.options & OPTION_CURSES:
+    if game.options & OPTION_CURSES:   # pragma: no cover
         setwnd(message_window)
         message_window.clear()
     chart()
@@ -3761,14 +3753,14 @@ NSYM        = 14
 
 def prstat(txt, data):
     proutn(txt)
-    if game.options & OPTION_CURSES:
+    if game.options & OPTION_CURSES:   # pragma: no cover
         skip(1)
         setwnd(status_window)
     else:
         proutn(" " * (NSYM - len(txt)))
     proutn(data)
     skip(1)
-    if game.options & OPTION_CURSES:
+    if game.options & OPTION_CURSES:   # pragma: no cover
         setwnd(report_window)
 
 # Code from moving.c begins here
@@ -3841,11 +3833,11 @@ def imove(icourse=None, noattack=False):
             stopegy = 50.0*icourse.distance/game.optime
             if iquad in ('T', 'K', 'C', 'S', 'R', '?'):
                 for enemy in game.enemies:
-                    if enemy.location == game.sector:
+                    if enemy.location == h:
                         collision(rammed=False, enemy=enemy)
                         return True
                 # This should not happen
-                prout(_("Which way did he go?"))
+                prout(_("Which way did he go?")) # pragma: no cover
                 return False
             elif iquad == ' ':
                 skip(1)
@@ -4588,7 +4580,7 @@ def mayday():
             break
         prout(_("fails."))
         textcolor(DEFAULT)
-        if game.options & OPTION_CURSES:
+        if game.options & OPTION_CURSES:       # pragma: no cover
             curses.delay_output(500)
     if m > 3:
         game.quad[game.sector.i][game.sector.j]='?'
@@ -5304,8 +5296,8 @@ def damagereport():
     for i in range(NDEVICES):
         if damaged(i):
             if not jdam:
-                prout(_("\tDEVICE\t\t\t-REPAIR TIMES-"))
-                prout(_("\t\t\tIN FLIGHT\t\tDOCKED"))
+                prout(_("DEVICE                             REPAIR TIMES"))
+                prout(_("                                   IN FLIGHT                DOCKED"))
                 jdam = True
             prout("  %-26s\t%8.2f\t\t%8.2f" % (device[i],
                                                game.damage[i]+0.05,
@@ -5371,7 +5363,7 @@ def sectscan(goodScan, i, j):
     if goodScan or (abs(i-game.sector.i)<= 1 and abs(j-game.sector.j) <= 1):
         if game.quad[i][j] in ('E', 'F'):
             if game.iscloaked:
-                highvideo()
+                highvideo()    # pragma: no cover
             textcolor({"green":GREEN,
                        "yellow":YELLOW,
                        "red":RED,
@@ -5632,11 +5624,11 @@ def goptions():
             else:
                 prout(_("No such option as ") + scanner.token)
         if mode == "set":
-            if (not (game.options & OPTION_CURSES)) and (changemask & OPTION_CURSES):
+            if (not (game.options & OPTION_CURSES)) and (changemask & OPTION_CURSES):  # pragma: no cover
                 iostart()
             game.options |= changemask
         elif mode == "clear":
-            if (game.options & OPTION_CURSES) and (not (changemask & OPTION_CURSES)):
+            if (game.options & OPTION_CURSES) and (not (changemask & OPTION_CURSES)):  # pragma: no cover
                 ioend()
             game.options &=~ changemask
         prout(_("Acknowledged, Captain."))
@@ -6066,7 +6058,7 @@ def choose():
     elif len(scanner.token):
         proutn(_("What is \"%s\"?") % scanner.token)
     setpassword()
-    if game.passwd == "debug":
+    if game.passwd == "debug":                # pragma: no cover
         game.idebug = True
         prout("=== Debug mode enabled.")
     # Use parameters to generate initial values of things
@@ -6300,8 +6292,10 @@ commands = [
     ("",                 0),
 ]
 
-def listCommands():
+def listCommands():                # pragma: no cover
     "Generate a list of legal commands."
+    # Coverage-disabled because testing for this is fragile
+    # in the presence of changes in the command set.
     prout(_("LEGAL COMMANDS ARE:"))
     emitted = 0
     for (key, opt) in commands:
@@ -6383,7 +6377,7 @@ def makemoves():
             clrscr()
             proutn("COMMAND> ")
             if scanner.nexttok() == "IHEOL":
-                if game.options & OPTION_CURSES:
+                if game.options & OPTION_CURSES:       # pragma: no cover
                     makechart()
                 continue
             elif scanner.token == "":
@@ -6402,14 +6396,14 @@ def makemoves():
                 if cmd == scanner.token.upper() or (not abandon_passed \
                         and cmd.startswith(scanner.token.upper())):
                     break
-            if cmd == "":
+            if cmd == "":                # pragma: no cover
                 listCommands()
                 continue
             elif opt and not (opt & game.options):
                 huh()
             else:
                 break
-        if game.options & OPTION_CURSES:
+        if game.options & OPTION_CURSES:       # pragma: no cover
             prout("COMMAND> %s" % cmd)
         if cmd == "SRSCAN":                # srscan
             srscan()
@@ -6517,7 +6511,7 @@ def makemoves():
             helpme()                        # get help
         elif cmd == "SCORE":
             score()                         # see current score
-        elif cmd == "CURSES":
+        elif cmd == "CURSES":  # pragma: no cover
             game.options |= (OPTION_CURSES | OPTION_COLOR)
             iostart()
         elif cmd == "OPTIONS":
@@ -6560,7 +6554,7 @@ def cramen(ch):
     elif ch == '#': s = _("Tholian web")
     elif ch == '?': s = _("Stranger")
     elif ch == '@': s = _("Inhabited World")
-    else: s = "Unknown??"
+    else: s = "Unknown??"                # pragma: no cover
     return s
 
 def crmena(loud, enemy, loctype, w):
@@ -6671,7 +6665,7 @@ class sstscanner:
             return None
         s.j = self.int()-1
         return s
-    def __repr__(self):
+    def __repr__(self):                # pragma: no cover
         return "<sstcanner: token=%s, type=%s, queue=%s>" % (self.token, self.type, self.inqueue)
 
 def ja():
@@ -6692,7 +6686,7 @@ def huh():
     skip(1)
     prout(_("Beg your pardon, Captain?"))
 
-def debugme():
+def debugme():                # pragma: no cover
     "Access to the internals for debugging."
     proutn("Reset levels? ")
     if ja():
@@ -6789,7 +6783,7 @@ if __name__ == '__main__':
         logfp = None
         game.options = OPTION_ALL &~ (OPTION_IOMODES | OPTION_PLAIN | OPTION_ALMY)
         if os.getenv("TERM"):
-            game.options |= OPTION_CURSES
+            game.options |= OPTION_CURSES      # pragma: no cover
         else:
             game.options |= OPTION_TTY
         seed = int(time.time())
@@ -6810,34 +6804,34 @@ if __name__ == '__main__':
                     seed = eval(seed)
                     line = replayfp.readline().strip()
                     arguments += line.split()[2:]
-                except ValueError:
+                except ValueError:                # pragma: no cover
                     sys.stderr.write("sst: replay file %s is ill-formed\n"% val)
                     raise SystemExit(1)
                 game.options |= OPTION_TTY
                 game.options &=~ OPTION_CURSES
-            elif switch == '-s':
+            elif switch == '-s':                # pragma: no cover
                 seed = int(val)
-            elif switch == '-t':
+            elif switch == '-t':       # pragma: no cover
                 game.options |= OPTION_TTY
                 game.options &=~ OPTION_CURSES
-            elif switch == '-x':
+            elif switch == '-x':                # pragma: no cover
                 game.idebug = True
             elif switch == '-c':       # Enable curses debugging - undocumented
                 game.cdebug = True
-            elif switch == '-V':
+            elif switch == '-V':                # pragma: no cover
                 print("SST2K", version)
                 raise SystemExit(0)
-            else:
+            else:                # pragma: no cover
                 sys.stderr.write("usage: sst [-t] [-x] [startcommand...].\n")
                 raise SystemExit(1)
         # where to save the input in case of bugs
-        if "TMPDIR" in os.environ:
+        if "TMPDIR" in os.environ:                # pragma: no cover
             tmpdir = os.environ['TMPDIR']
         else:
             tmpdir = "/tmp"
         try:
             logfp = open(os.path.join(tmpdir, "sst-input.log"), "w")
-        except IOError:
+        except IOError:                # pragma: no cover
             sys.stderr.write("sst: warning, can't open logfile\n")
             sys.exit(1)
         if logfp:
@@ -6886,7 +6880,7 @@ if __name__ == '__main__':
         finally:
             ioend()
         raise SystemExit(0)
-    except KeyboardInterrupt:
+    except KeyboardInterrupt:                # pragma: no cover
         if logfp:
             logfp.close()
         print("")