def ical(self, session, **params): icalendar = ics.Calendar() if 'locations' not in params or not params['locations']: locations = [id for id, name in c.EVENT_LOCATION_OPTS] calname = "full" else: locations = json.loads(params['locations']) if len(locations) > 3: calname = "partial" else: calname = "_".join([name for id, name in c.EVENT_LOCATION_OPTS if str(id) in locations]) calname = '{}_{}_schedule'.format(c.EVENT_NAME, calname).lower().replace(' ', '_') for location in locations: for event in session.query(Event)\ .filter_by(location=int(location))\ .order_by('start_time').all(): icalendar.events.add(ics.Event( name=event.name, begin=event.start_time, end=(event.start_time + timedelta(minutes=event.minutes)), description=normalize_newlines(event.description), created=event.created.when, location=event.location_label)) cherrypy.response.headers['Content-Type'] = \ 'text/calendar; charset=utf-8' cherrypy.response.headers['Content-Disposition'] = \ 'attachment; filename="{}.ics"'.format(calname) return icalendar
def schedule_tsv(self, session): cherrypy.response.headers['Content-Type'] = 'text/tsv' cherrypy.response.headers[ 'Content-Disposition'] = 'attachment;filename=Schedule-{}.tsv'.format( int(localized_now().timestamp())) schedule = defaultdict(list) for event in session.query(Event).order_by('start_time').all(): schedule[event.location_label].append( dict( event.to_dict(), **{ 'date': event.start_time_local.strftime('%m/%d/%Y'), 'start_time': event.start_time_local.strftime('%I:%M:%S %p'), 'end_time': (event.start_time_local + timedelta( minutes=event.minutes)).strftime('%I:%M:%S %p'), 'description': normalize_newlines(event.description).replace( '\n', ' ') })) return render( 'schedule/schedule.tsv', { 'schedule': sorted(schedule.items(), key=lambda tup: c.ORDERED_EVENT_LOCS.index(tup[1][0][ 'location'])) })
def linebreaksbr(text): """Convert all newlines ("\n") in a string to HTML line breaks ("<br />")""" is_markup = isinstance(text, Markup) text = normalize_newlines(text) if not is_markup: text = text_type(jinja2.escape(text)) text = text.replace('\n', '<br />') return safe_string(text)
def schedule_tsv(self, session): cherrypy.response.headers['Content-Type'] = 'text/tsv' cherrypy.response.headers['Content-Disposition'] = 'attachment;filename=Schedule-{}.tsv'.format( int(localized_now().timestamp())) schedule = defaultdict(list) for event in session.query(Event).order_by('start_time').all(): schedule[event.location_label].append(dict(event.to_dict(), **{ 'date': event.start_time_local.strftime('%m/%d/%Y'), 'start_time': event.start_time_local.strftime('%I:%M:%S %p'), 'end_time': (event.start_time_local + timedelta(minutes=event.minutes)).strftime('%I:%M:%S %p'), 'description': normalize_newlines(event.description).replace('\n', ' ') })) return render('schedule/schedule.tsv', { 'schedule': sorted(schedule.items(), key=lambda tup: c.ORDERED_EVENT_LOCS.index(tup[1][0]['location'])) })
def csv(self, out, session): out.writerow(['Session Title', 'Date', 'Time Start', 'Time End', 'Room/Location', 'Schedule Track (Optional)', 'Description (Optional)', 'Allow Checkin (Optional)', 'Checkin Begin (Optional)', 'Limit Spaces? (Optional)', 'Allow Waitlist (Optional)']) rows = [] for event in session.query(Event).order_by('start_time').all(): rows.append([ event.name, event.start_time_local.strftime('%m/%d/%Y'), event.start_time_local.strftime('%I:%M:%S %p'), (event.start_time_local + timedelta(minutes=event.minutes)).strftime('%I:%M:%S %p'), event.location_label, '', normalize_newlines(event.description).replace('\n', ' '), '', '', '', '' ]) for r in sorted(rows, key=lambda tup: tup[4]): out.writerow(r)
def body_as_html(self): if self.is_html: return self.body_with_body_tag_stripped else: return normalize_newlines(self.body).replace('\n', '<br>')
def export(self, query, full=False): """ Searches for attendees by either email, "first last" name, or "first last <email>" combinations. `query` should be a comma or newline separated list of email/name queries. Example: <pre>Merrium Webster, [email protected], John Doe <[email protected]></pre> Results are returned in the format expected by <a href="../import/staff">the staff importer</a>. """ _re_name_email = re.compile(r'^\s*(.*?)\s*<\s*(.*?@.*?)\s*>\s*$') _re_sep = re.compile(r'[\n,]') _re_whitespace = re.compile(r'\s+') queries = [s.strip() for s in _re_sep.split(normalize_newlines(query)) if s.strip()] names = dict() emails = dict() names_and_emails = dict() ids = set() for q in queries: if '@' in q: match = _re_name_email.match(q) if match: name = match.group(1) email = Attendee.normalize_email(match.group(2)) if name: first, last = (_re_whitespace.split(name.lower(), 1) + [''])[0:2] names_and_emails[(first, last, email)] = q else: emails[email] = q else: emails[Attendee.normalize_email(q)] = q elif q: try: ids.add(str(uuid.UUID(q))) except Exception: first, last = (_re_whitespace.split(q.lower(), 1) + [''])[0:2] names[(first, last)] = q with Session() as session: if full: options = [ subqueryload(Attendee.dept_memberships).subqueryload(DeptMembership.department), subqueryload(Attendee.dept_membership_requests).subqueryload(DeptMembershipRequest.department)] else: options = [] email_attendees = [] if emails: email_attendees = session.query(Attendee).filter(Attendee.normalized_email.in_(list(emails.keys()))) \ .options(*options).order_by(Attendee.email, Attendee.id).all() known_emails = set(a.normalized_email for a in email_attendees) unknown_emails = sorted([raw for normalized, raw in emails.items() if normalized not in known_emails]) name_attendees = [] if names: filters = [ and_(func.lower(Attendee.first_name) == first, func.lower(Attendee.last_name) == last) for first, last in names.keys()] name_attendees = session.query(Attendee).filter(or_(*filters)) \ .options(*options).order_by(Attendee.email, Attendee.id).all() known_names = set((a.first_name.lower(), a.last_name.lower()) for a in name_attendees) unknown_names = sorted([raw for normalized, raw in names.items() if normalized not in known_names]) name_and_email_attendees = [] if names_and_emails: filters = [ and_( func.lower(Attendee.first_name) == first, func.lower(Attendee.last_name) == last, Attendee.normalized_email == email) for first, last, email in names_and_emails.keys()] name_and_email_attendees = session.query(Attendee).filter(or_(*filters)) \ .options(*options).order_by(Attendee.email, Attendee.id).all() known_names_and_emails = set( (a.first_name.lower(), a.last_name.lower(), a.normalized_email) for a in name_and_email_attendees) unknown_names_and_emails = sorted([ raw for normalized, raw in names_and_emails.items() if normalized not in known_names_and_emails]) id_attendees = [] if ids: id_attendees = session.query(Attendee).filter(Attendee.id.in_(ids)) \ .options(*options).order_by(Attendee.email, Attendee.id).all() known_ids = set(str(a.id) for a in id_attendees) unknown_ids = sorted([i for i in ids if i not in known_ids]) seen = set() all_attendees = [ a for a in (id_attendees + email_attendees + name_attendees + name_and_email_attendees) if a.id not in seen and not seen.add(a.id)] fields = [ 'first_name', 'last_name', 'birthdate', 'email', 'zip_code', 'birthdate', 'international', 'ec_name', 'ec_phone', 'cellphone', 'badge_printed_name', 'found_how', 'comments', 'admin_notes', 'all_years', 'badge_status', 'badge_status_label', ] if full: fields.extend(['shirt']) attendees = [] for a in all_attendees: d = a.to_dict(fields) if full: assigned_depts = {} checklist_admin_depts = {} dept_head_depts = {} poc_depts = {} for membership in a.dept_memberships: assigned_depts[membership.department_id] = membership.department.name if membership.is_checklist_admin: checklist_admin_depts[membership.department_id] = membership.department.name if membership.is_dept_head: dept_head_depts[membership.department_id] = membership.department.name if membership.is_poc: poc_depts[membership.department_id] = membership.department.name d.update({ 'assigned_depts': assigned_depts, 'checklist_admin_depts': checklist_admin_depts, 'dept_head_depts': dept_head_depts, 'poc_depts': poc_depts, 'requested_depts': { (m.department_id if m.department_id else 'All'): (m.department.name if m.department_id else 'Anywhere') for m in a.dept_membership_requests}, }) attendees.append(d) return { 'unknown_ids': unknown_ids, 'unknown_emails': unknown_emails, 'unknown_names': unknown_names, 'unknown_names_and_emails': unknown_names_and_emails, 'attendees': attendees, }
def test_normalize_newlines(test_input, expected): assert expected == normalize_newlines(test_input)
def export(self, query, full=False): """ Searches for attendees by either email or first and last name. `query` should be a comma or newline separated list of emails and "first last" name combos. Results are returned in the format expected by <a href="../import/staff">the staff importer</a>. """ queries = [s.strip() for s in re.split('[\n,]', normalize_newlines(query)) if s.strip()] names = dict() emails = dict() ids = set() for q in queries: if '@' in q: emails[Attendee.normalize_email(q)] = q elif q: try: ids.add(str(uuid.UUID(q))) except Exception: first, _, last = [s.strip() for s in q.partition(' ')] names[q] = (first.lower(), last.lower()) with Session() as session: if full: options = [ subqueryload(Attendee.dept_memberships).subqueryload(DeptMembership.department), subqueryload(Attendee.dept_membership_requests).subqueryload(DeptMembershipRequest.department)] else: options = [] email_attendees = [] if emails: email_attendees = session.query(Attendee).filter(Attendee.normalized_email.in_(list(emails.keys()))) \ .options(*options).order_by(Attendee.email, Attendee.id).all() known_emails = set(a.normalized_email for a in email_attendees) unknown_emails = sorted([email for normalized, email in emails.items() if normalized not in known_emails]) name_attendees = [] if names: filters = [ and_(func.lower(Attendee.first_name) == n[0], func.lower(Attendee.last_name) == n[1]) for n in names.values()] name_attendees = session.query(Attendee).filter(or_(*filters)) \ .options(*options).order_by(Attendee.email, Attendee.id).all() id_attendees = [] if ids: id_attendees = session.query(Attendee).filter(Attendee.id.in_(ids)) \ .options(*options).order_by(Attendee.email, Attendee.id).all() known_names = set(a.full_name.lower() for a in name_attendees) unknown_names = sorted([full_name for full_name in names.keys() if full_name.lower() not in known_names]) seen = set() all_attendees = [ a for a in (id_attendees + email_attendees + name_attendees) if a.id not in seen and not seen.add(a.id)] fields = [ 'first_name', 'last_name', 'birthdate', 'email', 'zip_code', 'birthdate', 'international', 'ec_name', 'ec_phone', 'cellphone', 'badge_printed_name', 'found_how', 'comments', 'admin_notes', 'all_years', ] attendees = [] for a in all_attendees: d = a.to_dict(fields) if full: assigned_depts = {} checklist_admin_depts = {} dept_head_depts = {} poc_depts = {} for membership in a.dept_memberships: assigned_depts[membership.department_id] = membership.department.name if membership.is_checklist_admin: checklist_admin_depts[membership.department_id] = membership.department.name if membership.is_dept_head: dept_head_depts[membership.department_id] = membership.department.name if membership.is_poc: poc_depts[membership.department_id] = membership.department.name d.update({ 'assigned_depts': assigned_depts, 'checklist_admin_depts': checklist_admin_depts, 'dept_head_depts': dept_head_depts, 'poc_depts': poc_depts, 'requested_depts': { (m.department_id if m.department_id else 'All'): (m.department.name if m.department_id else 'Anywhere') for m in a.dept_membership_requests}, }) attendees.append(d) return { 'unknown_emails': unknown_emails, 'unknown_names': unknown_names, 'attendees': attendees, }
def body_as_html(self): if self.is_html: return re.split('<body[^>]*>', self.body)[-1].split('</body>')[0] else: return normalize_newlines(self.body).replace('\n', '<br>')