def confirmRestart(self):
     return self.askYesNoQuestion(_("Restart required"),
                                  _("To finish the upgrade, a restart is "
                                    "required.\n"
                                    "If you select 'y' the system "
                                    "will be restarted."),
                                  default='No')
 def information(self, summary, msg, extended_msg=None):
   print
   print twrap(summary)
   print twrap(msg)
   if extended_msg:
     print twrap(extended_msg)
   print _("To continue please press [ENTER]")
   sys.stdin.readline()
 def confirmRestart(self):
     " generic ask about the restart, can be overridden "
     summary = _("Reboot required")
     msg =  _("The upgrade is finished and "
              "a reboot is required. "
              "Do you want to do this "
              "now?")
     return self.askYesNoQuestion(summary, msg)
 def confirmRestart(self):
     " generic ask about the restart, can be overridden "
     summary = _("Reboot required")
     msg =  _("The upgrade is finished and "
              "a reboot is required. "
              "Do you want to do this "
              "now?")
     return self.askYesNoQuestion(summary, msg)
 def information(self, summary, msg, extended_msg=None):
     print
     print twrap(summary)
     print twrap(msg)
     if extended_msg:
         print twrap(extended_msg)
     print _("To continue please press [ENTER]")
     sys.stdin.readline()
 def estimatedDownloadTime(self, requiredDownload):
   """ get the estimated download time """
   if self.est_speed == 0:
     timeModem = requiredDownload/(56*1024/8)  # 56 kbit 
     timeDSL = requiredDownload/(1024*1024/8)  # 1Mbit = 1024 kbit
     s= _("This download will take about %s with a 1Mbit DSL connection "
          "and about %s with a 56k modem.") % (FuzzyTimeToStr(timeDSL), FuzzyTimeToStr(timeModem))
     return s
   # if we have a estimated speed, use it
   s = _("This download will take about %s with your connection. ") % FuzzyTimeToStr(requiredDownload/self.est_speed)
   return s
 def estimatedDownloadTime(self, requiredDownload):
   """ get the estimated download time """
   if self.est_speed == 0:
     timeModem = requiredDownload/(56*1024/8)  # 56 kbit 
     timeDSL = requiredDownload/(1024*1024/8)  # 1Mbit = 1024 kbit
     s= _("This download will take about %s with a 1Mbit DSL connection "
          "and about %s with a 56k modem.") % (FuzzyTimeToStr(timeDSL), FuzzyTimeToStr(timeModem))
     return s
   # if we have a estimated speed, use it
   s = _("This download will take about %s with your connection. ") % FuzzyTimeToStr(requiredDownload/self.est_speed)
   return s
 def _handleException(self, type, value, tb):
     import traceback
     print
     lines = traceback.format_exception(type, value, tb)
     logging.error("not handled exception:\n%s" % "\n".join(lines))
     self.error(
         _("A fatal error occurred"),
         _("Please report this as a bug and include the "
           "files /var/log/dist-upgrade/main.log and "
           "/var/log/dist-upgrade/apt.log "
           "in your report. The upgrade has aborted.\n"
           "Your original sources.list was saved in "
           "/etc/apt/sources.list.distUpgrade."), "\n".join(lines))
     sys.exit(1)
 def _handleException(self, type, value, tb):
     import traceback
     print
     lines = traceback.format_exception(type, value, tb)
     logging.error("not handled exception:\n%s" % "\n".join(lines))
     self.error(_("A fatal error occurred"),
                _("Please report this as a bug and include the "
                  "files /var/log/dist-upgrade/main.log and "
                  "/var/log/dist-upgrade/apt.log "
                  "in your report. The upgrade has aborted.\n"
                  "Your original sources.list was saved in "
                  "/etc/apt/sources.list.distUpgrade."),
                "\n".join(lines))
     sys.exit(1)
 def askYesNoQuestion(self, summary, msg, default='No'):
     print
     print twrap(summary)
     print twrap(msg)
     if default == 'No':
         print _("Continue [yN] "),
         res = sys.stdin.readline()
         # TRANSLATORS: first letter of a positive (yes) answer
         if res.strip().lower().startswith(_("y")):
             return True
         return False
     else:
         print _("Continue [Yn] "),
         res = sys.stdin.readline()
         # TRANSLATORS: first letter of a negative (no) answer
         if res.strip().lower().startswith(_("n")):
             return False
         return True
 def askYesNoQuestion(self, summary, msg, default='No'):
   print
   print twrap(summary)
   print twrap(msg)
   if default == 'No':
       print _("Continue [yN] "),
       res = sys.stdin.readline()
       # TRANSLATORS: first letter of a positive (yes) answer
       if res.strip().lower().startswith(_("y")):
           return True
       return False
   else:
       print _("Continue [Yn] "),
       res = sys.stdin.readline()
       # TRANSLATORS: first letter of a negative (no) answer
       if res.strip().lower().startswith(_("n")):
           return False
       return True
    def open(self, url):
        pass
    def show(self):
      pass
    def hide(self):
      pass

(STEP_PREPARE,
 STEP_MODIFY_SOURCES,
 STEP_FETCH,
 STEP_INSTALL,
 STEP_CLEANUP,
 STEP_REBOOT,
 STEP_N) = range(1,8)

( _("Preparing to upgrade"),
  _("Getting new software channels"),
  _("Getting new packages"),
  _("Installing the upgrades"),
  _("Cleaning up"),
)

class DistUpgradeView(object):
    " abstraction for the upgrade view "
    def __init__(self):
        self.needs_screen = False
        pass
    def getOpCacheProgress(self):
        " return a OpProgress() subclass for the given graphic"
        return apt.progress.base.OpProgress()
    def getFetchProgress(self):
 def confirmChanges(self, summary, changes, demotions, downloadSize,
                    actions=None, removal_bold=True):
   DistUpgradeView.confirmChanges(self, summary, changes, demotions, 
                                  downloadSize, actions)
   print
   print twrap(summary)
   print twrap(self.confirmChangesMessage)
   print " %s %s" % (_("Continue [yN] "), _("Details [d]")),
   while True:
     res = sys.stdin.readline()
     # TRANSLATORS: the "y" is "yes"
     if res.strip().lower().startswith(_("y")):
       return True
     # TRANSLATORS: the "n" is "no"
     elif res.strip().lower().startswith(_("n")):
       return False
     # TRANSLATORS: the "d" is "details"
     elif res.strip().lower().startswith(_("d")):
       output = ""
       if len(self.demotions) > 0:
           output += "\n"  
           output += twrap(
               _("No longer supported: %s\n") % " ".join([p.name for p in self.demotions]),
               subsequent_indent='  ')
       if len(self.toRemove) > 0:
           output += "\n"  
           output += twrap(
               _("Remove: %s\n") % " ".join([p.name for p in self.toRemove]),
               subsequent_indent='  ')
       if len(self.toRemoveAuto) > 0:
           output += twrap(
               _("Remove (was auto installed) %s") % " ".join([p.name for p in self.toRemoveAuto]), 
               subsequent_indent='  ')
           output += "\n"
       if len(self.toInstall) > 0:
           output += "\n"
           output += twrap(
               _("Install: %s\n") % " ".join([p.name for p in self.toInstall]),
               subsequent_indent='  ')
       if len(self.toUpgrade) > 0:
           output += "\n"  
           output += twrap(
               _("Upgrade: %s\n") % " ".join([p.name for p in self.toUpgrade]),
               subsequent_indent='  ')
       self.showInPager(output)
     print "%s %s" % (_("Continue [yN] "), _("Details [d]")),
 def confirmChanges(self,
                    summary,
                    changes,
                    demotions,
                    downloadSize,
                    actions=None,
                    removal_bold=True):
     DistUpgradeView.confirmChanges(self, summary, changes, demotions,
                                    downloadSize, actions)
     print
     print twrap(summary)
     print twrap(self.confirmChangesMessage)
     print " %s %s" % (_("Continue [yN] "), _("Details [d]")),
     while True:
         res = sys.stdin.readline()
         # TRANSLATORS: the "y" is "yes"
         if res.strip().lower().startswith(_("y")):
             return True
         # TRANSLATORS: the "n" is "no"
         elif res.strip().lower().startswith(_("n")):
             return False
         # TRANSLATORS: the "d" is "details"
         elif res.strip().lower().startswith(_("d")):
             output = ""
             if len(self.demotions) > 0:
                 output += "\n"
                 output += twrap(_("No longer supported: %s\n") %
                                 " ".join([p.name for p in self.demotions]),
                                 subsequent_indent='  ')
             if len(self.toRemove) > 0:
                 output += "\n"
                 output += twrap(_("Remove: %s\n") %
                                 " ".join([p.name for p in self.toRemove]),
                                 subsequent_indent='  ')
             if len(self.toRemoveAuto) > 0:
                 output += twrap(
                     _("Remove (was auto installed) %s") %
                     " ".join([p.name for p in self.toRemoveAuto]),
                     subsequent_indent='  ')
                 output += "\n"
             if len(self.toInstall) > 0:
                 output += "\n"
                 output += twrap(_("Install: %s\n") %
                                 " ".join([p.name for p in self.toInstall]),
                                 subsequent_indent='  ')
             if len(self.toUpgrade) > 0:
                 output += "\n"
                 output += twrap(_("Upgrade: %s\n") %
                                 " ".join([p.name for p in self.toUpgrade]),
                                 subsequent_indent='  ')
             self.showInPager(output)
         print "%s %s" % (_("Continue [yN] "), _("Details [d]")),
 def confirmRestart(self):
   return self.askYesNoQuestion(_("Restart required"),
                                _("To finish the upgrade, a restart is "
                                  "required.\n"
                                  "If you select 'y' the system "
                                  "will be restarted."), default='No')
 def showDemotions(self, summary, msg, demotions):
     self.information(summary, msg, 
                      _("Demoted:\n")+twrap(", ".join(demotions)))
def FuzzyTimeToStr(sec):
  " return the time a bit fuzzy (no seconds if time > 60 secs "
  #print "FuzzyTimeToStr: ", sec
  sec = int(sec)

  days = sec/(60*60*24)
  hours = sec/(60*60) % 24
  minutes = (sec/60) % 60
  seconds = sec % 60
  # 0 seonds remaining looks wrong and its "fuzzy" anyway
  if seconds == 0:
    seconds = 1

  # string map to make the re-ordering possible
  map = { "str_days" : "",
          "str_hours" : "",
          "str_minutes" : "",
          "str_seconds" : ""
        }
  
  # get the fragments, this is not ideal i18n wise, but its
  # difficult to do it differently
  if days > 0:
    map["str_days"] = ngettext("%li day","%li days", days) % days
  if hours > 0:
    map["str_hours"] = ngettext("%li hour","%li hours", hours) % hours
  if minutes > 0:
    map["str_minutes"] = ngettext("%li minute","%li minutes", minutes) % minutes
  map["str_seconds"] = ngettext("%li second","%li seconds", seconds) % seconds

  # now assemble the string
  if days > 0:
    # Don't print str_hours if it's an empty string, see LP: #288912
    if map["str_hours"] == '':
        return map["str_days"]
    # TRANSLATORS: you can alter the ordering of the remaining time
    # information here if you shuffle %(str_days)s %(str_hours)s %(str_minutes)s
    # around. Make sure to keep all '$(str_*)s' in the translated string
    # and do NOT change anything appart from the ordering.
    #
    # %(str_hours)s will be either "1 hour" or "2 hours" depending on the
    # plural form
    # 
    # Note: most western languages will not need to change this
    return _("%(str_days)s %(str_hours)s") % map
  # display no minutes for time > 3h, see LP: #144455
  elif hours > 3:
    return map["str_hours"]
  # when we are near the end, become more precise again
  elif hours > 0:
    # Don't print str_minutes if it's an empty string, see LP: #288912
    if map["str_minutes"] == '':
        return map["str_hours"]
    # TRANSLATORS: you can alter the ordering of the remaining time
    # information here if you shuffle %(str_hours)s %(str_minutes)s
    # around. Make sure to keep all '$(str_*)s' in the translated string
    # and do NOT change anything appart from the ordering.
    #
    # %(str_hours)s will be either "1 hour" or "2 hours" depending on the
    # plural form
    # 
    # Note: most western languages will not need to change this
    return _("%(str_hours)s %(str_minutes)s") % map
  elif minutes > 0:
    return map["str_minutes"]
  return map["str_seconds"]
def FuzzyTimeToStr(sec):
  " return the time a bit fuzzy (no seconds if time > 60 secs "
  #print "FuzzyTimeToStr: ", sec
  sec = int(sec)

  days = sec/(60*60*24)
  hours = sec/(60*60) % 24
  minutes = (sec/60) % 60
  seconds = sec % 60
  # 0 seonds remaining looks wrong and its "fuzzy" anyway
  if seconds == 0:
    seconds = 1

  # string map to make the re-ordering possible
  map = { "str_days" : "",
          "str_hours" : "",
          "str_minutes" : "",
          "str_seconds" : ""
        }
  
  # get the fragments, this is not ideal i18n wise, but its
  # difficult to do it differently
  if days > 0:
    map["str_days"] = ngettext("%li day","%li days", days) % days
  if hours > 0:
    map["str_hours"] = ngettext("%li hour","%li hours", hours) % hours
  if minutes > 0:
    map["str_minutes"] = ngettext("%li minute","%li minutes", minutes) % minutes
  map["str_seconds"] = ngettext("%li second","%li seconds", seconds) % seconds

  # now assemble the string
  if days > 0:
    # Don't print str_hours if it's an empty string, see LP: #288912
    if map["str_hours"] == '':
        return map["str_days"]
    # TRANSLATORS: you can alter the ordering of the remaining time
    # information here if you shuffle %(str_days)s %(str_hours)s %(str_minutes)s
    # around. Make sure to keep all '$(str_*)s' in the translated string
    # and do NOT change anything appart from the ordering.
    #
    # %(str_hours)s will be either "1 hour" or "2 hours" depending on the
    # plural form
    # 
    # Note: most western languages will not need to change this
    return _("%(str_days)s %(str_hours)s") % map
  # display no minutes for time > 3h, see LP: #144455
  elif hours > 3:
    return map["str_hours"]
  # when we are near the end, become more precise again
  elif hours > 0:
    # Don't print str_minutes if it's an empty string, see LP: #288912
    if map["str_minutes"] == '':
        return map["str_hours"]
    # TRANSLATORS: you can alter the ordering of the remaining time
    # information here if you shuffle %(str_hours)s %(str_minutes)s
    # around. Make sure to keep all '$(str_*)s' in the translated string
    # and do NOT change anything appart from the ordering.
    #
    # %(str_hours)s will be either "1 hour" or "2 hours" depending on the
    # plural form
    # 
    # Note: most western languages will not need to change this
    return _("%(str_hours)s %(str_minutes)s") % map
  elif minutes > 0:
    return map["str_minutes"]
  return map["str_seconds"]
 def confirmChanges(self, summary, changes, demotions, downloadSize,
                    actions=None, removal_bold=True):
     """ display the list of changed packages (apt.Package) and
         return if the user confirms them
     """
     self.confirmChangesMessage = ""
     self.demotions = demotions
     self.toInstall = []
     self.toUpgrade = []
     self.toRemove = []
     self.toRemoveAuto = []
     self.toDowngrade = []
     for pkg in changes:
         if pkg.marked_install: 
           self.toInstall.append(pkg)
         elif pkg.marked_upgrade: 
           self.toUpgrade.append(pkg)
         elif pkg.marked_delete:
           if pkg._pcache._depcache.is_auto_installed(pkg._pkg):
             self.toRemoveAuto.append(pkg)
           else:
             self.toRemove.append(pkg)
         elif pkg.marked_downgrade: 
           self.toDowngrade.append(pkg)
     # sort it
     self.toInstall.sort()
     self.toUpgrade.sort()
     self.toRemove.sort()
     self.toRemoveAuto.sort()
     self.toDowngrade.sort()
     # no re-installs 
     assert(len(self.toInstall)+len(self.toUpgrade)+len(self.toRemove)+len(self.toRemoveAuto)+len(self.toDowngrade) == len(changes))
     # now build the message (the same for all frontends)
     msg = "\n"
     pkgs_remove = len(self.toRemove) + len(self.toRemoveAuto)
     pkgs_inst = len(self.toInstall)
     pkgs_upgrade = len(self.toUpgrade)
     # FIXME: show detailed packages
     if len(self.demotions) > 0:
       msg += ngettext(
         "%(amount)d installed package is no longer supported by Canonical. "
         "You can still get support from the community.",
         "%(amount)d installed packages are no longer supported by "
         "Canonical. You can still get support from the community.",
         len(self.demotions)) % { 'amount' : len(self.demotions) }
       msg += "\n\n"
     if pkgs_remove > 0:
       # FIXME: make those two separate lines to make it clear
       #        that the "%" applies to the result of ngettext
       msg += ngettext("%d package is going to be removed.",
                       "%d packages are going to be removed.",
                       pkgs_remove) % pkgs_remove
       msg += " "
     if pkgs_inst > 0:
       msg += ngettext("%d new package is going to be "
                       "installed.",
                       "%d new packages are going to be "
                       "installed.",pkgs_inst) % pkgs_inst
       msg += " "
     if pkgs_upgrade > 0:
       msg += ngettext("%d package is going to be upgraded.",
                       "%d packages are going to be upgraded.",
                       pkgs_upgrade) % pkgs_upgrade
       msg +=" "
     if downloadSize > 0:
       msg += _("\n\nYou have to download a total of %s. ") %\
           apt_pkg.SizeToStr(downloadSize)
       msg += self.getFetchProgress().estimatedDownloadTime(downloadSize)
     if ((pkgs_upgrade + pkgs_inst) > 0) and ((pkgs_upgrade + pkgs_inst + pkgs_remove) > 100):
       if self.getFetchProgress().isDownloadSpeedEstimated():
         msg += "\n\n%s" % _( "Installing the upgrade "
                              "can take several hours. Once the download "
                              "has finished, the process cannot be canceled.")
       else:
         msg += "\n\n%s" % _( "Fetching and installing the upgrade "
                              "can take several hours. Once the download "
                              "has finished, the process cannot be canceled.")
     else:
       if pkgs_remove > 100:
         msg += "\n\n%s" % _( "Removing the packages "
                              "can take several hours. ")
     # Show an error if no actions are planned
     if (pkgs_upgrade + pkgs_inst + pkgs_remove) < 1:
       # FIXME: this should go into DistUpgradeController
       summary = _("The software on this computer is up to date.")
       msg = _("There are no upgrades available for your system. "
               "The upgrade will now be canceled.")
       self.error(summary, msg)
       return False
     # set the message
     self.confirmChangesMessage = msg
     return True
    def open(self, url):
        pass
    def show(self):
      pass
    def hide(self):
      pass

(STEP_PREPARE,
 STEP_MODIFY_SOURCES,
 STEP_FETCH,
 STEP_INSTALL,
 STEP_CLEANUP,
 STEP_REBOOT,
 STEP_N) = range(1,8)

( _("Preparing to upgrade"),
  _("Getting new software channels"),
  _("Getting new packages"),
  _("Installing the upgrades"),
  _("Cleaning up"),
)

class DistUpgradeView(object):
    " abstraction for the upgrade view "
    def __init__(self):
        self.needs_screen = False
        pass
    def getOpCacheProgress(self):
        " return a OpProgress() subclass for the given graphic"
        return apt.progress.base.OpProgress()
    def getFetchProgress(self):
 def confirmChanges(self, summary, changes, demotions, downloadSize,
                    actions=None, removal_bold=True):
     """ display the list of changed packages (apt.Package) and
         return if the user confirms them
     """
     self.confirmChangesMessage = ""
     self.demotions = demotions
     self.toInstall = []
     self.toUpgrade = []
     self.toRemove = []
     self.toRemoveAuto = []
     self.toDowngrade = []
     for pkg in changes:
         if pkg.marked_install: 
           self.toInstall.append(pkg)
         elif pkg.marked_upgrade: 
           self.toUpgrade.append(pkg)
         elif pkg.marked_delete:
           if pkg._pcache._depcache.is_auto_installed(pkg._pkg):
             self.toRemoveAuto.append(pkg)
           else:
             self.toRemove.append(pkg)
         elif pkg.marked_downgrade: 
           self.toDowngrade.append(pkg)
     # sort it
     self.toInstall.sort()
     self.toUpgrade.sort()
     self.toRemove.sort()
     self.toRemoveAuto.sort()
     self.toDowngrade.sort()
     # no re-installs 
     assert(len(self.toInstall)+len(self.toUpgrade)+len(self.toRemove)+len(self.toRemoveAuto)+len(self.toDowngrade) == len(changes))
     # now build the message (the same for all frontends)
     msg = "\n"
     pkgs_remove = len(self.toRemove) + len(self.toRemoveAuto)
     pkgs_inst = len(self.toInstall)
     pkgs_upgrade = len(self.toUpgrade)
     # FIXME: show detailed packages
     if len(self.demotions) > 0:
       msg += ngettext(
         "%(amount)d installed package is no longer supported by Canonical. "
         "You can still get support from the community.",
         "%(amount)d installed packages are no longer supported by "
         "Canonical. You can still get support from the community.",
         len(self.demotions)) % { 'amount' : len(self.demotions) }
       msg += "\n\n"
     if pkgs_remove > 0:
       # FIXME: make those two separate lines to make it clear
       #        that the "%" applies to the result of ngettext
       msg += ngettext("%d package is going to be removed.",
                       "%d packages are going to be removed.",
                       pkgs_remove) % pkgs_remove
       msg += " "
     if pkgs_inst > 0:
       msg += ngettext("%d new package is going to be "
                       "installed.",
                       "%d new packages are going to be "
                       "installed.",pkgs_inst) % pkgs_inst
       msg += " "
     if pkgs_upgrade > 0:
       msg += ngettext("%d package is going to be upgraded.",
                       "%d packages are going to be upgraded.",
                       pkgs_upgrade) % pkgs_upgrade
       msg +=" "
     if downloadSize > 0:
       msg += _("\n\nYou have to download a total of %s. ") %\
           apt_pkg.SizeToStr(downloadSize)
       msg += self.getFetchProgress().estimatedDownloadTime(downloadSize)
     if (pkgs_upgrade + pkgs_inst + pkgs_remove) > 100:
       msg += "\n\n%s" % _( "Fetching and installing the upgrade "
                            "can take several hours. Once the download "
                            "has finished, the process cannot be cancelled.")
     # Show an error if no actions are planned
     if (pkgs_upgrade + pkgs_inst + pkgs_remove) < 1:
       # FIXME: this should go into DistUpgradeController
       summary = _("Your system is up-to-date")
       msg = _("There are no upgrades available for your system. "
               "The upgrade will now be canceled.")
       self.error(summary, msg)
       return False
     # set the message
     self.confirmChangesMessage = msg
     return True
 def showDemotions(self, summary, msg, demotions):
     self.information(summary, msg,
                      _("Demoted:\n") + twrap(", ".join(demotions)))
 def abort(self):
     print
     print _("Aborting")
 def abort(self):
   print
   print _("Aborting")