[[TableOfContents]] === 프로그램 개요 === 집에서 모인모인을 돌리다가 전에 생각해두었었던 MindMap 이 생각이 났다. Page간 관계들에 대한 Navigation을 위한. 무작정 코딩부터 하려고 했는데 머릿속에 정리가 되질 않았다. 연습장에 이리저리 쓰고 그리고 했지만. -_-; '너는 왜 공부하고 실천을 안하는 것이야!' 공부란 머리로 절반, 몸으로 절반을 익힌다. 컴공에서 '백견이 불여일타' 란 말이 괜히 나오는 것은 아니리라. 파이썬을 실행시켰다. === 프로그래밍 중 느낀점 === * '생각할 수 있는 가장 단순한 것부터 생각하라.' 디자인은 TFP 와 Refactoring의 과정만으로 어느정도 보장이 된다. TFP을 추구하는 이상 기능와 의도에 의한 모듈화가 기본적으로 이루어진다. (여태껏의 경험 -- 그래봤자 3번째지만 -- 에 의하면, TFP를 하면서 LongMethod 냄새가 난 적이 없었다. (LongMethod와 Bad Smell 에 대해서는 BadSmellsInCode를 참조하라.) 만일 중복코드 등의 문제가 발생하더라도 기존의 막무가내식 방식에 비해 그 빈도가 적다. 만일 Bad Smell 이 난다면 ["Refactoring"] 을 하면 된다. (참고로 밑의 소스는 ["Refactoring"]의 과정은 거치지 않았다.) * Python 이라는 툴이 참 재미있는 녀석이라 생각한다. 방식이야 basic에서의 그것이겠지만, '인터프리터언어라는 것이 쉽고 편하다' 의 이유를 다시 생각하게 해준 계기가 되었다. 일반적으로 우리가 프로그래밍을 할 때는 (여기서는 C++이라 하자) Visual C++ 을 하나만 띄어놓고 프로그래밍 하는 경우가 별로 없다. 보통 product code 를 위한 하나, 해당 함수 기능의 부분구현 (임시코드 구현)을 위한 하나. 서버-클라이언트 프로그래밍인 경우에는 3개를 띄우는 경우도 다반사이다. Python 의 shell 은 임시코드를 구현하는데 매우 편리한 도구이다. (한편 이쯤되면 검문이 필요하다. VS 2-3개 띄우는 거랑 python IDLE을 2-3개 띄우는 거랑 다를바가 뭐냐.. --; 내가 말하고 싶은 것은 C++이나 PHP에 파이썬처럼 공통 인터프리터 쉘이 있었으면 하는 것. -_a 흐흐..) 암튼. 나는 모인모인소스를 보면서 제목 검색 관련 일부 코드를 짤라서 쉘에서 간단히 실행해보고 검토하고 실제 소스에 적용해볼 수 있었다. === WikiPageGatherTestCase.py === {{{~cpp import unittest from WikiPageGather import * class WikiPageGatherTestCase (unittest.TestCase): def setUp (self): self.pageGather = WikiPageGather () def tearDown (self): self.pageGather = None def testConvertWikiPageNameToMoinFileName (self): self.assertEquals (self.pageGather.WikiPageNameToMoinFileName ('''한글테스트'''), '''_c7_d1_b1_db_c5_d7_bd_ba_c6_ae''') self.assertEquals (self.pageGather.WikiPageNameToMoinFileName ("FrontPage"), "FrontPage") def testGetPageNamesFromPage (self): self.pageGather.SetPage ("FrontPage") self.assertEquals (self.pageGather.GetPageNamesFromPage (), ["LearningHowToLearn", "ActiveX", "Python", "XPInstalled", "TestFirstProgramming", "한글테스트", "PrevFrontPage"]) def testGetPageNamesFromString (self): strings = "Test First In TestFirstIn TesF TestFi guuweo StringIn" self.assertEquals (self.pageGather.GetPageNamesFromString (strings), ["TestFirstIn", "TestFi", "StringIn"]) strings = '''["Testing"] ["Testing The Program"] higu TestFirst twet''' self.assertEquals (self.pageGather.GetPageNamesFromString (strings), ["Testing", "Testing The Program", "TestFirst"]) def testIsHeadTagLine (self): strings = "== testing ==" self.assertEquals (self.pageGather.IsHeadTagLine (strings), 1) strings = "tese ewfe ewfw" self.assertEquals (self.pageGather.IsHeadTagLine (strings), 0) def testRemoveHeadLine (self): strings = '''=== ExtremeProgramming ===\ntesting.. -_-a\n== TestFirst Programmin ==\nfwe\n''' self.assertEquals (self.pageGather.RemoveHeadLine (strings), "testing.. -_-a\nfwe\n") def testGetWikiPage(self): self.assertEquals (self.pageGather.GetWikiPage ("FrontPage"), '=== Reading ===\n' + '["LearningHowToLearn"]\n\n\n=== C++ ===\n["ActiveX"]\n\n' + '[[Include(ActiveX,Test,1)]]\n\n=== Python ===\n["Python"]\n\n' + '=== ExtremeProgramming ===\n * ["XPInstalled"]\n * TestFirstProgramming\n'+ ' * ["ÇѱÛÅ׽ºƮ"]\n\n----\n["PrevFrontPage"]\n\n----\n') suite = unittest.makeSuite (WikiPageGatherTestCase, "test") runner = unittest.TextTestRunner () runner.run (suite) }}} === WikiPageGather.py === {{{~cpp import string, urllib, re class WikiPageGather: def __init__(self): self.pagePath = "f:\web\wiki-moinmoin\data\text\" self.pagename = '' def WikiPageNameToMoinFileName (self,pagename): safe = string.letters + string.digits res = list(pagename) for i in range(len(res)): c = res[i] if c not in safe: res[i] = '_%02x' % ord(c) return string.joinfields(res, '') def SetPage (self, pagename): self.pagename = pagename def GetWikiPage (self, pagename): fullpathname = self.pagePath + self.WikiPageNameToMoinFileName (pagename) pagefile = open (fullpathname, 'r') lines = pagefile.readlines () page = '' for line in lines: page += line pagefile.close() return page def RemoveHeadLine (self, lines): lines = string.split (lines, "\n") resultText = '' for line in lines: if self.IsHeadTagLine (line): continue elif line == '': continue resultText += line + "\n" return resultText def IsHeadTagLine (self, strings): try: if strings[0] == '=': return 1 elif strings[0:2] == '==': return 1 elif strings[0:3] == '===': return 1 else: return 0 except IndexError: return 0 def GetPageNamesFromPage (self): page = self.GetWikiPage (self.pagename) page = self.RemoveHeadLine (page) pagenamelist = [] pagenamelist += self.GetPageNamesFromString (page) return pagenamelist def GetPageNamesFromString (self, strings): PageNameRegularStr = '''(([A-Z][a-z0-9]+){2,})|(\[".*?"\])''' PageNameReg = re.compile (PageNameRegularStr) PageNameReg.findall (strings) pagenamelist = [] for pagename in PageNameReg.findall (strings): if pagename[0] != '': pagenamelist.append (pagename[0]) elif pagename[2] != '': realname = string.replace (pagename[2], '''["''', '') realname = string.replace (realname, '''"]''', '') pagenamelist.append (realname) return pagenamelist def main (self): self.SetPage ("FrontPage") for pagename in self.GetPageNamesFromPage (): print "pagename : " + pagename print "filename : " + self.WikiPageNameToMoinFileName (pagename) if __name__ == "__main__": pageGather = WikiPageGather () pageGather.main () }}} === 실행 결과 === 집에서 돌리고 있는 모인모인 디렉토리 기준임. (Python shell 인 IDLE 한글 패치를 해주지 않아서 그런지 원래는 한글이 깨져서 나온다. 약간 편집했음.) {{{~cpp pagename : LearningHowToLearn filename : LearningHowToLearn pagename : ActiveX filename : ActiveX pagename : Python filename : Python pagename : XPInstalled filename : XPInstalled pagename : TestFirstProgramming filename : TestFirstProgramming pagename : 한글테스트 filename : _c7_d1_b1_db_c5_d7_bd_ba_c6_ae pagename : PrevFrontPage filename : PrevFrontPage }}} === 문제점 === 위의 예에서는 해당 모듈에서 FrontPage 화일을 직접 open 했다. 위키에서 FrontPage가 바뀌었을 경우에는 해당 알고리즘이 올바르다 하더라도 테스트 코드에서 에러를 유발할 것이다. - 테스트를 위한 FrontPage 화일을 따로 빼두는 방법이 있겠군. -_-; (문제를 명확하게 해두면 해결방법이 도출되기 쉽다. ^^;) ---- ["TestFirstProgramming"]