- 论坛徽章:
- 0
|
这篇我开始基本设置之旅---basic.py解析:
如图所示,basic也仅实现了一个类,7个方法。
还是像前两篇一样,我们来将代码贴出来,然后逐行分析,遇到新的模块或者陌生的语法和调用,我会引导外部分析:
import gtk
import gtk.glade
import gobject
import string
import os
import random //python的随机数生成器模块,比如需要一从1到100的随机数,则random.randint(1,100).
import crypt //验证unix密码的函数,只有一种可能那就是crypt.crypt(word, salt)
import getopt //命令行构造
from rhpl import keyboard_models
import rhpl.keyboard as keyboard //rhpl的关于识别系统键盘的库函数
from hardwareLists import langDict //识别系统语言的类,将会详细分析其代码。
import kickstartGui //上篇分析过的,毕竟有些东西是要显示在主要的GUI上的。
import sys
from pykickstart.constants import *
##
## I18N
##
import gettext
gtk.glade.bindtextdomain("system-config-kickstart")
_ = lambda x: gettext.ldgettext("system-config-kickstart", x)
sys.path.append("/usr/share/system-config-date") //追加另外一个设置日期的工具的PYTHONPATH.
class basic: //定义basic类
def __init__(self, parent_class, xml, notebook, ksHandler):
self.parent_class = parent_class
self.notebook = notebook
self.ks = ksHandler
self.xml = xml
//以下一段为从glade文件获得gtk相应的widget.
self.lang_combo = xml.get_widget("lang_combo")
self.keyboard_combo = xml.get_widget("keyboard_combo")
self.timezone_combo = xml.get_widget("timezone_combo")
self.utc_check_button = xml.get_widget("utc_check_button")
self.root_passwd_entry = xml.get_widget("root_passwd_entry")
self.root_passwd_confirm_entry = xml.get_widget("root_passwd_confirm_entry")
self.reboot_checkbutton = xml.get_widget("reboot_checkbutton")
self.text_install_checkbutton = xml.get_widget("text_install_checkbutton")
self.ks.bootloader(md5pass="", password="")
self.interactive_checkbutton = xml.get_widget("interactive_checkbutton")
self.encrypt_root_pw_checkbutton = xml.get_widget("encrypt_root_pw_checkbutton")
self.lang_support_list = xml.get_widget("lang_support_list")
self.platform_combo = xml.get_widget("platform_combo")
self.platform_list = [_("x86, AMD64, or Intel EM64T"), _("Intel Itanium"), _("IBM iSeries"),
_("IBM pSeries"), _("IBM zSeries/s390")]
self.platform_combo.set_popdown_strings(self.platform_list)
self.platform_combo.entry.connect("changed", self.platformChanged)//自定义,不是从glade获得,系统所支持的架构。
self.key_checkbutton = xml.get_widget("key_checkbutton")
self.key_entry = xml.get_widget("key_entry")
self.key_checkbutton.connect("toggled", self.keyChanged)//去找keychanged这个方法吧!
self.langDict = langDict //获得系统支持的语言,以python字典形式存储。详见后面。
# set a default platform
if not self.ks.platform:
self.ks.platform = "x86, AMD64, or Intel EM64T"
#populate language combo
self.lang_list = self.langDict.keys()
self.lang_list.sort()
self.lang_combo.set_popdown_strings(self.lang_list)
#set default to English
self.lang_combo.list.select_item(self.lang_list.index('English (USA)'))
#populate keyboard combo, add keyboards here
self.keyboard_dict = keyboard_models.KeyboardModels().get_models()
keys = self.keyboard_dict.keys()
keyboard_list = []
for item in keys:
keyboard_list.append(self.keyboard_dict[item][0])
keyboard_list.sort()
self.keyboard_combo.set_popdown_strings(keyboard_list)
#set default to English
kbd = keyboard.Keyboard()
kbd.read()
currentKeymap = kbd.get()
#set keyboard to current keymap
try:
self.keyboard_combo.entry.set_text(self.keyboard_dict[currentKeymap][0])
except:
self.keyboard_combo.entry.set_text(self.keyboard_dict["us"][0])
#populate time zone combo
import zonetab //来自system-config-date的类,获取/usr/share/zoneinfo/zone.tab文件内容,此将会在以后对文本处理方面来分析。
zt = zonetab.ZoneTab()
self.timezone_list = [ x.tz for x in zt.getEntries() ] //将大洲/国家提取出来。
self.timezone_list.sort() //排序
try:
select = self.timezone_list.index("America/New_York") //index,呵呵,狗日的america.
except:
select = 0
self.timezone_combo.set_popdown_strings(self.timezone_list) //下拉列表框
self.timezone_combo.list.select_item(select)
def updateKS(self, ksHandler): //更新ks临时
self.ks = ksHandler
def formToKickstart(self, doInstall): //获得信息
self.ks.lang(lang=self.languageLookup(self.lang_combo.entry.get_text())) //语言
keys = self.keyboard_dict.keys() //键盘
keys.sort()
for item in keys:
if self.keyboard_dict[item][0] == self.keyboard_combo.entry.get_text():
self.ks.keyboard(keyboard=item)
break
self.ks.timezone(timezone=self.timezone_combo.entry.get_text(), isUtc=self.utc_check_button.get_active())
//以下的密码设置应该注意一下,很多地方都会用到。
//首先判断两次输入的明文是否匹配。不匹配则弹出对话框,并再次输入。(再保存文件时会提示!也就是说在applykickstart时才会调用此方法。)
if self.root_passwd_entry.get_text() != self.root_passwd_confirm_entry.get_text():
dlg = gtk.MessageDialog(None, 0, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, _("Root passwords do not match."))
dlg.set_title(_("Error"))
dlg.set_default_size(100, 100)
dlg.set_position (gtk.WIN_POS_CENTER)
dlg.set_icon(kickstartGui.iconPixbuf)
dlg.set_border_width(2)
dlg.set_modal(True)
toplevel = self.xml.get_widget("main_window")
dlg.set_transient_for(toplevel)
dlg.run()
dlg.hide()
self.notebook.set_current_page(0)//切还到当前
self.root_passwd_entry.set_text("") //清空
self.root_passwd_confirm_entry.set_text("") //清空
self.root_passwd_entry.grab_focus() //获得光标
return None
pure = self.root_passwd_entry.get_text()
//注意了,加密出没!
if pure != "":
if self.encrypt_root_pw_checkbutton.get_active() == True:
salt = "$1$"
saltLen = 8
if not pure.startswith(salt):
for i in range(saltLen):
salt = salt + random.choice (string.letters + string.digits + './')
self.passwd = crypt.crypt (pure, salt) //类似unix的shadow加密。
temp = unicode (self.passwd, 'iso-8859-1') //编码!!
self.ks.rootpw(isCrypted=True, password=temp)
else:
self.ks.rootpw(isCrypted=True, password=pure)
else:
self.passwd = self.root_passwd_entry.get_text()
self.ks.rootpw(isCrypted=False, password=self.passwd) //大不了不加密就是了。
self.ks.platform = self.platform_combo.entry.get_text() 获取平台列表
if self.reboot_checkbutton.get_active():
self.ks.reboot(action=KS_REBOOT)
else:
self.ks.reboot(action=KS_WAIT)
if self.text_install_checkbutton.get_active():
self.ks.displaymode(displayMode=DISPLAY_MODE_TEXT)
else:
self.ks.displaymode(displayMode=DISPLAY_MODE_GRAPHICAL)
self.ks.interactive(interactive=self.interactive_checkbutton.get_active())
if self.key_checkbutton.get_active():
if self.key_entry.get_text() == "":
self.ks.key(key=KS_INSTKEY_SKIP)
else:
self.ks.key(key=self.key_entry.get_text())
else:
self.ks.key(key="")
return 0
def languageLookup(self, args): //语言获取
return self.langDict [args]
def platformChanged(self, entry): //平台
platform = entry.get_text()
if platform:
self.parent_class.platformTypeChanged(entry.get_text())
def keyChanged(self, args):
self.key_entry.set_sensitive(self.key_checkbutton.get_active())
def applyKickstart(self): //一切都OK?我要保存了阿!!!!!!!
if self.ks.platform in self.platform_list:
self.platform_combo.entry.set_text(self.ks.platform)
if self.ks.lang.lang.find (".") != -1:
ksLang = self.ks.lang.lang.split(".")[0]
else:
ksLang = self.ks.lang.lang
for lang in self.langDict.keys():
if self.langDict[lang] == ksLang:
self.lang_combo.list.select_item(self.lang_list.index(lang))
if self.ks.keyboard.keyboard != "":
self.keyboard_combo.entry.set_text(self.keyboard_dict[self.ks.keyboard.keyboard][0])
if self.ks.timezone.timezone != "":
self.timezone_combo.list.select_item(self.timezone_list.index(self.ks.timezone.timezone))
self.reboot_checkbutton.set_active(self.ks.reboot.action == KS_REBOOT)
if self.ks.displaymode.displayMode == DISPLAY_MODE_TEXT:
self.text_install_checkbutton.set_active(True)
if self.ks.interactive.interactive == True:
self.interactive_checkbutton.set_active(True)
if self.ks.rootpw.password != "":
self.root_passwd_entry.set_text(self.ks.rootpw.password)
self.root_passwd_confirm_entry.set_text(self.ks.rootpw.password)
self.encrypt_root_pw_checkbutton.set_active(self.ks.rootpw.isCrypted)
if self.ks.key.key == "":
self.key_checkbutton.set_active(False)
self.key_entry.set_text("")
elif self.ks.key.key == KS_INSTKEY_SKIP:
self.key_checkbutton.set_active(True)
self.key_entry.set_text("")
else:
self.key_checkbutton.set_active(True)
self.key_entry.set_text(self.ks.key.key)
文章到此,就开始有了疑惑,不就是这些吗?有什么大不了的?但是,喜欢往里专的人都清楚和明白,键盘是怎么被读取到的?时区了呢?加密的过程是什么?语言列表是如何出现的?以上均是一个import就解决了的问题,那么我们该怎么往下走了呢?
一个小小软件,错综复杂到如此地步,真是小看了它!解决问题是程序员的使命,而代码就是解决问题的实现,解决问题是负载的,代码应该是清晰的,但逻辑上应该是复杂的!
还好,就快完了,其实脚本语言的最大的使命之一就是文本处理!!文本能够熟练的处理好了,也就可以成为一名合格的系统管理员了!至于高深的算法、优秀的数据结构那是很遥远的东西,与现在的无关,将来也许会有!
来看代码吧!废话真多!
//删除了注释。
import string //仅仅是一个string就够了?string已经很强大了!
#pull list of language from system-config-languages
langDict = {} //定义一字典
lines = open("/usr/share/system-config-language/locale-list", "r").readlines()
//逐行读取指定文件
for line in lines:
tokens = string.split(line) //将行中的单词按空格、tab、换行符等分割,存储到list中。
if '.' in tokens[0]: //如果行中的第一个单词里有“点”时
#Chop encoding off so we can compare to self.installedLangs
langBase = string.split(tokens[0], '.') //用.将此单词分割,存储到列表。
langBase = langBase[0] //相当于赋值
elif '@' in tokens[0]: //如果行中的第一个单词里有@时
langBase = string.split(tokens[0], '@')//用@将此单词分割,存储到列表。
langBase = langBase[0]
else:
langBase = tokens[0] //什么都没有,就是没有了!
name = ""
for token in tokens[3:]: //将行中的第四个词抽取
name = name + " " + token //组成新的名称
name = string.strip(name) //将刚组成的新的名称再按空格、tab、换行符等分割。
langDict[name] = langBase //放到langDict中存储。
我以文件/usr/share/system-config-language/locale-list中的中国那一行为例说明:
zh_CN.UTF-8 utf8 lat0-sun16 Chinese (P.R. of China) - 中文(简体)
这是原文,经过此程序的过滤后,输出为:
langBase 是zh_CN,name是C h i n e s e.
顺便说一句,关于时区的抽取和语言这个差不了多少,此处我分析了一个例子,贴在此处:
import re,string
fn = '/usr/share/zoneinfo/zone.tab'
def readZoneTab():
f = open(fn, 'r')
comment = re.compile("^#")
coordre = re.compile("[\+-]")
while 1:
line = f.readline()
if not line:
break
if comment.search(line):
continue
fields = string.split(line, '\t')
if len(fields) 3:
comments = string.strip(fields[3])
else:
comments = None
f.close()
if __name__ == "__main__":
readZoneTab()
还用到了正则表达式模块了,呵呵,这是没有几年功夫搞不定的东西。。。。。
好,此篇点到为止,功能篇将继续,自己期待以下自己的时间!
本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/6303/showart_1360991.html |
|