U E D R , A S I H C RSS

TFP예제/Wiki Page Gather



1. 프로그램 개요

집에서 모인모인을 돌리다가 전에 생각해두었었던 MindMap생각이 났다. Page간 관계들에 대한 Navigation을 위한. 무작정 코딩부터 하려고 했는데 머릿속에 정리가 되질 않았다. 연습장에 이리저리 쓰고 그리고 했지만. -_-; '너는 왜 공부하고 실천을 안하는 것이야!' 공부란 머리로 절반, 몸으로 절반을 익힌다. 컴공에서 '백견이 불여일타' 란 말이 괜히 나오는 것은 아니리라.

파이썬을 실행시켰다.

2. 프로그래밍 중 느낀점

  • '생각할 수 있는 가장 단순한 것부터 생각하라.' 디자인은 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 흐흐..) 암튼. 나는 모인모인소스를 보면서 제목 검색 관련 일부 코드를 짤라서 쉘에서 간단히 실행해보고 검토하고 실제 소스에 적용해볼 수 있었다.


3. 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)

4. 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 ()

5. 실행 결과

집에서 돌리고 있는 모인모인 디렉토리 기준임. (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

6. 문제점

위의 예에서는 해당 모듈에서 FrontPage 화일을 직접 open 했다. 위키에서 FrontPage가 바뀌었을 경우에는 해당 알고리즘이 올바르다 하더라도 테스트 코드에서 에러를 유발할 것이다. - 테스트를 위한 FrontPage 화일을 따로 빼두는 방법이 있겠군. -_-; (문제를 명확하게 해두면 해결방법이 도출되기 쉽다. ^^;)


Valid XHTML 1.0! Valid CSS! powered by MoniWiki
last modified 2021-02-07 05:28:10
Processing time 0.0204 sec