From ed745b457d22bcec3af9648e39320f7d6f0fa0a5 Mon Sep 17 00:00:00 2001 From: Ryan Cross Date: Wed, 11 Sep 2013 17:35:10 +0000 Subject: [PATCH] fix bug where concluded BOFs showing in proceedings - Legacy-Id: 6143 --- ietf/secr/proceedings/proc_utils.py | 163 ++++++++++++++-------------- ietf/secr/utils/group.py | 27 +++-- 2 files changed, 95 insertions(+), 95 deletions(-) diff --git a/ietf/secr/proceedings/proc_utils.py b/ietf/secr/proceedings/proc_utils.py index 48de03baf..b191982ca 100644 --- a/ietf/secr/proceedings/proc_utils.py +++ b/ietf/secr/proceedings/proc_utils.py @@ -37,7 +37,7 @@ def mycomp(timeslot): except AttributeError: key = None return key - + def get_progress_stats(sdate,edate): ''' This function takes a date range and produces a dictionary of statistics / objects for use @@ -46,7 +46,7 @@ def get_progress_stats(sdate,edate): data = {} data['sdate'] = sdate data['edate'] = edate - + # Activty Report Section new_docs = Document.objects.filter(type='draft').filter(docevent__type='new_revision', docevent__newrevisiondocevent__rev='00', @@ -61,20 +61,20 @@ def get_progress_stats(sdate,edate): data['updated'] += 1 if updates > 2: data['updated_more'] +=1 - + # calculate total documents updated, not counting new, rev=00 result = set() events = DocEvent.objects.filter(doc__type='draft',time__gte=sdate,time__lte=edate) for e in events.filter(type='new_revision').exclude(newrevisiondocevent__rev='00'): result.add(e.doc) data['total_updated'] = len(result) - + # calculate sent last call data['last_call'] = events.filter(type='sent_last_call').count() - + # calculate approved data['approved'] = events.filter(type='iesg_approved').count() - + # get 4 weeks monday = Meeting.get_ietf_monday() cutoff = monday + datetime.timedelta(days=3) @@ -82,14 +82,14 @@ def get_progress_stats(sdate,edate): ff2_date = cutoff - datetime.timedelta(days=21) ff3_date = cutoff - datetime.timedelta(days=14) ff4_date = cutoff - datetime.timedelta(days=7) - + ff_docs = Document.objects.filter(type='draft').filter(docevent__type='new_revision', docevent__newrevisiondocevent__rev='00', docevent__time__gte=ff1_date, docevent__time__lte=cutoff) ff_new_count = ff_docs.count() ff_new_percent = format(ff_new_count / float(data['new']),'.0%') - + # calculate total documents updated in final four weeks, not counting new, rev=00 result = set() events = DocEvent.objects.filter(doc__type='draft',time__gte=ff1_date,time__lte=cutoff) @@ -97,48 +97,48 @@ def get_progress_stats(sdate,edate): result.add(e.doc) ff_update_count = len(result) ff_update_percent = format(ff_update_count / float(data['total_updated']),'.0%') - + data['ff_new_count'] = ff_new_count data['ff_new_percent'] = ff_new_percent data['ff_update_count'] = ff_update_count data['ff_update_percent'] = ff_update_percent - + # Progress Report Section data['docevents'] = DocEvent.objects.filter(doc__type='draft',time__gte=sdate,time__lte=edate) data['action_events'] = data['docevents'].filter(type='iesg_approved') data['lc_events'] = data['docevents'].filter(type='sent_last_call') - + data['new_groups'] = Group.objects.filter(type='wg', groupevent__changestategroupevent__state='active', groupevent__time__gte=sdate, groupevent__time__lte=edate) - + data['concluded_groups'] = Group.objects.filter(type='wg', groupevent__changestategroupevent__state='conclude', groupevent__time__gte=sdate, groupevent__time__lte=edate) - + data['new_docs'] = Document.objects.filter(type='draft').filter(docevent__type='new_revision', docevent__time__gte=sdate, docevent__time__lte=edate).distinct() - + data['rfcs'] = DocEvent.objects.filter(type='published_rfc', doc__type='draft', time__gte=sdate, time__lte=edate) - + # attach the ftp URL for use in the template for event in data['rfcs']: num = get_rfc_num(event.doc) event.ftp_url = 'ftp://ftp.ietf.org/rfc/rfc%s.txt' % num - + data['counts'] = {'std':data['rfcs'].filter(doc__intended_std_level__in=('ps','ds','std')).count(), 'bcp':data['rfcs'].filter(doc__intended_std_level='bcp').count(), 'exp':data['rfcs'].filter(doc__intended_std_level='exp').count(), 'inf':data['rfcs'].filter(doc__intended_std_level='inf').count()} - + return data - + def write_html(path,content): f = open(path,'w') f.write(content) @@ -156,7 +156,7 @@ def create_interim_directory(): Create static Interim Meeting directory pages that will live in a different URL space than the secretariat Django project ''' - + # produce date sorted output page = 'proceedings.html' meetings = InterimMeeting.objects.order_by('-date') @@ -165,7 +165,7 @@ def create_interim_directory(): f = open(path,'w') f.write(response.content) f.close() - + # produce group sorted output page = 'proceedings-bygroup.html' qs = InterimMeeting.objects.all() @@ -175,7 +175,7 @@ def create_interim_directory(): f = open(path,'w') f.write(response.content) f.close() - + def create_proceedings(meeting, group, is_final=False): ''' This function creates the proceedings html document. It gets called anytime there is an @@ -185,7 +185,7 @@ def create_proceedings(meeting, group, is_final=False): # abort, proceedings from meetings before 79 have a different format, don't overwrite if meeting.type_id == 'ietf' and int(meeting.number) < 79: return - + sessions = Session.objects.filter(meeting=meeting,group=group) if sessions: session = sessions[0] @@ -194,7 +194,7 @@ def create_proceedings(meeting, group, is_final=False): agenda = None minutes = None slides = None - + chairs = group.role_set.filter(name='chair') secretaries = group.role_set.filter(name='secr') if group.parent: # Certain groups like Tools Team do no have a parent @@ -202,7 +202,7 @@ def create_proceedings(meeting, group, is_final=False): else: ads = None tas = group.role_set.filter(name='techadv') - + docs = Document.objects.filter(group=group,type='draft').order_by('time') meeting_root = get_upload_root(meeting) @@ -213,15 +213,15 @@ def create_proceedings(meeting, group, is_final=False): settings.MEDIA_URL, meeting.date.strftime('%Y/%m/%d'), group.acronym) - + # Only do these tasks if we are running official proceedings generation, - # otherwise skip them for expediency. This procedure is called any time meeting + # otherwise skip them for expediency. This procedure is called any time meeting # materials are uploaded/deleted, and we don't want to do all this work each time. - + if is_final: # ---------------------------------------------------------------------- # Find active Drafts and RFCs, copy them to id and rfc directories - + drafts = docs.filter(states__slug='active') for draft in drafts: source = os.path.join(draft.get_file_path(),draft.filename_with_rev()) @@ -234,7 +234,7 @@ def create_proceedings(meeting, group, is_final=False): else: draft.bytes = 0 draft.url = url_root + "id/%s" % draft.filename_with_rev() - + rfcs = docs.filter(states__slug='rfc') for rfc in rfcs: # TODO should use get_file_path() here but is incorrect for rfcs @@ -245,7 +245,7 @@ def create_proceedings(meeting, group, is_final=False): target = os.path.join(meeting_root,'rfc') rfc.rmsg = '' rfc.msg = '' - + if not os.path.exists(target): os.makedirs(target) shutil.copy(source,target) @@ -282,7 +282,7 @@ def create_proceedings(meeting, group, is_final=False): # ---------------------------------------------------------------------- else: drafts = rfcs = bluesheets = None - + # the simplest way to display the charter is to place it in a
 block
     # however, because this forces a fixed-width font, different than the rest of
     # the document we modify the charter by adding replacing linefeeds with 
's @@ -292,8 +292,8 @@ def create_proceedings(meeting, group, is_final=False): else: charter = None ctime = None - - + + # rather than return the response as in a typical view function we save it as the snapshot # proceedings.html response = render_to_response('proceedings/proceedings.html',{ @@ -312,10 +312,10 @@ def create_proceedings(meeting, group, is_final=False): 'minutes': minutes, 'agenda': agenda} ) - + # save proceedings proceedings_path = get_proceedings_path(meeting,group) - + f = open(proceedings_path,'w') f.write(response.content) f.close() @@ -323,7 +323,7 @@ def create_proceedings(meeting, group, is_final=False): os.chmod(proceedings_path, 0664) except OSError: pass - + # rebuild the directory if meeting.type.slug == 'interim': create_interim_directory() @@ -335,20 +335,21 @@ def create_proceedings(meeting, group, is_final=False): def gen_areas(context): meeting = context['meeting'] gmet, gnot = groups_by_session(None,meeting) - + # append proceedings URL for group in gmet + gnot: group.proceedings_url = "%s/proceedings/%s/%s.html" % (settings.MEDIA_URL,meeting.number,group.acronym) - - for (counter,area) in enumerate(context['areas'], start=1): - groups_met = {'wg':filter(lambda a: a.parent==area and a.state.slug!='bof' and a.type_id=='wg',gmet), - 'bof':filter(lambda a: a.parent==area and a.state.slug=='bof' and a.type_id=='wg',gmet), + + for (counter,area) in enumerate(context['areas'], start=1): + groups_met = {'wg':filter(lambda a: a.parent==area and a.state.slug not in ('bof','bof-conc') and a.type_id=='wg',gmet), + 'bof':filter(lambda a: a.parent==area and a.state.slug in ('bof','bof-conc') and a.type_id=='wg',gmet), 'ag':filter(lambda a: a.parent==area and a.type_id=='ag',gmet)} - - groups_not = {'wg':filter(lambda a: a.parent==area and a.state.slug!='bof' and a.type_id=='wg',gnot), + + groups_not = {'wg':filter(lambda a: a.parent==area and a.state.slug not in ('bof','bof-conc') and a.type_id=='wg',gnot), 'bof':filter(lambda a: a.parent==area and a.state.slug=='bof' and a.type_id=='wg',gnot), 'ag':filter(lambda a: a.parent==area and a.type_id=='ag',gnot)} - + + html = render_to_response('proceedings/area.html',{ 'area': area, 'meeting': meeting, @@ -356,63 +357,63 @@ def gen_areas(context): 'groups_not': groups_not, 'index': counter} ) - + path = os.path.join(settings.SECR_PROCEEDINGS_DIR,meeting.number,'%s.html' % area.acronym) write_html(path,html.content) def gen_acknowledgement(context): meeting = context['meeting'] - + html = render_to_response('proceedings/acknowledgement.html',{ 'meeting': meeting} ) - + path = os.path.join(settings.SECR_PROCEEDINGS_DIR,meeting.number,'acknowledgement.html') write_html(path,html.content) - + def gen_agenda(context): meeting = context['meeting'] - + #timeslots, update, meeting, venue, ads, plenaryw_agenda, plenaryt_agenda = agenda_info(meeting.number) timeslots = TimeSlot.objects.filter(meeting=meeting) - + # sort by area:group then time sort1 = sorted(timeslots, key = mycomp) sort2 = sorted(sort1, key = lambda a: a.time) - + html = render_to_response('proceedings/agenda.html',{ 'meeting': meeting, 'timeslots': sort2} ) - + path = os.path.join(settings.SECR_PROCEEDINGS_DIR,meeting.number,'agenda.html') write_html(path,html.content) - + # get the text agenda from datatracker url = 'https://datatracker.ietf.org/meeting/%s/agenda.txt' % meeting.number text = urlopen(url).read() path = os.path.join(settings.SECR_PROCEEDINGS_DIR,meeting.number,'agenda.txt') write_html(path,text) - + def gen_attendees(context): meeting = context['meeting'] - + attendees = Registration.objects.using('ietf' + meeting.number).all().order_by('lname') - + html = render_to_response('proceedings/attendee.html',{ 'meeting': meeting, 'attendees': attendees} ) - + path = os.path.join(settings.SECR_PROCEEDINGS_DIR,meeting.number,'attendee.html') write_html(path,html.content) - + def gen_group_pages(context): meeting = context['meeting'] - + for group in Group.objects.filter(type__in=('wg','ag','rg'), state__in=('bof','proposed','active')): create_proceedings(meeting,group,is_final=True) - + def gen_index(context): index = render_to_response('proceedings/index.html',context) path = os.path.join(settings.SECR_PROCEEDINGS_DIR,context['meeting'].number,'index.html') @@ -421,36 +422,36 @@ def gen_index(context): def gen_irtf(context): meeting = context['meeting'] irtf_chair = Role.objects.filter(group__acronym='irtf',name='chair')[0] - + html = render_to_response('proceedings/irtf.html',{ 'irtf_chair':irtf_chair} ) path = os.path.join(settings.SECR_PROCEEDINGS_DIR,meeting.number,'irtf.html') write_html(path,html.content) - + def gen_overview(context): meeting = context['meeting'] - + ietf_chair = Role.objects.get(group__acronym='ietf',name='chair') ads = Role.objects.filter(group__type='area',group__state='active',name='ad') sorted_ads = sorted(ads, key = lambda a: a.person.name_parts()[3]) - + html = render_to_response('proceedings/overview.html',{ 'meeting': meeting, 'ietf_chair': ietf_chair, 'ads': sorted_ads} ) - + path = os.path.join(settings.SECR_PROCEEDINGS_DIR,meeting.number,'overview.html') write_html(path,html.content) - + def gen_plenaries(context): ''' - This function generates pages for the Plenaries. At meeting 85 the Plenary sessions + This function generates pages for the Plenaries. At meeting 85 the Plenary sessions were combined into one, so we need to handle not finding one of the sessions. ''' meeting = context['meeting'] - + # Administration Plenary try: admin_session = Session.objects.get(meeting=meeting,name__contains='Administration Plenary') @@ -466,7 +467,7 @@ def gen_plenaries(context): write_html(path,admin.content) except Session.DoesNotExist: pass - + # Technical Plenary try: tech_session = Session.objects.get(meeting=meeting,name__contains='Technical Plenary') @@ -482,16 +483,16 @@ def gen_plenaries(context): write_html(path,tech.content) except Session.DoesNotExist: pass - + def gen_progress(context, final=True): ''' This function generates the Progress Report. This report is actually produced twice. First for inclusion in the Admin Plenary, then for the final proceedings. When produced the first - time we want to exclude the headers because they are broken links until all the proceedings + time we want to exclude the headers because they are broken links until all the proceedings are generated. ''' meeting = context['meeting'] - + # proceedings are run sometime after the meeting, so end date = the previous meeting # date and start date = the date of the meeting before that now = datetime.date.today() @@ -501,30 +502,30 @@ def gen_progress(context, final=True): data = get_progress_stats(start_date,end_date) data['meeting'] = meeting data['final'] = final - + html = render_to_response('proceedings/progress.html',data) - + path = os.path.join(settings.SECR_PROCEEDINGS_DIR,meeting.number,'progress-report.html') write_html(path,html.content) - + def gen_research(context): meeting = context['meeting'] gmet, gnot = groups_by_session(None,meeting) - + groups = filter(lambda a: a.type_id=='rg', gmet) - + # append proceedings URL for group in groups: group.proceedings_url = "%s/proceedings/%s/%s.html" % (settings.MEDIA_URL,meeting.number,group.acronym) - + html = render_to_response('proceedings/rg_irtf.html',{ 'meeting': meeting, 'groups': groups} ) - + path = os.path.join(settings.SECR_PROCEEDINGS_DIR,meeting.number,'rg_irtf.html') write_html(path,html.content) - + def gen_training(context): meeting = context['meeting'] timeslots = context['others'] @@ -540,4 +541,4 @@ def gen_training(context): ) path = os.path.join(settings.SECR_PROCEEDINGS_DIR,meeting.number,'train-%s.html' % counter ) write_html(path,html.content) - + diff --git a/ietf/secr/utils/group.py b/ietf/secr/utils/group.py index 7c8f4f520..e3d2afda5 100644 --- a/ietf/secr/utils/group.py +++ b/ietf/secr/utils/group.py @@ -20,9 +20,9 @@ def get_charter_text(group): f = file(path,'r') text = f.read() f.close() - + return text - + def get_my_groups(user,conclude=False): ''' Takes a Django user object (from request) @@ -31,24 +31,24 @@ def get_my_groups(user,conclude=False): area director - has access to all groups in their area wg chair or secretary - has acceses to their own group chair of irtf has access to all irtf groups - + If user=None than all groups are returned. concluded=True means include concluded groups. Need this to upload materials for groups after they've been concluded. it happens. ''' my_groups = set() states = ['bof','proposed','active'] - if conclude: - states.append('conclude') + if conclude: + states.extend(['conclude','bof-conc']) all_groups = Group.objects.filter(type__in=('wg','rg','ag','team'),state__in=states).order_by('acronym') if user == None: return all_groups else: person = user.get_profile() - + if has_role(user,'Secretariat'): return all_groups - + for group in all_groups: if group.role_set.filter(person=person,name__in=('chair','secr')): my_groups.add(group) @@ -56,16 +56,16 @@ def get_my_groups(user,conclude=False): if group.parent and group.parent.role_set.filter(person=person,name__in=('ad','chair')): my_groups.add(group) continue - + return list(my_groups) - + def groups_by_session(user, meeting): ''' Takes a Django User object and a Meeting object - Returns a tuple scheduled_groups, unscheduled groups. sorted lists of those groups that + Returns a tuple scheduled_groups, unscheduled groups. sorted lists of those groups that the user has access to, secretariat defaults to all groups If user=None than all groups are returned. - + For groups with a session, we must include "concluded" groups because we still want to know who had a session at a particular meeting even if they are concluded after. This is not true for groups without a session because this function is often used to build select lists (ie. @@ -80,8 +80,7 @@ def groups_by_session(user, meeting): if group in groups_with_sessions: groups_session.append(group) else: - if group.state_id != 'conclude': + if group.state_id not in ('conclude','bof-conc'): groups_no_session.append(group) - + return groups_session, groups_no_session - \ No newline at end of file