# (c) 2006 Canonical # Author: Michael Vogt # # Released under the GPL # import warnings warnings.filterwarnings("ignore", "apt API not stable yet", FutureWarning) import apt import apt_pkg import os import shutil import subprocess import thread import time import gettext import sys import string import tempfile import re import FontConfig from gettext import gettext as _ from LocaleInfo import LocaleInfo from LangCache import * import macros # the language-selector abstraction class LanguageSelectorBase(object): """ base class for language-selector code """ def __init__(self, datadir=""): self._datadir = datadir # load the localeinfo "database" self._localeinfo = LocaleInfo("languagelist", self._datadir) self._cache = None def openCache(self, progress): self._cache = LanguageSelectorPkgCache(self._localeinfo, progress) def getMissingLangPacks(self): """ return a list of language packs that are not installed but should be installed """ missing = [] for langInfo in self._cache.getLanguageInformation(): #print langInfo.languageCode trans_package = "language-pack-%s" % langInfo.languageCode # we have a langpack installed, see if we have all of them if (trans_package in self._cache and \ (self._cache[trans_package].isInstalled or \ self._cache[trans_package].markedInstall or \ self._cache[trans_package].markedUpgrade) and \ not self._cache[trans_package].markedDelete): #print "IsInstalled: %s " % trans_package #print self._cache.pkg_translations[langInfo.languageCode] if langInfo.languageCode in self._cache.pkg_translations: for (pkg, translation) in self._cache.pkg_translations[langInfo.languageCode]: if (pkg in self._cache and \ (self._cache[pkg].isInstalled or \ self._cache[pkg].markedInstall or \ self._cache[pkg].markedUpgrade) and \ not self._cache[pkg].markedDelete and \ translation in self._cache and \ ((not self._cache[translation].isInstalled and \ not self._cache[translation].markedInstall and \ not self._cache[translation].markedUpgrade) or \ self._cache[translation].markedDelete) and \ not translation in missing): missing.append(translation) trans_package = "language-support-writing-%s" % langInfo.languageCode # we have a langsupport-writing installed, see if we have all of them if (trans_package in self._cache and (self._cache[trans_package].isInstalled or \ self._cache[trans_package].markedInstall or \ self._cache[trans_package].markedUpgrade)): #print "IsInstalled: %s " % trans_package #print self._cache.pkg_writing[langInfo.languageCode] if langInfo.languageCode in self._cache.pkg_writing: for (pkg, pull_pkg) in self._cache.pkg_writing[langInfo.languageCode]: if '|' in pkg: # multiple dependencies, if one of them is installed, pull the pull_pkg for p in pkg.split('|'): if self._cache[p] and \ (self._cache[p].isInstalled or \ self._cache[p].markedInstall or \ self._cache[p].markedUpgrade) and \ not self._cache[p].markedDelete and \ pull_pkg in self._cache and \ ((not self._cache[pull_pkg].isInstalled and \ not self._cache[pull_pkg].markedInstall and \ not self._cache[pull_pkg].markedUpgrade) or \ self._cache[pull_pkg].markedDelete) and \ not pull_pkg in missing: missing.append(pull_pkg) else: if pkg in self._cache and \ (self._cache[pkg].isInstalled or \ self._cache[pkg].markedInstall or \ self._cache[pkg].markedUpgrade) and \ not self._cache[pkg].markedDelete and \ pull_pkg in self._cache and \ ((not self._cache[pull_pkg].isInstalled and \ not self._cache[pull_pkg].markedInstall and \ not self._cache[pull_pkg].markedUpgrade) or \ self._cache[pull_pkg].markedDelete) and \ not pull_pkg in missing: missing.append(pull_pkg) # now check for a missing default language support default_lang = self._localeinfo.getSystemDefaultLanguage()[0] macr = macros.LangpackMacros(self._datadir, default_lang) default_lang = macr["LOCALE"] pkgcode = macr["PKGCODE"] # # if there is no default lang, return early # if default_lang is None: # return missing # # Fallback is English # pkgcode = 'en' # if default_lang in self._cache.langpack_locales: # pkgcode = self._cache.langpack_locales[default_lang] trans_package = "language-pack-%s" % pkgcode if (trans_package in self._cache and not self._cache[trans_package].isInstalled): missing += [trans_package] if pkgcode in self._cache.pkg_translations: for (pkg, translation) in self._cache.pkg_translations[pkgcode]: if (self._cache[pkg].isInstalled and not self._cache[translation].isInstalled): missing.append(translation) support_packages = LanguageSelectorPkgCache._getPkgList(self._cache, pkgcode) for support_package in support_packages: if (support_package in self._cache and not self._cache[support_package].isInstalled): missing.append(support_package) if pkgcode in self._cache.pkg_writing: for (pkg, pull_pkg) in self._cache.pkg_writing[pkgcode]: if '|' in pkg: # multiple dependencies, if one of them is installed, pull the pull_pkg for p in pkg.split('|'): if self._cache[p] and \ (self._cache[p].isInstalled or \ self._cache[p].markedInstall or \ self._cache[p].markedUpgrade) and \ not self._cache[p].markedDelete and \ pull_pkg in self._cache and \ ((not self._cache[pull_pkg].isInstalled and \ not self._cache[pull_pkg].markedInstall and \ not self._cache[pull_pkg].markedUpgrade) or \ self._cache[pull_pkg].markedDelete) and \ not pull_pkg in missing: missing.append(pull_pkg) else: if pkg in self._cache and \ (self._cache[pkg].isInstalled or \ self._cache[pkg].markedInstall or \ self._cache[pkg].markedUpgrade) and \ not self._cache[pkg].markedDelete and \ pull_pkg in self._cache and \ ((not self._cache[pull_pkg].isInstalled and \ not self._cache[pull_pkg].markedInstall and \ not self._cache[pull_pkg].markedUpgrade) or \ self._cache[pull_pkg].markedDelete) and \ not pull_pkg in missing: missing.append(pull_pkg) return missing def runAsRoot(self, cmd): " abstract interface for the frontends to run specific commands as root" # compatibilty code for frontends that already run as root if os.getuid() == 0: return subprocess.call(cmd) # raise AttributeError, "this method needs to be overwriten by the subclass" def writeLanguageSettings(self, sysLang=None, sysLanguage=None, userLang=None, userLanguage=None): conffiles = [] if sysLang or sysLanguage: conffiles = ["/etc/default/locale", "/etc/environment"] elif userLang or userLanguage: conffiles.append(os.path.expanduser("~/.profile")) else: # no arguments given, nothing to do. return None if sysLang: macr = macros.LangpackMacros(self._datadir, sysLang) findString = "LANG=" setString = "LANG=\"%s\"\n" % macr["SYSLOCALE"] elif sysLanguage: findString = "LANGUAGE=" setString = "LANGUAGE=\"%s\"\n" % sysLanguage elif userLang: macr = macros.LangpackMacros(self._datadir, userLang) findString = "export LANG=" setString = "export LANG=\"%s\"\n" % macr["SYSLOCALE"] elif userLanguage: findString = "export LANGUAGE=" setString = "export LANGUAGE=\"%s\"\n" % userLanguage for fname in conffiles: out = tempfile.NamedTemporaryFile() foundString = False if os.path.exists(fname) and \ os.access(fname, os.R_OK): # look for the line for line in open(fname): tmp = string.strip(line) if tmp.startswith(findString): foundString = True line = setString out.write(line) # if we have not found them add them if foundString == False: out.write(setString) out.flush() if sysLang or sysLanguage: self.runAsRoot(["/bin/cp",out.name, fname]) else: if os.access(fname, os.W_OK): shutil.copy(out.name, fname) os.chmod(fname, 0644) if userLang: # Special handler for GDM gdmscript = "/etc/init.d/gdm" if os.path.exists("/var/run/gdm.pid") and os.path.exists(gdmscript): fname = os.path.expanduser("~/.dmrc") out = tempfile.NamedTemporaryFile() foundLang = False # the Language var foundDesktop = False # the [Desktop] entry filebuffer = [] macr = macros.LangpackMacros(self._datadir, userLang) if os.path.exists(fname): # look for the line for line in open(fname): tmp = string.strip(line) if len(tmp) > 0: filebuffer.append(tmp) if tmp == '[Desktop]': foundDesktop = True if tmp.startswith("Language="): foundLang = True # if we have not found them add them if foundDesktop == False: line="\n[Desktop]\n" out.write(line) if foundLang == False: line="Language=%s\n" % macr["SYSLOCALE"] out.write(line) for line in filebuffer: if line.startswith("Language="): line = "Language=%s\n" % macr["SYSLOCALE"] else: line = line+"\n" out.write(line) out.flush() shutil.copy(out.name, fname) os.chmod(fname, 0644) if 'USER' in os.environ: userid = os.environ["USER"] path = '/var/cache/gdm/%s' % userid if os.path.exists(path): shutil.copy(fname, "%s/dmrc" % path) os.chmod("%s/dmrc" % path, 0644) # now set the fontconfig-voodoo if sysLanguage: fc = FontConfig.FontConfigHack() defaultLanguageCode = sysLanguage.split(':')[0] if defaultLanguageCode in fc.getAvailableConfigs(): self.runAsRoot(["fontconfig-voodoo", "-f", "--set=%s" % defaultLanguageCode]) else: self.runAsRoot(["fontconfig-voodoo","-f","--remove-current"]) # def setSystemDefaultLanguage(self, defaultLanguageCode): # " this updates the system default language " # conffiles = ["/etc/default/locale", "/etc/environment"] # for fname in conffiles: # out = tempfile.NamedTemporaryFile() # foundLanguage = False # the LANGUAGE var # foundLang = False # the LANG var # if os.path.exists(fname): # # look for the line # for line in open(fname): # tmp = string.strip(line) # if tmp.startswith("LANGUAGE="): # foundLanguage = True # line="LANGUAGE=\"%s\"\n" % self._localeinfo.makeEnvString(defaultLanguageCode) # #print line # if tmp.startswith("LANG="): # foundLang = True # # we always write utf8 languages # line="LANG=\"%s.UTF-8\"\n" % defaultLanguageCode # out.write(line) # #print line # # if we have not found them add them # if foundLanguage == False: # line="LANGUAGE=\"%s\"\n" % self._localeinfo.makeEnvString(defaultLanguageCode) # out.write(line) # if foundLang == False: # line="LANG=\"%s.UTF-8\"\n" % defaultLanguageCode # out.write(line) # out.flush() # self.runAsRoot(["/bin/cp",out.name, fname]) # # now set the fontconfig-voodoo # fc = FontConfig.FontConfigHack() # #print defaultLanguageCode # #print fc.getAvailableConfigs() # if defaultLanguageCode in fc.getAvailableConfigs(): # self.runAsRoot(["fontconfig-voodoo", "-f", # "--set=%s" % defaultLanguageCode]) # else: # self.runAsRoot(["fontconfig-voodoo","-f","--remove-current"]) # def setUserDefaultLanguage(self, defaultLanguageCode): # " this updates the user default language " # fname = os.path.expanduser("~/.dmrc") # out = tempfile.NamedTemporaryFile() # foundLang = False # the Language var # if os.path.exists(fname): # # look for the line # for line in open(fname): # tmp = string.strip(line) # if tmp.startswith("Language="): # foundLang = True # # we always write utf8 languages # line="Language=%s.UTF-8\n" % defaultLanguageCode # out.write(line) # # if we have not found them add them # if foundLang == False: # line="Language=%s.UTF-8\n" % defaultLanguageCode # out.write(line) # out.flush() # shutil.copy(out.name, fname) # os.chmod(fname, 0644) # # FIXME: This should be set on a per user base in ~/.fonts.conf # ## now set the fontconfig-voodoo # #fc = FontConfig.FontConfigHack() # ##print defaultLanguageCode # ##print fc.getAvailableConfigs() # #f defaultLanguageCode in fc.getAvailableConfigs(): # # self.runAsRoot(["fontconfig-voodoo", "-f", # # "--set=%s" % defaultLanguageCode]) # #else: # # self.runAsRoot(["fontconfig-voodoo","-f","--remove-current"]) # obsolete # def missingTranslationPkgs(self, pkg, translation_pkg): # """ this will check if the given pkg is installed and if # the needed translation package is installed as well # It returns a list of packages that need to be # installed # """ # # FIXME: this function is called too often and it's too slow # # -> see ../TODO for ideas how to fix it # missing = [] # # check if the pkg itself is available and installed # if not pkg in self._cache: # return missing # if not self._cache[pkg].isInstalled: # return missing # # match every packages that looks similar to translation_pkg # # # for pkg in self._cache: # if (pkg.name == translation_pkg or # pkg.name.startswith(translation_pkg+"-")): # if not pkg.isInstalled and pkg.candidateVersion != None: # missing.append(pkg.name) # return missing # if __name__ == "__main__": lsb = LanguageSelectorBase(datadir="..") lsb.openCache(apt.progress.OpProgress()) print lsb.verifyPackageLists()