def conv(xml_in, html_out='out.html', template_name='html.pt', xpath_filter='//entry'): if not xml_in: raise ValueError('No XML input file specified (-i|--xml-in)') entries = util.get_entries(xml_in, xpath_filter) template = env.get_template(template_name) html = template.render(entries=entries, view=util.JinjaView()) with open(html_out, 'wb') as fp: fp.write(html.encode('utf8')) return html_out
def conv(schedule_xml, # schedule XML string or schedule XML filename date_str, # YYYY-MM-DD rooms, # list of rooms hour_start=0, # schedule starts hour_end=24, # schedule ends resolution=15, # timeslot resolution in minutes caption=None, # caption of table weekday=None, # weekday name event_renderer=None): entries = util.get_entries(schedule_xml, '//day[@date="{}"]/entry'.format(date_str)) row_headers = list() for hour in range(hour_start, hour_end + 1): for minute in range(0, 60, resolution): row_headers.append('{:02}:{:02}h'.format(hour, minute)) tb = table.Table(60/resolution * (hour_end - hour_start) , len(rooms)) tb.caption = caption tb.col_headers = rooms tb.row_headers = row_headers tb.weekday = weekday for e in entries: # determine starting row of event e_start = e.start.text # format '0700' s_hour = int(e_start[:2]) s_minute = int(e_start[2:]) s_row = (s_hour - hour_start) * (60 / resolution) + s_minute / resolution # calculate row span over multiple time slots s_duration = int(e.duration) rowspan = s_duration / resolution # determine col of event if e.room == 'ALL': # span over all columns s_col = 0 colspan = len(rooms) tb.addCell(s_row, s_col, rowspan=rowspan, colspan=colspan, event=e) else: for room in e.room.text.split(','): if room in rooms: s_col = rooms.index(room) colspan = 1 tb.addCell(s_row, s_col, rowspan=rowspan, colspan=colspan, event=e) return tb.render(event_renderer=event_renderer)
def conv(xml_in=None, html_out='brochure.html', first_page_number=1, pdf_converter=None, pdf_filename=None, imagedir=None, emptypage=False, fontpath='fonts', template='brochure_talks.pt'): if not xml_in: raise ValueError('No XML input file specified (-i|--xml-in)') if imagedir: for name in os.listdir(imagedir): filename = os.path.join(imagedir, name) img = PIL.Image.open(filename) target_size = min(img.size) if img.size != (target_size, target_size): print 'Cropping {}'.format(filename) img2 = img.crop((0, 0, target_size, target_size)) img2.save(filename) entries = list() for day in range(21, 26): date_str = '2014-07-{}'.format(day) entries_d = util.get_entries(xml_in, '//day[@date="{}"]/entry'.format(date_str)) entries_d = [e for e in entries_d if e.category] entries.append(dict(entries=entries_d, date_text=datetime.strptime(date_str, '%Y-%m-%d').strftime('%A'), date_str=date_str)) speakers = list() speakers_seen = set() for e in util.get_entries(xml_in, '//day/entry'): for speaker in e.speakers or []: speaker_name = speaker.speaker.name speaker_description = speaker.speaker.description speaker_image_url = speaker.speaker.image speaker_has_content = 'has-content' if len(speaker_description.text or '')> 0 else 'has-no-content' speaker_image_file = '' speaker_image_found = False if imagedir: speaker_image_file = os.path.join(os.path.abspath(imagedir), speaker.speaker.attrib['id']) for ext in ('.png', '.jpg', '.gif'): if os.path.exists(speaker_image_file + ext): speaker_image_file += ext speaker_image_found = True break if not speaker_image_found: print 'No speaker image found for {} ({})'.format(speaker_name.text.encode('utf8'), speaker.speaker.attrib['id']) if not speaker_name in speakers_seen: speakers.append(dict(name=speaker_name, name_lower=unicode(speaker_name).lower(), description=speaker_description, image_file=speaker_image_file, has_content=speaker_has_content, has_image=speaker_image_found, image_url=speaker_image_url)) speakers_seen.add(speaker_name) speakers = sorted(speakers, key=operator.itemgetter('name_lower')) print '{} speakers found'.format(len(speakers)) template = env.get_template(template) html = template.render( first_page_number=int(first_page_number) - 1, second_page_number=int(first_page_number) +3, day_entries=entries, speakers=speakers, emptypage=emptypage, view=util.JinjaView()) with open(html_out, 'wb') as fp: print 'HTML output written to "{}"'.format(html_out) fp.write(html.encode('utf8')) if pdf_converter in ('princexml', 'pdfreactor', 'pdfreactor7', 'remote-princexml', 'remote-pdfreactor'): # write HTML file to a dedicated scratch directory tmpd = tempfile.mkdtemp() html_filename = os.path.join(tmpd, 'index.html') with open(html_filename, 'wb') as fp: fp.write(html.encode('utf-8')) # copy over conversion resources resources_dir = os.path.join(os.path.dirname(__file__), 'templates', 'resources') for dirname, dirnames, filenames in os.walk(resources_dir): for fname in filenames: shutil.copy(os.path.join(dirname, fname), tmpd) if fontpath and os.path.exists(fontpath): for filename in os.listdir(fontpath): shutil.copy(os.path.join(fontpath, filename), tmpd) if pdf_converter in ('princexml', 'pdfreactor', 'pdfreactor7'): # local pdf generation through PrinceXML or PDFreactor if pdf_filename: out_pdf = pdf_filename else: out_pdf = '{}.pdf'.format(os.path.splitext(html_filename)[0]) if pdf_converter == 'princexml': cmd = 'prince -v "{}" -o "{}"'.format(html_filename, out_pdf) elif pdf_converter == 'pdfreactor': cmd = 'pdfreactor --disablefontembedding "{}" "{}"'.format(html_filename, out_pdf) elif pdf_converter == 'pdfreactor7': cmd = '/opt/PDFreactor7/bin/pdfreactor --disablefontembedding "{}" "{}"'.format(html_filename, out_pdf) print 'Running: {}'.format(cmd) proc = subprocess.Popen(cmd, shell=True) status = proc.wait() print 'Exit code: {}'.format(status) if status != 0: raise RuntimeError('PDF generation failed') print 'PDF written to "{}"'.format(out_pdf) return out_pdf elif pdf_converter in ('remote-princexml', 'remote-pdfreactor'): # remote pdf generation through PrinceXML or PDFreactor # through https://pp-server.zopyx.com server_url = os.environ['PP_SERVER_URL'] authorization_token = os.environ['PP_AUTHORIZATION_TOKEN'] output_filename = tempfile.mktemp(suffix='.pdf', dir=tmpd) result = pdf(source_directory=tmpd, converter=pdf_converter.replace('remote-', ''), output=output_filename, server_url=server_url, authorization_token=authorization_token, verbose=True) if result['status'] != 'OK': raise RuntimeError('Remote PDF generation failed') print 'PDF written to "{}"'.format(result['output_filename']) return result['output_filename']