Esempio n. 1
0
def tracking(request,rng):
    frto = rng.split(':') ; narr=[]
    for tel in frto:
        otel = tel
        if tel=='lastmonth': tel = (datetime.datetime.now()-datetime.timedelta(days=30)).strftime('%Y-%m-%d')
        if tel=='lastweek': tel = (datetime.datetime.now()-datetime.timedelta(days=7)).strftime('%Y-%m-%d')
        if tel=='yesterday': tel = (datetime.datetime.now()-datetime.timedelta(days=1)).strftime('%Y-%m-%d')
        if tel=='today': tel = (datetime.datetime.now()).strftime('%Y-%m-%d')
        narr.append(tel)
    frto = narr

    st,op = gso("find %s -type f -iname 'hours.json'"%cfg.DATADIR) ; assert st==0
    fnames = op.split("\n")
    sums={} ; tasksums={} ; tdescrs = {} ; testimates = {}
    for fn in fnames:
        tid = os.path.dirname(fn).replace(cfg.DATADIR+'/','')
        with open(fn,'r') as f: j = json.loads(f.read())
        matching = filter(lambda x: x[0]>=frto[0] and x[0]<=frto[1],j.items())
        for dt,data in matching:
            for person,hrs in data.items():
                sums[person] = sums.get(person,0)+hrs
                if person not in tasksums: tasksums[person]={}
                tasksums[person][tid] = tasksums[person].get(tid,0)+hrs
                t = get_task(tid)
                if tid not in tdescrs: tdescrs[tid] = t['summary']
                metastates,content = read_current_metastates(t,True)

                if t.get('total_hours') and metastates.get('work estimate'):
                    remaining_hours = '%4.2f'%(float(metastates.get('work estimate')['value']) - float(t.get('total_hours')))
                else:
                    remaining_hours = '--'
                testimates[tid]=remaining_hours

    sums = sums.items()
    sums.sort(lambda x,y: cmp(x[1],y[1]),reverse=True)
    return {'fr':frto[0],'to':frto[1],'tracked':sums,'tasksums':tasksums,'tdescrs':tdescrs,'testimates':testimates}
def task(request,P,C,task,rev=None):
    # fetch_stamp is a hidden form input used to protect task updates against overwrite by older forms of the task submitted
    fstamp = request.params.get('changed_at')
    if fstamp and fstamp!='None': fstamp = datetime.datetime.strptime( fstamp, "%Y-%m-%d %H:%M:%S.%f" )
    else: fstamp=None

    now = datetime.datetime.now()
    if task.endswith('/'): task=task[0:-1]
    gwu = cfg.GITWEB_URL
    if task.startswith('new/'):
        under='/'.join(task.split('/')[1:])
        task='new'
    else:
        under=None
    msg=None
    adm = get_admin(request,'unknown')
    repos = get_repos(C)
    usernames = get_usernames(C)

    tags=[] ; links=[] ; informed=[] ; branches=[] ;
    cross_links_raw = get_cross_links(C,task)
    cross_links=[]
    dependencies=[]
    for k,v in list(request.params.items()):
        if k.startswith('tag-'):
            tn = k.replace('tag-','')
            if tn=='new':
                for nt in [nt.strip() for nt in v.split(',') if nt.strip()!='']:
                    tags.append(nt)
            else:
                tags.append(tn)
        if k.startswith('link-'):
            tn = k.replace('link-','')
            if tn in ['new-url','new-anchor']:
                continue #raise Exception('newlink')
            else:
                links.append({'url':v,'anchor':tn})
        if k.startswith('informed-'):
            tn = k.replace('informed-','')
            if tn=='new': continue
            informed.append(tn)
        if k.startswith('branches-'):
            tn = k.replace('branches-','')
            if tn in ['new-repo','new-branch']: continue
            branches.append(tn)
        if k.startswith('cross_link-'):
            cln = k.replace('cross_link-','')
            cross_links.append(cln)
            #print('adding cross_link',cln,'due to',k,v)
        if k.startswith('dependency-'):
            dln = k.replace('dependency-','')
            dependencies.append(dln)
    lna = request.params.get('link-new-anchor')
    lnu = request.params.get('link-new-url')
    ncl = request.params.get('add-cross_link')
    ndl = request.params.get('add-dependency')

    if task and task!='new':
        karma = getattr(get_task(C,task),'karma',{})
    else:
        karma = {}

    nkarma = request.params.get('karma-new')
    if nkarma:
        kdt = datetime.datetime.now().date().strftime('%Y-%m-%d')
        nkarmaval = request.params.get('karma-plus') and 1 or -1
        # find out what's our expense for today
        mykarma = sum([k['value'][1] for k in get_karma(C,kdt,adm)])
        if (nkarmaval>0 and mykarma<cfg.KARMA_POINTS_PER_DAY) or nkarmaval<0:
            if kdt not in karma: karma[kdt]={}
            if adm not in karma[kdt]: karma[kdt][adm]={}
            if nkarma not in karma[kdt][adm]: karma[kdt][adm][nkarma]=0
            newval = karma[kdt][adm][nkarma]+nkarmaval
            if newval>=0: karma[kdt][adm][nkarma]=newval

    if ncl:
        for ncli in ncl.split(','):
            cross_links.append(ncli)
    if ndl:
        for ndli in ndl.split(','):
            dependencies.append(ndli)

    if lna and lnu:
        links.append({'anchor':lna,'url':lnu})

    inn = request.params.get('informed-new')
    if inn and inn not in informed:
        informed.append(inn)

    nrb = request.params.get('branches-new-branch','')
    assert '/' not in nrb,"branch name may not contain '/'"
    if nrb: branches.append(request.params.get('branches-new-repo')+'/'+nrb)


    tags = list(set([tag for tag in tags if tag!='']))

    uns = request.params.get('unstructured','').strip()
    if len(uns) and not uns.startswith('**'):
        uns='** Details\n'+uns
    assignees=[request.params.get('assignee')]

    if request.params.get('id') and request.params.get('id')!='None':
        t = get_task(C,request.params.get('id'))
        assignees.append(t.assignee)
        tid = request.params.get('id')
        o_params = {'summary':request.params.get('summary'),
                    'karma':dict(karma),
                    'tags':tags,
                    'status':request.params.get('status'),
                    'assignee':request.params.get('assignee'),
                    'handled_by':request.params.get('handled_by'),
                    'unstructured':uns,
                    'links':links,
                    'cross_links_raw':request.params.get('cross_links'),
                    'cross_links':cross_links,
                    'dependencies':dependencies,
                    'informed':informed,
                    'branches':branches}
        print(o_params)
        rewrite(P,C,tid,o_params,safe=False,user=adm,fetch_stamp=fstamp)
        t = get_task(C,tid)
        cross_links_raw = get_cross_links(C,tid)
        if request.params.get('content-journal'):
            tj = get_task(C,task)
            metastates={}
            append_journal_entry(P,C,tj,adm,request.params.get('content-journal'),metastates)
        assert request.params.get('id')



    if request.params.get('create'):
        o_params = {'summary':request.params.get('summary'),
                    'status':request.params.get('status'),
                    'assignee':request.params.get('assignee'),
                    'creator':get_admin(request,'unknown'),
                    'handled_by':request.params.get('handled_by'),
                    'unstructured':uns,
                    'links':links,
                    'informed':informed,
                    'branches':branches}
        if request.params.get('under'):
            parent = request.params.get('under')
        else:
            parent=None
        rt = add_task(P,C,parent=parent,params=o_params,tags=tags,user=adm)
        redir = '/'+URL_PREFIX+rt._id
        print('redircting to %s'%redir)
        rd = Redirect(redir)
        return rd
    if task=='new':
        ch=[]
    else:
        #raise Exception('eff off',task)
        #print('getting children')
        ch = get_children(C,task)
        sortmode = request.params.get('sortby','default')
        ch.sort(key=cmp_to_key(sortmodes[sortmode]),reverse=True)
        print(('got',len(ch),'kids'))

    if task=='new':
        t = Task(created_at=None,
                 summary='',
                 unstructured='',
                 status='TODO',
                 assignee=adm,
                 creator=adm,
                 tags=[],
                 links=[],
                 branches=[],
                 karma={},
                 journal=[])
        opar=[]
        gantt_labels={} ; gantt={}
        changed_at=None
    else:
        gantt_labels,gantt = gantt_info(C,task)
        C.execute("select changed_at from tasks where id=%s",(task,))
        fo = C.fetchone()
        if fo:
            changed_at = fo['changed_at']
        else:
            changed_at = None
        if rev:
            t = Task.get_rev(C,task,rev)
        else:
            t = get_task(C,task)
        par = task ; parents=[]
        parents = task.split('/')
        opar = []
        for i in range(len(parents)-1):
            opar.append('/'.join(parents[:i+1]))
    parents = [(pid,get_task(C,pid)['summary']) for pid in opar]
    prt = get_usernames(C)
    metastates,content = read_current_metastates(t,True)
    zerodelta = datetime.timedelta(seconds=0)
    if gantt.get('t') and gantt.get('we'):
        remaining_hours = gantt.get('we')-gantt.get('t')
    else:
        remaining_hours=zerodelta
    #journal
    jitems = t.journal
    dependencies = getattr(t,'dependencies',[])
    branchtargets=[(re.compile("pre"),"preproduction"),
                   (re.compile("prod"),"production"),
                   (re.compile(".*"),"staging")]
    btgts={}
    for br in t.branches:
        for ptn,tgt in branchtargets:
            ptnres = ptn.search(br.split("/")[1])
            #print 'ptnres of',br,'in',tgt,'is',ptnres
            if ptnres: 
                if tgt not in btgts: btgts[tgt]=[]
                btgts[tgt].append(br)
                break

    C.execute("select * from tasks_pri_comb_lean where id=%s",(task,))
    pri = C.fetchall()
    if len(pri):
        pr = pri[0]
        pri = pr['tot_pri']
        dep_pri = pr['dep_pri']
    else:
        pri=0
        dep_pri=0

    C.execute("select depid,path_info from tasks_deps_hierarchy where tid=%s",(t._id,))
    fulldeps = [d for d in C.fetchall() if d['depid'] not in dependencies]
    C.execute("select tid,path_info from tasks_deps_hierarchy where depid=%s",(t._id,))
    dependants = [d for d in C.fetchall()]
    tup = tuple(cross_links_raw+
                [d['tid'] for d in dependants]+
                [d for d in dependencies]+
                [fd['depid'] for fd in fulldeps])
    if len(tup):
        C.execute("select id id,contents->>'summary' summary from tasks where id in %s",(tup,))
        summaries = dict([(r['id'],r['summary']) for r in C.fetchall()])
    else:
        summaries={}

    return basevars(request,P,C,{'task':t,
                                 'rev':rev,
                                 'changed_at':changed_at,
                                 'pri':pri,
                                 'dep_pri':dep_pri,
                                 'gantt':gantt,
                                 'gantt_labels':gantt_labels,
                                 'zerodelta':zerodelta,
                                 'branches_by_target':btgts,
                                 'summaries':summaries,
                                 'cross_links':cross_links_raw,
                                 'dependencies':dependencies,
                                 'fulldeps':fulldeps,
                                 'dependants':dependants,
                                 'remaining_hours':remaining_hours,
                                 'total_hours':0,
                                 'j':{'%s existing entries'%t._id:jitems},
                                 'gwu':gwu,
                                 'url':RENDER_URL,
                                 'statuses':STATUSES,
                                 'participants':prt,
                                 'usernames':usernames,
                                 'msg':msg,
                                 'children':ch,
                                 'repos':repos,
                                 'parents':parents,
                                 'request':request,
                                 'metastates':metastates,
                                 'possible_metastates':cfg.METASTATES,
                                 'colors':cfg.METASTATES_COLORS,
                                 'overrides':cfg.METASTATES_OVERRIDES,
                                 'karma_per_day':cfg.KARMA_POINTS_PER_DAY,
                                 'diff_branches':cfg.DIFF_BRANCHES,
                                 'under':under,
                                 'humanize':humanize,
                                 'now':now,
                                 'reduce':reduce,
    })
def queue(request,P,C,assignee=None,archive=False,metastate_group='merge'):
    #print('queue()')
    if assignee=='me':
        assignee=get_admin(request,'unknown')
    queue={}
    #print('get_journals()')
    gj = get_journals(P,C,
                      assignee=assignee,
                      metastate_group=metastate_group,
                    archive=archive
    )
    for tj in gj:
        t = tj['contents']
        tid = t['_id']
        #print('going over task',tid)
        cm,content = read_current_metastates(tj['contents'],True)

        #skip this task if has no metastates relevant to us
        relevant_metastates=False
        for cmk in cm:
            if cmk in cfg.METASTATES[metastate_group]:
                relevant_metastates=True
                break
        if not relevant_metastates: continue
        #print 'reading journal'
        jitems = read_journal(t)
        lupd = sorted(list(cm.values()),key=lambda x:x['updated'],reverse=True)
        if len(lupd): lupd=lupd[0]['updated']
        else: lupd=None
        #any journal update takes precedence
        if len(jitems):
            try:
                jlupd = jitems[-1]['created_at']
            except:
                raise Exception(jitems[-1])
            if not lupd or jlupd >=lupd:
                lupd = jlupd
        #assert t.get('total_hours')!='None'
        #print 'adding to queue'
        queue[tid]={'states':dict([(cmk,cmv['value']) for cmk,cmv in list(cm.items())]),
                    #'total_hours':t.get('total_hours',0),
                    'fullstates':cm,
                    'last updated':lupd,
                    'status':t['status'],
                    'summary':t['summary'],
                    'last entry':content,
                    'tags':t['tags'],
                    'assignee':t['assignee'],
                    'merge':[l['url'] for l in t['links'] if l['anchor']=='merge doc'],
                    'job':[l['url'] for l in t['links'] if l['anchor']=='job'],
                    'specs':[l['url'] for l in t['links'] if l['anchor']=='specs']}
    queue = list(queue.items())
    qsort = cmp_to_key(
        lambda x1,x2: 
        cmp((x1[1]['last updated'] and datetime.datetime.strptime(x1[1]['last updated'].split('.')[0],iso_dfmt) or datetime.datetime(year=1970,day=1,month=1)),
        (x2[1]['last updated'] and datetime.datetime.strptime(x2[1]['last updated'].split('.')[0],iso_dfmt) or datetime.datetime(year=1970,day=1,month=1))))
    queue.sort(key=qsort,reverse=True)


    metastate_url_prefix = dict (list(zip(list(cfg.METASTATE_URLS.values()),list(cfg.METASTATE_URLS.keys()))))[metastate_group]
    #print('rendering')
    return basevars(request,P,C,{'queue':queue,
            'metastate_group':metastate_group,
            'metastate_url_prefix':metastate_url_prefix,
            'metastates':METASTATES,
            'colors':cfg.METASTATES_COLORS,
            'overrides':cfg.METASTATES_OVERRIDES})
Esempio n. 4
0
def queue(request,assignee=None,archive=False,metastate_group='merge'):
    if assignee=='me':
        assignee=get_admin(request,'unknown')
    queue={}
    print 'cycling journals'
    for t in get_journals():
        if assignee and t.assignee!=assignee: continue

        if metastate_group!='production':
            if not archive and t['status'] in cfg.DONESTATES: continue
            elif archive and t['status'] not in cfg.DONESTATES: continue

        tid = t._id
        #print t
        assert t.status,"could not get status for %s"%tid
        #print 'reading metastates'
        cm,content = read_current_metastates(t,True)

        #skip this task if has no metastates relevant to us
        relevant_metastates=False
        for cmk in cm:
            if cmk in cfg.METASTATES[metastate_group]:
                relevant_metastates=True
                break
        if not relevant_metastates: continue
        print 'reading journal'
        jitems = read_journal(t)
        lupd = sorted(cm.values(),lambda x1,x2: cmp(x1['updated'],x2['updated']),reverse=True)
        if len(lupd): lupd=lupd[0]['updated']
        else: lupd=None
        #any journal update takes precedence
        if len(jitems):
            try:
                jlupd = jitems[-1]['created_at']
            except:
                raise Exception(jitems[-1])
            if not lupd or jlupd >=lupd:
                lupd = jlupd
        #assert t.get('total_hours')!='None'
        print 'adding to queue'
        queue[tid]={'states':dict([(cmk,cmv['value']) for cmk,cmv in cm.items()]),
                    #'total_hours':t.get('total_hours',0),
                    'fullstates':cm,
                    'last updated':lupd,
                    'status':t['status'],
                    'summary':t['summary'],
                    'last entry':content,
                    'tags':t['tags'],
                    'assignee':t.assignee,
                    'merge':[l['url'] for l in t.links if l['anchor']=='merge doc'],
                    'job':[l['url'] for l in t.links if l['anchor']=='job'],
                    'specs':[l['url'] for l in t.links if l['anchor']=='specs']}
    print 'done. itemizing'
    queue = queue.items()
    print 'sorting'
    queue.sort(lambda x1,x2: cmp((x1[1]['last updated'] and x1[1]['last updated'] or datetime.datetime(year=1970,day=1,month=1)),(x2[1]['last updated'] and x2[1]['last updated'] or datetime.datetime(year=1970,day=1,month=1))),reverse=True)


    metastate_url_prefix = dict (zip(cfg.METASTATE_URLS.values(),cfg.METASTATE_URLS.keys()))[metastate_group]
    print 'rendering'
    return {'queue':queue,
            'metastate_group':metastate_group,
            'metastate_url_prefix':metastate_url_prefix,
            'metastates':METASTATES,
            'colors':cfg.METASTATES_COLORS,
            'overrides':cfg.METASTATES_OVERRIDES}
Esempio n. 5
0
def task(request,task):
    if task.endswith('/'): task=task[0:-1]
    gwu = cfg.GITWEB_URL
    if task.startswith('new/'):
        under='/'.join(task.split('/')[1:])
        task='new'
    else:
        under=None
    msg=None
    adm = get_admin(request,'unknown')
    repos = [r['Name'] for r in get_table_contents(os.path.join(cfg.DATADIR,'repos.org')) if r.get('Name')]

    tags=[] ; links=[] ; informed=[] ; branches=[]
    for k,v in request.params.items():
        if k.startswith('tag-'):
            tn = k.replace('tag-','')
            if tn=='new':
                for nt in [nt.strip() for nt in v.split(',') if nt.strip()!='']:
                    tags.append(nt)
            else:
                tags.append(tn)
        if k.startswith('link-'):
            tn = k.replace('link-','')
            if tn in ['new-url','new-anchor']:
                continue #raise Exception('newlink')
            else:
                links.append({'url':v,'anchor':unicode(tn,'utf-8')})
        if k.startswith('informed-'):
            tn = k.replace('informed-','')
            if tn=='new': continue
            informed.append(tn)
        if k.startswith('branches-'):
            tn = k.replace('branches-','')
            if tn in ['new-repo','new-branch']: continue
            branches.append(tn)
    lna = request.params.get('link-new-anchor')
    lnu = request.params.get('link-new-url')

    if lna and lnu:
        links.append({'anchor':lna,'url':lnu})

    inn = request.params.get('informed-new')
    if inn and inn not in informed:
        informed.append(inn)

    nrb = request.params.get('branches-new-branch','')
    assert '/' not in nrb,"branch name may not contain '/'"
    if nrb: branches.append(request.params.get('branches-new-repo')+'/'+nrb)


    tags = list(set([tag for tag in tags if tag!='']))

    uns = request.params.get('unstructured','').strip()
    if len(uns) and not uns.startswith('**'):
        uns='** Details\n'+uns
    assignees=[request.params.get('assignee')]

    if request.params.get('id') and request.params.get('id')!='None':
        t = get_task(request.params.get('id'))
        assignees.append(t.assignee)
        tid = request.params.get('id')
        o_params = {'summary':request.params.get('summary'),
                    'tags':tags,
                    'status':request.params.get('status'),
                    'assignee':request.params.get('assignee'),
                    'unstructured':uns,
                    'links':links,
                    'informed':informed,
                    'branches':branches}
        print o_params
        rewrite(tid,o_params,safe=False,user=adm)
        t = get_task(tid)
        if request.params.get('content-journal'):
            tj = get_task(task)
            metastates={}
            append_journal_entry(tj,adm,request.params.get('content-journal'),metastates)
        assert request.params.get('id')



    if request.params.get('create'):
        o_params = {'summary':request.params.get('summary'),
                    'status':request.params.get('status'),
                    'assignee':request.params.get('assignee'),
                    'creator':get_admin(request,'unknown'),
                    'unstructured':uns,
                    'links':links,
                    'informed':informed,
                    'branches':branches}
        if request.params.get('under'):
            parent = request.params.get('under')
        else:
            parent=None
        rt = add_task(parent=parent,params=o_params,tags=tags,user=adm)
        redir = '/'+URL_PREFIX+rt._id
        print 'redircting to %s'%redir
        rd = Redirect(redir)
        return rd
    if task=='new':
        ch=[]
    else:
        ch = get_children(task)

    if task=='new':
        t = Task(created_at=None,
                 summary='',
                 unstructured='',
                 status='TODO',
                 assignee=adm,
                 creator=adm,
                 tags=[],
                 links=[],
                 branches=[],
                 journal=[])
        opar=[]
    else:
        t = get_task(task)
        par = task ; parents=[]
        parents = task.split('/')
        opar = []
        for i in xrange(len(parents)-1):
            opar.append('/'.join(parents[:i+1]))
    parents = [(pid,get_task(pid)['summary']) for pid in opar]
    prt = [r[0] for r in get_participants(sort=True)]
    metastates,content = read_current_metastates(t,True)

    # if t.get('total_hours') and metastates.get('work estimate'):
    #     remaining_hours = float(metastates.get('work estimate')['value']) - float(t.get('total_hours'))
    # elif t.get('total_hours'):
    #     remaining_hours = -1 * float(t.get('total_hours'))
    # else:
    #     remaining_hours = None
    remaining_hours=None

    #journal
    jitems = t.journal
    return {'task':t,
            'remaining_hours':remaining_hours,
            'total_hours':0,
            'j':{'%s existing entries'%t._id:jitems},
            'gwu':gwu,
            'url':RENDER_URL,
            'statuses':STATUSES,
            'participants':prt,
            'msg':msg,
            'children':ch,
            'repos':repos,
            'parents':parents,
            'request':request,
            'metastates':metastates,
            'possible_metastates':cfg.METASTATES,
            'colors':cfg.METASTATES_COLORS,
            'overrides':cfg.METASTATES_OVERRIDES,
            'diff_branches':cfg.DIFF_BRANCHES,
            'under':under,
    }