2019년 2월 28일 목요일

[라이딩] 190228.팔당~양평


2019. 2. 28. 작년 휴가 남은 마지막 하나...
오늘 초미세먼지가 많지만 그냥 휴일을 버릴 수 없어서
라이딩을 계획하다.

무릎부상때문에 40km 이상의 라이딩도 쉽지 않다.
그래도 이전에 아라배길 라이딩시 다소 무리는 되었지만 60km 라이딩을 했으니 이번에도 무리가 되더라도 복귀하는데는 문제가 없을 것으로 생각하고 팔당 ~ 양주 라이딩을 계획했다.

좀 더 멀리까지 기차타고 가서 오고 싶었지만, 팔당으로 오는 기차는 없다.
경강선은 다른쪽으로 가는 기차고 판교까지 가기에는 내 다리가 버티지 못할 것 같다.


이거 저거 잡다하게 시간을 버리고 서브웨이에서 샌드위치를 사고 떠나니 10시가 넘었다.
11시에 팔당역에 도착해서 준비하고...
화장실도 다녀오고...


저 시립박물관 안에는 뭐가 있을까?
복귀하고도 점심을 먹으러 가는 바람에 제대로 보질 못했다.


무릎은 이렇게 보호대로...
복귀 중 무릎에 이상이 왔지만, 무릎 보호대로 조금이나마 버틸 수 있었다.



양평군 미술관 인증센터, 여기까지 30km를 왔는데 무릎은 멀쩡하다...
무릎에 무리를 주지 않으려 꽤 신경써서 타고 와서 그런지
이전보다 컨디션도 좋은 것 같다. (보급도 제대로 조금 챙겨먹다가 무릎에만 신경쓰다 보니 양평에 도착... ;;)

조금 더 갈까 하다가... 무릎 생각에 점심식사 생각에 (아래뱃길에서 한강으로 들어서 점심을 거르고 핵핵거리던 것이 생각났다) 다시 복귀하기로 했다.

복귀하면서 잠깐 댄싱도 해 보았는데... 모든게 멀쩡하다..........가...
40km 지점 정도 되었나... 또 무릎에 이상 신호가 온다...
무릎에 이상신호가 오면 모든 근육에 피로가 누적된다...

최대한 페달링을 여러가지로 해보고 통증을 피해다니려 했는데...
아까와는 많이 느낌이 다르다... ㅠㅠ


어찌 어찌해서 능내에 돌아왔다.
아까는 인증센터를 들르지 않고 그냥 갔는데...
예전 역사가 보기에 좋다. 지금은 박물관으로 쓰고 있는데 잠시 열어보니 예전 작은 대합실도 보이고 예전에는 이 작은 곳에서 서울에 가기 위해 또는 춘천쪽으로 가기위해 기차를 기다리며 생활터전이었던 곳이라 생각해 본다.




이 근처에서 점심을 먹을까 좀 찾아보았지만, 평일이라 그런건지 제대로 문을 연 곳이 없다. 팔당쪽에서 올라온 한 가족도 먹을 곳을 찾아보지만 제대로 찾지 못한 것 같다.


아직 무릎이 문제가 있어 괴롭다.
힘이 들고 봉크가 와서 라이딩이 어려워지는 것은 좋아질 수 있지만...
이 무릎은 더 이상 무리를 할 수도 없고, 어떻게 해결책을 찾기도 어렵고 난감하다.

어제 장경인대염에 효과있는 무릎보호대가 있는 것 같은데 그 무릎보호대를 사서 사용해 봐야겠다.

2019년 2월 27일 수요일

[라이딩] 190226.싯포스트 클램프 볼트 부러지다.

2/26
 아들이 집 근처 샵에 디녀왔는데 볼트 얻는데 실패 클램프 전체를 교체해야 한디고 함.
 1만원에서 3만원 이상까지...
 퇴근 후 바로 클램프와 싯포를 뽑아 구매했드 샵으로 로 출동...
그곳에서도 클클램프 통채로 교환해야한다고 했지만...
 남아있는 나사가 잘 돌아가고 있어 볼트볼트를 주심...
그곳에서는 마지막에 부러진 볼트가 끝까지 나오지 않았음. 안나오면 5천원 주고 맡기면 나사에 1자 홈 만들어 돌려 빼볼 수도 있다고 하심.
 일단 집에서 해보기로  함. 토크랜치도 사려했지만 팁교체가능한 공구가 매장에 없어서 구매는 실패.  그래도 집에 와서 플라이어로 겨우겨우 뽑아네는데 성공하여 수리 완료 !

 190225.
 뒷꿈치로 안장 높이를 다시 확인해 보니 살짝 높은 것 같아 1.5mm정도 낮추고 다시 조이다가... 뚝 끊어져 버림...

2019년 2월 13일 수요일

[Python] Relase Mate 1.13

ld and ref build has the same base, partial diff cannot be done
# v1.12
# - add project feature
# v1.13
# - change project feature

import time
import re

import requests
#from xml.etree.ElementTree import ElementTree as ETR
import xml.etree.ElementTree as ETR
from xml.etree.ElementTree import Element as ET
from xml.etree.ElementTree import parse

import csv

VERSIONINFO = 'Release Mate v1.13'

BUILD_XML = 'build_data.xml'
BUILDINFOXML = 'buildinfo.xml'

QB_URL = 'https://android.qb.sec.samsung.net/rest/'
QB_TOKENRQ = 'https://android.qb.sec.samsung.net/signin?1-1.IFormSubmitListener-form'
QB_CONFPATH = 'ids?configuration_path='
QB_BUILDRQ = 'build_requests'
QB_BUILDS  = 'builds/'

CSVENCODING = 'euc-kr'
INDEXCOL = 1

class QB:
    def __init__(self):
        self.__qb_cookies = dict()

    def qblogin(self, user, password, reflash=False):
        if len(self.__qb_cookies) != 0:
            return self.session, self.__qb_cookies

        token_url = QB_TOKENRQ
        token_data = {'userName': user, 'password': password}
        self.session = requests.session()
        self.session.post(token_url, token_data)
        self.__qb_cookies = requests.utils.dict_from_cookiejar(self.session.cookies)

        if len(self.__qb_cookies) < 3:
            print('### WARNING ### Quickbuild login failed ...\n')

        time.sleep(1)

        return self.session, self.__qb_cookies

    def qb_getconfid(self, path):
        if len(self.__qb_cookies) == 0:
            print('### WARNING ### quickbuild has not been logged ...')
            return 0

        txt = requests.get(QB_URL + QB_CONFPATH + path, cookies=self.__qb_cookies, verify=True).text
        time.sleep(1)

        return txt

    def qb_getbuild(self, bid:str):
        if len(self.__qb_cookies) == 0:
            print('### WARNING ### quickbuild has not been logged ...')
            return 0

        txt = requests.get(QB_URL + QB_BUILDS + bid, cookies=self.__qb_cookies, verify=True).text
# TO REMOVE XML FILE
#        with open(BUILDINFOXML, 'wt', encoding='utf-8') as f:
#            n = f.write(txt)
#        return n
        return txt

    def qb_getclinfo(self, xml):
        base = ''
        partials = ''

# TO REMOVE XML FILE
#        with open(BUILDINFOXML, 'rt', encoding='utf-8') as f:
        if xml != '':
#            tree = parse(BUILDINFOXML)
#            root = tree.getroot()
            root = ETR.fromstring(xml)
            sav = root.find('secretAwareVariableValues')
            entlist = sav.getchildren()
            for ent in entlist:
                l = ent.getchildren()
                if l[0].text == 'CL_SYNC':
                    base = l[1].getchildren()[0].text
                if l[0].text == 'CL_PARTIAL' :
                    sublist = l[1].getchildren()
                    if len(sublist) != 0:
                        partials = l[1].getchildren()[0].text
            if partials is None:
                partials = ''
        return base, partials

    def __qb_entry(self, vname, vval):
        ent = ET('entry')
        name = ET('string')
        name.text = vname
        ent.append(name)
        val = ET('string')
        val.text = vval
        ent.append(val)
        return ent

    def qb_data(self, confid, base, partials, usermode=True, csc=None):
        if type(confid) != str or type(base) != str or (partials != None and type(partials) != str):
            raise TypeError

        breq = ET('com.pmease.quickbuild.BuildRequest')

        cid = ET('configurationId')
        cid.text = confid
        breq.append(cid)

        variables = ET('variables')

        if usermode==True:
            variables.append(self.__qb_entry('DEFAULT_BUILD_MODE', 'USER_BUILD_DEFAULT_OPTIONS'))
        else:
            variables.append(self.__qb_entry('DEFAULT_BUILD_MODE', 'ENG_BUILD_DEFAULT_OPTIONS'))
        variables.append(self.__qb_entry('CL_SYNC', base))
        variables.append(self.__qb_entry('CL_PARTIAL', partials))
        variables.append(self.__qb_entry('CL_SHELVE', ''))
        if csc!=None:
            variables.append(self.__qb_entry('BUILD_CSC', csc))

        breq.append(variables)
# TO REMOVE XML FILE
#        ETR(breq).write(BUILD_XML, encoding='utf-8', method='xml', xml_declaration=True)
        return ETR.tostring(breq)

    def qb_build(self, confid, base, partials, usermode=True):
        qb_header = {'Content-Type': 'text/xml', 'charset': 'utf-8'}
# TO REMOVE XML FILE
#        self.qb_data(confid, base, partials, usermode)
#        rtn = requests.post(QB_URL + QB_BUILDRQ, data=open(BUILD_XML, 'rt', encoding='utf-8').read().replace('\n', ''), cookies=self.__qb_cookies, headers = qb_header)
        xml = self.qb_data(confid, base, partials, usermode)
        rtn = requests.post(QB_URL + QB_BUILDRQ, data=xml, cookies=self.__qb_cookies, headers = qb_header)

        time.sleep(1)

        return rtn

CLLIST = 'cl_list.txt'
CHKCL = 'checkcl.txt'
CLFORM = re.compile(r'\d+')
ENC = 'utf-8'
ENC2 = 'euc-kr'
ENC3 = 'cp949'

#################################################################################

class CL:
    qb = None
    client = ''

    def reset(self):
        self.refmode = 0        # 0 : use base and partial, 1 : user build-id
        self.kormode = 0
        self.depot = ''
        self.rbid = self.cbid = self.pbid = ''
        self.e = self.k = self.a = self.s = self.m = self.orgstr = self.resultstr = self.errmsg = self.basecl = self.qb_base = self.qb_partials = ''
        self.pbase = self.ppartials = ''
        self.pmode = -1         # prev build 저장방식
        self.eurclset = set()
        self.korclset = set()
        self.addclset = set()
        self.subclset = set()
        self.mustset  = set()
        self.diff1 = []
        self.diff2 = []
        self.resultlist = []
        self.mustlist = []
        self.underlist = []
        self.newcllist = []
        self.newlist = []
        self.config = []
        self.confid = dict()

    def setfile(self, fn):
        self.filename = fn

    def __init__(self, qbinst=None, fn=None):
        self.qb = qbinst if qbinst != None else None
        self.setfile(CLLIST if fn==None else fn)
        self.reset()

    def setqb(qbinst):
        self.qb = qbinst

    def str2set(self, cls):
        CL = re.compile(r'\w+')
        clset = set()
        #
        for match in CL.finditer(cls):
            cl = match.group()
            clset.add(cl)
        return clset

    def set2str(self, clset):
        clstr = ''
        for cl in clset:
            clstr += str(cl)
            clstr += ','
        return clstr[:-1]

    def set2str2(self, clset, chkset):
        clstr = ''
        for cl in clset:
            clstr += str(cl)
            if cl in chkset:
                clstr += '*'
            clstr += ','
        return clstr[:-1]

    def __match_comment(self, line):
        temp = re.findall('^\s*#(.*)', line)
        if temp != []:
            return True
        return False

    def __matchcls(self, base, matchstr, line):
        match = False
        temp = re.findall('^\s*'+matchstr+'\s*=', line)
        if len(temp) > 0:
            match = True
        temp = re.findall('^\s*'+matchstr+'\s*=\s*([\d,\s]*)#{0,1}', line)
        if temp != []:
            if base != '':
                base += ','
            base += temp[0].replace(' ','').replace('\n','')
        return match, base

    def __getcls(self):
        self.reset()
        with open(self.filename, mode='rt', encoding='utf-8') as f:
            #
            ln = 0
            while(1):
                line = f.readline()
                ln += 1

                self.orgstr += line
                if line == '' or line[:13] == '# end of data':
                    break

                temp = []
                #
                temp = re.findall('\s*', line)
                if temp[0] == line:
                    continue

                temp = re.findall('^depot\s*=\s*([\w/\-\.]+)', line)
                if temp != []:
                    self.depot = temp[0]
                    continue

                temp = re.findall('^client\s*=\s*([\w\-]+)', line)
                if temp != []:
                    self.client = temp[0]
                    continue

                temp = re.findall('^qb\s*=\s*([\w\-/]+)', line)
                if temp != []:
                    self.config.append(temp[0])
                    continue

                if self.pmode == -1:
                    temp = re.findall('^prev_buildid\s*=\s*([\d]+)', line)                 
                    if temp != []:
                        self.pbid = temp[0]
                        try:
                            xml = self.qb.qb_getbuild(self.pbid)
                            self.pbase, self.ppartials = self.qb.qb_getclinfo(xml)
                        except:
                            print('### ERROR ### Error occured !!! : prev - self.pbase = %s, self.ppartials = %s' % (self.pbase, self.ppartials))

                        self.pmode = 1
                        continue

                    temp = re.findall('^prev_base\s*=\s*([\d]+)', line)
                    if temp != []:
                        self.pbase = temp[0]
                        self.pmode = 0
                        continue

                temp = re.findall('^ref_buildid', line)
                if temp != []:
                    temp = re.findall('^ref_buildid\s*=\s*([\d]+)', line)
                    if temp != []:
                        self.rbid = temp[0]
                        try:
                            xml = self.qb.qb_getbuild(self.rbid)
                            self.basecl, self.e = self.qb.qb_getclinfo(xml)
                        except:
                            print('### ERROR ### Error occured !!! : ref - self.basecl = %s, self.e = %s' % (self.basecl, self.e))

                    self.refmode = 1
                    continue

                temp = re.findall('^cur_buildid', line)
                if temp != []:
                    temp = re.findall('^cur_buildid\s*=\s*([\d]+)', line)
                    if temp != []:
                        self.cbid = temp[0]
                        try:
                            xml = self.qb.qb_getbuild(self.cbid)
                            tempbase, self.k = self.qb.qb_getclinfo(xml)
                        except:
                            print('### ERROR ### Error occured !!! : cur - tempbase = %s, self.k = %s' % (tempbase, self.k))

                        if tempbase != self.basecl:
                            print("### WARNING ### ... current base is not the same one as ref base's ")

                    self.kormode = 1
                    continue

                if(self.refmode == 0):
                    temp = re.findall('^base\s*=\s*([\d]+)', line)
                    if temp != []:
                        self.basecl = temp[0]
                        continue
                #
                match = mt = False

                if self.pmode == 0:
                    mt, self.ppartials = self.__matchcls(self.e, 'prev_partials', line)
                    match |= mt           
                if self.refmode == 0:
                    mt, self.e = self.__matchcls(self.e, 'ref_partials', line)
                    match |= mt
                if self.kormode == 0:
                    mt, self.k = self.__matchcls(self.k, 'cur_partials', line)
                    match |= mt
                mt, self.a = self.__matchcls(self.a, 'add_partials', line)
                match |= mt
                mt, self.s = self.__matchcls(self.s, 'sub_partials', line)
                match |= mt
                mt, self.m = self.__matchcls(self.m, 'must_partials', line)
                match |= mt
                match |= self.__match_comment(line)
                if match == False :
                    print('### ERROR ### Error in line #%d' % ln)
                    self.errmsg += 'Error in line #'
                    self.errmsg += str(ln)
                    self.errmsg += '\n'

                self.eurclset = self.str2set(self.e)
                self.korclset = self.str2set(self.k)
                self.addclset = self.str2set(self.a)
                self.subclset = self.str2set(self.s)
                self.mustset  = self.str2set(self.m)


    def __putcls(self):
        result_str = '------------------------------------------\n' +         \
        self.errmsg                                                      + '\n'    \
        '1. REF - CUR : \n' +                 \
         str([int(x) for x in self.diff1]).replace(', ',',')[1:-1] + '\n\n' +   \
        '2. CUR - REF : (Please check whether to add or not!) \n' + \
         str([int(x) for x in self.diff2]).replace(', ',',')[1:-1] + '\n\n' +   \
        '3. New CL list = REF + ADD CL - SUB CL (' + str(len(self.newcllist)) + ' CLs)\n\n' + 'Base : ' + str(self.basecl) + '\nPartial : \n' +   \
        str([int(x) for x in self.newcllist]).replace(', ',',')[1:-1] + '\n\n' +   \
        '***** CLs below the Base *****\n' +                               \
        str([int(x) for x in self.underlist]).replace(', ',',')[1:-1] + '\n'     
        #
        with open(self.filename, mode='wt+', encoding='utf-8') as f:
            f.write(self.orgstr)
            f.write(result_str)
        return result_str

    def update(self):
        print('########### process CL list "%s" ... ###########' % self.filename)
     
        self.reset()
        self.__getcls()
     
        self.diff1 = list(self.eurclset - self.korclset) # - subclset
        self.diff2 = list(self.korclset - self.eurclset) # - addclset
        self.diff1.sort()
        self.diff2.sort()

        # self.korclset = self.korclset.union(eurclset)
        # self.korclset = self.korclset.union(addclset)
        self.korclset = self.eurclset | self.addclset   # korclset에 넣어둔 CL때문에 잘못 나오는 것이 있어 로직 변경
        self.resultlist = list(self.korclset - self.subclset)
        self.mustlist = list(self.mustset)

        if self.resultlist != '' and self.basecl != '':
            self.underlist = [ x for x in self.resultlist if int(x) < int(self.basecl) ]
            self.newcllist = [ x for x in self.resultlist if int(x) > int(self.basecl) ]

        self.underlist.sort()
        self.newcllist.sort()
        self.mustlist.sort()

        for cl in self.mustlist:
            if cl not in self.newcllist:
                self.newcllist.append(cl)
     
        self.resultstr = self.__putcls()
        print('########## Completed ##########\n')

        # prepare variables to build
        self.qb_base = str(self.basecl)
        self.qb_partials = str([int(x) for x in self.newcllist]).replace(', ',',')[1:-1]

        return self.resultstr

##################################################################

from P4 import P4

CHKCL = 'checkcl.txt'
CLFORM = re.compile(r'\d+')
ENC = 'utf-8'
ENC2 = 'euc-kr'
ENC3 = 'cp949'

def p4con(client, user, password):
    p4 = P4()
    p4.user = user
    p4.password = password
    p4.port = '165.213.202.46:1716'
    p4.client = client

    p4.connect()
    p4.run_login()

    return p4

def p4discon(p4):
    p4.disconnect()

# p4_run_changes()

def readfile():
    cllist = []
    with open(CHKCL, mode='r', encoding=ENC) as f:
        orgfile = ''
        while(1):
            line = f.readline()
            orgfile += line
            if line == '' or line[:13] == '# end of data':
                break
            cls = re.findall(CLFORM, line)
            for cl in cls:
                cllist.append(int(cl))
    return cllist, orgfile

def getchginfo(p4, cl):
    # i = p4.fetch_change(cl)
    i = p4.run('describe', cl)

    info = ''
    info += '=======================================================\n'
    info += '- CL ' + str(i[0].get('change')) + ', DATE ' + i[0].get('time') + ', User : ' + i[0].get('user') + '\n'
    info += '-------------------------------------\n'
    info += '- Description : \n'
    info += i[0].get('desc')
    info += '-------------------------------------\n'
    files = i[0].get('depotFile')
    if files :
        info += '- Files : ' + str(len(files)) + ' file(s)\n'
        for f in files:
            info += f
            info += '\n'
    info += '\n'
    return info

def getinfo(p4, cllist):
    info = ''
    for cl in cllist:
        info += getchginfo(p4, cl)
    return info

def writefile(orgstr, newstr):
    with open(CHKCL, mode='w', encoding=ENC) as f:
        f.write(orgstr)
        f.write(newstr)

def viewcls(client, user, password):
    cllist, orgstr = readfile()

    try:
        p4 = p4con(client, user, password)
        info = getinfo(p4, cllist)
        writefile(orgstr, info)

        p4discon(p4)
    except:
        for e in p4.errors:
            print('### ERROR ###')
            print(e)

def viewcl(client, user, password, cl):
    info = ''

    try:
        p4 = p4con(client, user, password)
        info = getchginfo(p4, cl)
        p4discon(p4)
    except:
        for e in p4.errors:
            print('### ERROR ###')
            print(e)

    return info

def yesno(str):
    while True:
        resp = input(str)
        resp = re.findall(r'(\w)', resp)
        if len(resp) == 0:
            continue
        resp = [x.lower() for x in resp]
        break

    print('')
    if resp[0] != 'y':
        return 0
    return 1

##################################################################

class Release:
    def __init__(self, qb=None):
        filechecked = False
        while True:
            self.project = input('Enter Project Name : ').strip()

            if self.project != '':
                cllistfn = 'cl_list_' + self.project + '.txt'
            else:
                cllistfn = CLLIST
            try:
                with open(cllistfn, 'rt'):
                    filechecked = True
            except:
                print('### Warning ### File not found : %s' % cllistfn)

            if filechecked == True:
                print('===> OK!, File checked !!!\n')
                break

        self.cllistfn = cllistfn
        self.qb = QB() if qb == None else qb
        self.cl = CL(self.qb, cllistfn)
        self.csvin = 'in.csv'
        self.csvout = 'out.csv'
 
    def update(self):
        return self.cl.update()

    def build(self, target='all'):
        if len(self.cl.config) == 0:
            print('### WARNING ### Threre is no configurations to build ...\n')
            return
        print('Builds ... (base : %s, partials : %s)' % (self.cl.qb_base, self.cl.qb_partials))
        for x in self.cl.config:
            print('   Triggering build for %s ... ' % x)       
            cid = self.cl.confid.get(x, self.qb.qb_getconfid(x))
            if target=='user':
                self.qb.qb_build(cid, self.cl.qb_base, self.cl.qb_partials, True)
            if target=='eng' :
                self.qb.qb_build(cid, self.cl.qb_base, self.cl.qb_partials, False)
            if target=='all' :
                self.qb.qb_build(cid, self.cl.qb_base, self.cl.qb_partials, True)
                time.sleep(2)
                self.qb.qb_build(cid, self.cl.qb_base, self.cl.qb_partials, False)
            print('   Finished ...\n')       
            time.sleep(2)

    def build_check(self):
        print('Build check ... (base : %s, partials : %s)' % (self.cl.qb_base, self.cl.qb_partials))
        print('Build configurations are ...')
        for x in self.cl.config:
            print('- %s' % x)       
        print('\n')

    def getNewCL(self, client, user, password):
        if self.cl.pmode == -1:
            print('### WARNING ### You must assign previous build-id.\n')
            return []

        try:
            p4 = p4con(client, user, password)

            relcls = []
            print('   Checking new cls between two builds for depot : %s' %  self.cl.depot)
            print('   self.cl.pbase = %s, self.cl.qb_base = %s' % (self.cl.pbase, self.cl.qb_base))

            if self.cl.pbase == self.cl.qb_base:
                # partial 추가된 것만 뽑기
                print('   two builds have the same base, check partials...')
                qb_p = [x.strip() for x in self.cl.qb_partials.split(',')]
                p_p = [x.strip() for x in self.cl.ppartials.split(',')]
                relcls = sorted(list(set(qb_p)-set(p_p)))
            else:
                # base 사이에 추가된 것 뽑기
                added = p4.run('changes', '-ssubmitted', self.cl.depot+'@'+self.cl.pbase+','+self.cl.qb_base)
                for x in added:
                    cl = x.get('change')
                    # 이전 partial에 포함된 것은 빼기
                    if cl in self.cl.ppartials:
                        continue
                    relcls.append(cl)       
                # 이번 partial에 추가된 것은 더하기
                addcls = self.cl.qb_partials.split(',')
                if len(addcls) == 1 and addcls[0] != '':
                    relcls += addcls
                # 중복된 것 삭제
                relcls = list(set(relcls))
                relcls = sorted(relcls)

            p4discon(p4)
        except:
            print('### ERROR ###   Something wrong ... ')
            for e in p4.errors:
                print(e)

        return relcls

    def REL2FLUMEN(self, client, user, password, relcls):
        resultlist = []
        resultstr = ''
        chg = r'\*+\sCherry-picking\s([\d]+)'
        flm = r'/FLUMEN/'
        resultdict = dict()

        try:
            p4 = p4con(client, user, password)
            for relcl in relcls:
                p4cl = p4.run('describe', relcl)
                if len(p4cl) == 0:
                    errstr = '   @........ -> @???????? : cannot find' + relcl
                    resultstr = resultstr + errstr + '\n'
                    print(errstr)
                    continue
                fcl = re.findall(chg, p4cl[0].get('desc'))
                if len(fcl) == 0:
                    errstr = '   @........ -> @' + relcl + ' : cannot process description for ' + relcl
                    resultstr = resultstr + errstr + '\n'
                    print(errstr)
                    continue
                p4fcl = p4.run('describe', fcl[0])
                if len(p4fcl) == 0:
                    errstr = '   @???????? -> @' + relcl + ' : Cannot find cherry picked cl ' + fcl[0] + ' for org cl ' + relcl
                    resultstr = resultstr + errstr + '\n'
                    print(errstr)
                    continue
             
                depotfiles = p4fcl[0].get('depotFile')
                chkflm = False
                for x in depotfiles:
                    if len(re.findall(flm, x)) > 0:
                        chkflm = True

                if chkflm != True:
                    errstr = '   @' + fcl[0] + ' -> @' + relcl + ' : Found a cherry picked cl! But not FLUMEN'
                    resultstr = resultstr + errstr + '\n'
                    print(errstr)
                    continue

                errstr = '   @' + fcl[0] + ' -> @' + relcl
                resultstr = resultstr + errstr + '\n'
                print(errstr)
             
                resultlist.append((fcl[0], relcl))

            resultdict = dict(resultlist)

            p4discon(p4) 
        except:
            for e in p4.errors:
                print('### ERROR ###')
                print(e)

        return (resultstr, resultdict)

    def checkNewCL(self, client, user, password):
        resultstr = ''
        relcls = self.getNewCL(client, user, password)

        if len(relcls) <= 0:
            print('### WARNING ### There is nothing new or failed to obtain new cls due to unknown errors.\n')
            return '', dict()

        resultlist = []
        if yesno('Do you wanna convert REL CLs into FLUMEN CLs ? : ') == 0:
            print('Newly added CLs are ...')
            for x in relcls:
                print('@' + str(x))
                resultstr = resultstr + '@' + str(x) + '\n'
                resultlist.append((str(x), ''))
                resultdict = dict(resultlist)
            return (resultstr, resultdict)

        return self.REL2FLUMEN(client, user, password, relcls)
 
    def updateCSV(self, clmap):     
        with open(self.csvin, 'rt') as i:
            with open(self.csvout, 'wt') as o:
                cr = csv.reader(i)
                cw = csv.writer(o)

                orglist = []
                newlist = []
                for x in cr:
                    orglist.append(x)

                titlefound = False
                titlepass = False
                for x in orglist:
                    newitem = []
                    lval = ''               
                    for i in range(len(x)):
                        newitem.append(x[i])
                        if i == INDEXCOL:                       
                            if x[0] == 'NO':
                                newitem.append('Release CL')
                                titlefound = True
                            else:
                                lval = clmap.get(str(x[i]), '')
                                newitem.append(lval)

                    if titlepass == False or lval != '':
                        newlist.append(newitem)
                        if titlefound == True:
                            titlepass = True

                cw.writerows(newlist)


##################################################################

# release = Release()

# update = lambda : release.u()
# build = lambda : release.b()

##################################################################

class ReleaseUI:
    user = ''
    password = ''

    def __qblogin(self):
        if self.user == '' or self.password == '':
           print('### WARNING ### You should enter login information agian.\nMenu login finished.')

        print('Quickbuild log-in ...\n')
        self.release.qb.qblogin(self.user, self.password)

    def doLogin(self):
        if self.user == '':
            self.user = input('userName cannot be null.\nPlease enter userName : ')
        if self.password == '':
            self.password = input('password cannot be null.\nPlease enter password : ')

        self.__qblogin()

    def doReLogin(self):
        self.user = input('Please enter userName : ')
        self.password = input('Please tner password : ')
        self.doLogin()

    def __printVer(self):
        print(VERSIONINFO + '\n' + '-'*30 + '\n')

    def __init__(self):
        self.__printVer()
        self.qb = QB()
        self.release = Release(self.qb)
        self.doReLogin()

    def doNewProject(self):
        self.release = Release(self.qb)

    def doUpdate(self):
        print(self.release.update())

    def doBuild(self, target='all'):
        if target == 'all' or target == 'user' or target == 'eng':
            self.release.build(target)
        else:
            print('### WARNING ### Cannot recognize build option : %s' % target)

    def doCheckBuild(self, target='all'):
        self.release.build_check()

    def doCheckCL(self):
        viewcls(self.release.cl.client, self.user, self.password)
        print('CL info has been updated ...\n')

    def doCheckNewCL(self):
        resultstr, clmap = self.release.checkNewCL(self.release.cl.client, self.user, self.password)
        with open(self.release.cllistfn, 'wt', encoding=ENC) as f:
            f.write(self.release.cl.orgstr)
            f.write(self.release.cl.resultstr)
            f.write('\n' + '\n****** Newly append CLs are ... ******\n\n')
            f.write(resultstr)
            f.write('\n')

        if len(clmap) == 0:
            return

        try:
            self.release.updateCSV(clmap)
        except:
            print("### WARNING ### Something happened while updating Release CLs with CSV...")

    def doHelp(self):
        self.__printVer()
        print('Please be sure to place "cl_list.txt" at the same folder with this Program !!! \n')
        print('commands')
        print('- help or ? : this screen')
        print('- update : update cl_list.txt')
        print('- login  : log on Quickbuild server')
        print('- relogin  : log on Quickbuild server with new user and password')
        print('- build  : build with respect to the CLs on cl_list.txt')
        print('           build or build all - build user and eng binary')
        print('           build user         - build user binary')
        print('           build eng          - build eng binary')
        print('           to use this, you should login on QB server')
        print('- newbuild : same as what "build" does.')
        print('             But "update" will be performed before build is processed')
        print('- check build : display parameters when build command is performed')
        print('        newcl : check newly added cl w.r.t the previous build ')
        print('                to use this, ')
        print('                prev_buildid or prev_base and prev_partials should be provided')
        print('                and log on P4 server \( assume that P4 user info is the same as QB \) ')
        print('- newprj : change project')
        print('- exit   : Exit from menu')
        print('')

    def __call__(self):
#  나중에... commands와 sub-commands 처리 routine화 시키기 ...
#        commands = {'update': self.doUpdate, 'login' : self.doLogin, 'relogin' : self.doReLogin,
#                    'help' : self.doHelp, '?' : self.doHelp }
        while True:
            prompt = '[' + self.release.project + ']' + ' Enter commands ? '
            instr = input(prompt)
            command = re.findall(r'([\w]+|\?)', instr)
            cmd = [x.lower() for x in command]
            if len(cmd) == 0:
                continue

            if cmd[0] == 'newprj':
                self.doNewProject()
            elif cmd[0] == 'update':
                self.doUpdate()
            elif cmd[0] == 'login':
                self.doLogin()
            elif cmd[0] == 'relogin':
                self.doReLogin()
            elif cmd[0] == 'build' :
                if len(cmd) > 1:
                    self.doBuild(target=cmd[1])
                else:
                    self.doBuild()
            elif cmd[0] == 'newbuild' :
                self.doUpdate()
                if yesno('=> Wanna build ? (Y/N) : ') != 0:
                    continue

                if len(cmd) > 1:
                    self.doBuild(target=cmd[1])
                else:
                    self.doBuild()
            elif cmd[0] == 'check' :
                if len(cmd) > 1:
                    if cmd[1] == 'cl':
                        self.doCheckCL()
                    elif cmd[1] == 'build':
                        self.doCheckBuild()
                    elif cmd[1] == 'newcl':
                        self.doCheckNewCL()
            elif cmd[0] == 'help' or cmd[0] == '?':
                self.doHelp()
            elif cmd[0] == 'exit':
                break;
            else:
                print('Invalid command : %s' % command[0])

if __name__ == '__main__':
    ReleaseUI()()

200926.가오리코스 라이딩

9/26 골절인지 아닌지 확인 안됨. 이후 미세골절여부 확인 핸드폰을 드는 것도 어려움 9/29 x ray 다시 찍지 않고 이후 재 방문 요청 ...