experimental... .pdf

249 views
Skip to first unread message

mdipierro

unread,
Oct 3, 2010, 12:10:38 AM10/3/10
to web2py-users
install pdflatex

create a views/generic.pdf that contains:

---- begin file ----
{{
import re
from gluon.contrib.markmin.markmin2pdf import markmin2pdf
def markmin_serializer(text,tag=None,attr={}):
if tag==None: return re.sub('\s+',' ',text)
if tag=='br': return '\n\n'
if tag=='h1': return '# '+text+'\n\n'
if tag=='h2': return '#'*2+' '+text+'\n\n'
if tag=='h3': return '#'*3+' '+text+'\n\n'
if tag=='h4': return '#'*4+' '+text+'\n\n'
if tag=='li': return '\n- '+text.replace('\n',' ')
if tag=='table': return '\n-----\n'+text+'\n------\n'
if tag=='tr': return text[3:].replace('\n',' ')+'\n'
if tag=='td': return ' | '+text
if tag=='p': return text+'\n\n'
if tag=='b' or tag=='strong': return '**%s**' % text
if tag=='em' or tag=='i': return "''%s''" % text
if tag=='tt' or tag=='code': return '``%s``' % text
if tag=='a': return '[[%s %s]]' % (text,attr.get('_href',''))
return text
html=response.render('%s/%s.html' %
(request.controller,request.function))
markmin=TAG(html).element('#content').flatten(markmin_serializer)
response.write(markmin2pdf(markmin)[0],escape=False)
response.headers['content-type']='text'
}}
---- end file---

Now you should be able to view any web2py page with .pdf in pdf.

I am sure this can also be done and better with pyfpdf but I have not
tried. Perhaps Mariano can help us

mdipierro

unread,
Oct 3, 2010, 12:28:34 AM10/3/10
to web2py-users
or better

{{
import re
from gluon.contrib.markmin.markmin2pdf import markmin2pdf
def markmin_serializer(text,tag=None,attr={}):
if tag==None: return re.sub('\s+',' ',text)
if tag=='br': return '\n\n'
if tag=='h1': return '# '+text+'\n\n'
if tag=='h2': return '#'*2+' '+text+'\n\n'
if tag=='h3': return '#'*3+' '+text+'\n\n'
if tag=='h4': return '#'*4+' '+text+'\n\n'
if tag=='p': return text+'\n\n'
if tag=='li': return '\n- '+text.replace('\n',' ')
if tag=='tr': return text[3:].replace('\n',' ')+'\n'
if tag in ['table','blockquote']: return '\n-----\n'+text+'\n------
\n'
if tag in ['td','th']: return ' | '+text
if tag in ['b','strong','label']: return '**%s**' % text
if tag in ['em','i']: return "''%s''" % text
if tag in ['tt','code']: return '``%s``' % text
if tag=='a': return '[[%s %s]]' % (text,attr.get('_href',''))
return text
html=response.render('%s/%s.html' %
(request.controller,request.function))
markmin=TAG(html).element('#content').flatten(markmin_serializer)
pdf,warnings,errors=markmin2pdf(markmin)
if errors:
response.headers['Content-Type']='text'

response.write(HTML(BODY(H1('errors'),LU(*errors),H1('warnings'),LU(*warnings))))
else:
response.headers['Content-Type']='application/pdf'
response.write(pdf,escape=False)
pass

mart

unread,
Oct 3, 2010, 1:02:34 AM10/3/10
to web2py-users
Ok, 'm really liking this! a few questions:


1) I'm not catching on where we get pdflatex... is it a plugin? where
do we get it?


2) Is this a feature that can be add to an up for users? meanin
something like "upload your document - then download your pdf (or
email generated pdf")? should be doable?


3) I used reportlab for drawing fingerboard templates for kids
learning the violin (which I got some nasty email from some template
maker/vendor, so now I really want to put this out there - its just
number crunching so it should be a crome to sell numbers to kids ;) )
Is here a way to make use of those drawing capabilities? simple: draw
lines @ coordinates?


4) scaling: is there a way to control that at this end? (for printing
purposes - scaling needs to be disabled)


thanks :)

Michele Comitini

unread,
Oct 3, 2010, 4:35:38 AM10/3/10
to web...@googlegroups.com
@Mart

1) You need to install a TeX distribution, TeX Live is probably the
most complete: http://tug.org/texlive/


2010/10/3 mart <msene...@gmail.com>:

mdipierro

unread,
Oct 3, 2010, 10:11:09 AM10/3/10
to web2py-users
what is scaling?

mart

unread,
Oct 3, 2010, 3:50:24 PM10/3/10
to web2py-users
@Michele: Thanks for that, I will make good use of it! :)

@Massimo: scaling is one of those options that is more often set by
the pdf viewer (because what generates the pdf usually sets the
default to "scaling=enabled"). If I re-use that fingerboard example:
When using the app, the young violinist, will be asked to measure his/
her violin's scale length (from nut to bridge). then enters the
measurement, exactly. so by simply using the rule of 18 (really
17.817), it generates that template that he/she can print and use to
out his position markers on the violin. The important thing, is that
the printed pdf must be exact, if not he/she will be pitchy. Which
means, if scaling is enabled, the printer will print in a wysisyg
fashion (fits the screen)... which is completely wrong. there must be
no scaling at all, print the exact measutrements.

Since PDF seems to be a hot issue, here's how I use reportlab to
generate the pdf templates (but now, I want to use the web2py builtin
libs) - I know, not too too pretty, but works :)

Thanks,
Mart :)

'''
@author: mart
'''
import os, sys, string
from pyFret.reportlab.pdfgen.canvas import Canvas
from pyFret.reportlab.lib.pagesizes import letter, A4
from pyFret.reportlab.lib.units import cm, mm, inch, pica
from pyFret.reportlab.graphics.charts.textlabels import Label
from pyFret.reportlab.lib import colors


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

################################################M####
## create string instrument position markers
####A###

##################################################R##

###################################################T#


"""
ref. 4/4 = 32.6 ou 32.7 cm
rect(x, y, width, height, stroke=1, fill=0)
RGB Brown =(107,66,38)
RGB Purple = (135,31,120)
"""

###################################
# rule of 18, unrounded to 17.817 #
###################################
n = 17.817

#########################################
# number of position markers to create #
#########################################
markers = 12

#######################################
# list of standard markers as indices #
#######################################
indexList = [1,3,4,6,8,10,11]

#####################
# string resources #
#####################
sJoin = ' join at previous marker'

def main():

##################################################################################################
# will create position markers in range of 2000 mm to 9000 mm,
converted to cm (20.00 to 90.00) #
# dynamically printed to
PDF
#

##################################################################################################
#createAll()
# Test()
byInput()


def byInput():
sLenght = raw_input("your scale lenght: ")
calculateOffsetFromScaleLenght(float(sLenght))

def Test():
List = [32.6,21.75,21.4,23.45,73,90]
for item in List:
createTest(item)

def createTest(sLenght):
calculateOffsetFromScaleLenght(sLenght)

def createAll():
##########################
# generate scalelenghts #
##########################
i = 20.0
Min = 20
Max = 90
for c in range(Min,Max):
while i < Max:
print i
i += 0.01
calculateOffsetFromScaleLenght(i)

def calculateOffsetFromScaleLenght(initScaleLenght):
offsetList = []
offset = 0
nScaleLenght = initScaleLenght
counter = 0
while counter < markers:
offset = getOffSet(nScaleLenght);
offsetList.append(offset)
nScaleLenght = get_nScalelenght(nScaleLenght,offset)
counter += 1
genPDF(initScaleLenght, (7.62,9.5,12.7),cm, offsetList)

def genPDF(initScaleLenght, (startLine,endLine, stringLine), measure,
offsetList):
##################################
# create reference to PDF object #
##################################
pdf = Canvas(str(initScaleLenght) + '.pdf', bottomup=1)
pdf.setFont("Courier", 10)

###################################
# calculate total lenght of frets #
###################################
fLenght = 0
for item in offsetList:
fLenght += item

#####################
# draw nut #
#####################
pdf.line(startLine*measure,3*measure,endLine*measure,3*measure)
pdf.drawString(stringLine * measure, 3*measure, str(0) + ' /nut/'
+ str(initScaleLenght))

#############################################
# if offsets are generated (valid number) #
#############################################
if len(offsetList) > 0:
pageLenghtMax = 26
accruedOffSet = 0
belowMaxList = []
##############################
# draw terminating rectangle #
##############################
pdf.setStrokeColorRGB(0, 0, 0)
pdf.rect(startLine*measure, 3*measure, 1.9*measure,
(fLenght)*measure, stroke=1, fill=0)

#########################
# build up belowMaxList #
#########################
for o in offsetList:
if o < pageLenghtMax:
belowMaxList.append(o)
###########################
# iterate over offsetList #
###########################
for offset in offsetList:
oIndex = offsetList.index(offset)
########################################
# incremented sum of generated offsets #
########################################
accruedOffSet = offset + accruedOffSet
accruedOffsetString = offset + accruedOffSet
##########################################
# standard markers in red else yellow #
##########################################
if oIndex in indexList:
pdf.setStrokeColorRGB(0, 0, 0)
else:
pdf.setStrokeColorRGB(1, 1, 0)
#####################
# draw the markers #
#####################
if accruedOffSet < pageLenghtMax:
pdf.line(startLine*measure,(accruedOffSet +
3)*measure,endLine*measure,(accruedOffSet + 3)*measure)
pdf.drawString(stringLine * measure, (accruedOffSet +
3)*measure, str(accruedOffSet))
########################################
# create new page if eop is reached #

########################################
else:
pdf.showPage()
pdf.setFont("Courier", 10)

#######################################################
# restart accruedOffSet @ 0 and sraw "connect" marker
#

#######################################################
pdf.line(startLine*measure,3*measure,endLine*measure,
3*measure)
pdf.drawString(stringLine * measure, 3*measure, sJoin)
accruedOffSet = 0

##############################
# draw terminating rectangle #
##############################
pdf.setStrokeColorRGB(0, 0, 0)
pdf.rect(startLine*measure, 3*measure, 1.9*measure,
(accruedOffSet)*measure, stroke=1, fill=0)

################################
# save the data to pdf file #
################################
pdf.save()
print("your template is ready
({0}.pdf)".format(str(initScaleLenght)))

def get_nScalelenght(scalelenght,offset):
newScaleLenght = 0
if scalelenght > 0 and offset > 0:
newScaleLenght = scalelenght - offset
return newScaleLenght

def getOffSet(scaleLenght):
nOffset = 0
if scaleLenght > 0:
nOffset = scaleLenght / n
return nOffset


if '__main__':
main()

Michele Comitini

unread,
Oct 3, 2010, 4:02:33 PM10/3/10
to web...@googlegroups.com
@Massimo,

is it text?

response.headers['content-type']='text'

or

response.headers['content-type']='application/pdf' ?

tnx
mic

2010/10/3 mdipierro <mdip...@cs.depaul.edu>:

mdipierro

unread,
Oct 3, 2010, 8:28:08 PM10/3/10
to web2py-users
if there are errors it should return text containing the errors, else
pdf. This mechanism for error reporting is temporary and does not
quite work.

On Oct 3, 3:02 pm, Michele Comitini <michele.comit...@gmail.com>
wrote:
> @Massimo,
>
> is it text?
>
> response.headers['content-type']='text'
>
> or
>
> response.headers['content-type']='application/pdf' ?
>
> tnx
> mic
>
> 2010/10/3 mdipierro <mdipie...@cs.depaul.edu>:

Mariano Reingart

unread,
Oct 4, 2010, 8:08:14 PM10/4/10
to web...@googlegroups.com
On Sun, Oct 3, 2010 at 1:10 AM, mdipierro <mdip...@cs.depaul.edu> wrote:
>
> I am sure this can also be done and better with pyfpdf but I have not
> tried. Perhaps Mariano can help us

Having latest web2py versions (including pyfpdf), write in a views/generic.pdf:

---- begin file ----
{{

from gluon.contrib.pyfpdf import FPDF, HTMLMixin
from gluon.sanitizer import sanitize

class MyFPDF(FPDF, HTMLMixin):
pass

pdf=MyFPDF()
pdf.add_page()
html=response.render('%s/%s.html' %
(request.controller,request.function))
html = sanitize(html, escape=False)
pdf.write_html(html)
response.headers['Content-Type']='application/pdf'
response.write(pdf.output(dest='S'), escape=False)

}}
---- end file---

At MyFPDF class you can add headers and footers.

The sanitize part is to strip some HTML tags that cannot be rendered
(ie. javascript).

As some DIVs contents and similar may still pass (like menus), a
better alternative may be render only certains portions of the page in
a custom view:

pdf.write_html(str(XML(CENTER(section), sanitize=False)))

Best regards,

Mariano Reingart
http://www.sistemasagiles.com.ar
http://reingart.blogspot.com

Mariano Reingart

unread,
May 26, 2011, 3:48:06 PM5/26/11
to luifran, web...@googlegroups.com
Putting the following code in generic.pdf and getting report.pdf does not work?
(also, per default there is a generic.pdf made by massimo that uses
markmin and latex if I remember it correctly)

from gluon.contrib.pyfpdf import FPDF, HTMLMixin
from gluon.sanitizer import sanitize

class MyFPDF(FPDF, HTMLMixin):
pass

pdf=MyFPDF()
pdf.add_page()
html=response.render('%s/%s.html' %
(request.controller,request.function))
html = sanitize(html, escape=False)
pdf.write_html(html)
response.headers['Content-Type']='application/pdf'
response.write(pdf.output(dest='S'), escape=False)

On Thu, May 26, 2011 at 4:30 PM, luifran <lbernalh...@yahoo.es> wrote:
> if I have a view , for example report.html, how I render this view in
> pdf with the generic pdf?
>
> On 4 oct 2010, 17:08, Mariano Reingart <reing...@gmail.com> wrote:

Christopher Steel

unread,
May 26, 2011, 11:44:09 PM5/26/11
to web2py-users
I think report.pdf required reportlab? Massimo had an application for
creating forms that used markmin and latex.

This web2py app includes a plugin that implements an assortment of pdf
stuff (mostly your implementation of pyfpdf and the report.pdf, was
that a Google thing?.

Anyway the plugin is handy for testing and experimenting and includes
some other PDF examples, one with a different font.

http://code.google.com/p/uc-pyfpdf/

If you need some testing let me know, I love PDF's

Cheers,

Chris


On May 26, 3:48 pm, Mariano Reingart <reing...@gmail.com> wrote:
> Putting the following code in generic.pdf and getting report.pdf does not work?
> (also, per default there is a generic.pdf made by massimo that uses
> markmin and latex if I remember it correctly)
>
> from gluon.contrib.pyfpdf import FPDF, HTMLMixin
> from gluon.sanitizer import sanitize
>
> class MyFPDF(FPDF, HTMLMixin):
>    pass
>
> pdf=MyFPDF()
> pdf.add_page()
> html=response.render('%s/%s.html' %
> (request.controller,request.function))
> html = sanitize(html, escape=False)
> pdf.write_html(html)
> response.headers['Content-Type']='application/pdf'
> response.write(pdf.output(dest='S'), escape=False)
>

Massimo Di Pierro

unread,
May 27, 2011, 12:06:11 AM5/27/11
to web2py-users
I just made a change to trunk about. the new generic.pdf uses pyfpdf
and it is smart in locating files for including images.

massimo

Massimo Di Pierro

unread,
May 27, 2011, 12:35:19 AM5/27/11
to web2py-users
There are still problems...it does not render headers and tables...

On May 26, 11:06 pm, Massimo Di Pierro <massimo.dipie...@gmail.com>
wrote:

Mariano Reingart

unread,
May 27, 2011, 12:08:01 PM5/27/11
to web...@googlegroups.com
Regarding PyFPDF:

Headers should be rendered.

Tables need at least a first TH, prior any TD, who indicates column
width (and it is wise to use THEAD and TBODY when you have multiple
pages), see:
http://code.google.com/p/pyfpdf/wiki/WriteHTML

<table border="0" align="center" width="50%">
<thead><tr><th width="30%">Header 1</th><th width="70%">header
2</th></tr></thead>
<tbody>
<tr><td>cell 1</td><td>cell 2</td></tr>
<tr><td>cell 2</td><td>cell 3</td></tr>
</tbody>
</table>

I'm planning to fix this issues, to cover more basic html conversions.

You can see what can do pyfpdf in this file:
http://pyfpdf.googlecode.com/files/html.pdf

BTW, did you see the new visual designer of pdf templates?

http://code.google.com/p/pyfpdf/wiki/Templates?ts=1306512231&updated=Templates#Designer

It is a wx application, and I'm planning to connect it using DAL to
ease template/report generation (I think this is much easier and
manageable way than converting html).

Best regards,

mart

unread,
May 29, 2011, 2:02:09 PM5/29/11
to web2py-users
Wow! This is really nice! so all that is need for the designer is
wxPython?

Mart :)

On May 27, 12:08 pm, Mariano Reingart <reing...@gmail.com> wrote:
> Regarding PyFPDF:
>
> Headers should be rendered.
>
> Tables need at least a first  TH, prior any TD, who indicates column
> width (and it is wise to use THEAD and TBODY when you have multiple
> pages), see:http://code.google.com/p/pyfpdf/wiki/WriteHTML
>
> <table border="0" align="center" width="50%">
> <thead><tr><th width="30%">Header 1</th><th width="70%">header
> 2</th></tr></thead>
> <tbody>
> <tr><td>cell 1</td><td>cell 2</td></tr>
> <tr><td>cell 2</td><td>cell 3</td></tr>
> </tbody>
> </table>
>
> I'm planning to fix this issues, to cover more basic html conversions.
>
> You can see what can do pyfpdf in this file:http://pyfpdf.googlecode.com/files/html.pdf
>
> BTW, did you see the new visual designer of pdf templates?
>
> http://code.google.com/p/pyfpdf/wiki/Templates?ts=1306512231&updated=...
>
> It is a wx application, and I'm planning to connect it using DAL to
> ease template/report generation (I think this is much easier and
> manageable way  than converting html).
>
> Best regards,
>
> Mariano Reingarthttp://www.sistemasagiles.com.arhttp://reingart.blogspot.com

Christopher Steel

unread,
May 29, 2011, 11:39:26 PM5/29/11
to web2py-users
I am going try things out again when I get a chance. This stuff is
just great. I love the fact that we build on a solid API so in the end
we get the GUI and command line and API access for developers and the
blind. It totally rocks!!!

Markmin to PDF would be very interesting as well..

Chris

On May 27, 12:08 pm, Mariano Reingart <reing...@gmail.com> wrote:
> Regarding PyFPDF:
>
> Headers should be rendered.
>
> Tables need at least a first  TH, prior any TD, who indicates column
> width (and it is wise to use THEAD and TBODY when you have multiple
> pages), see:http://code.google.com/p/pyfpdf/wiki/WriteHTML
>
> <table border="0" align="center" width="50%">
> <thead><tr><th width="30%">Header 1</th><th width="70%">header
> 2</th></tr></thead>
> <tbody>
> <tr><td>cell 1</td><td>cell 2</td></tr>
> <tr><td>cell 2</td><td>cell 3</td></tr>
> </tbody>
> </table>
>
> I'm planning to fix this issues, to cover more basic html conversions.
>
> You can see what can do pyfpdf in this file:http://pyfpdf.googlecode.com/files/html.pdf
>
> BTW, did you see the new visual designer of pdf templates?
>
> http://code.google.com/p/pyfpdf/wiki/Templates?ts=1306512231&updated=...
>
> It is a wx application, and I'm planning to connect it using DAL to
> ease template/report generation (I think this is much easier and
> manageable way  than converting html).
>
> Best regards,
>
> Mariano Reingarthttp://www.sistemasagiles.com.arhttp://reingart.blogspot.com
>
> On Fri, May 27, 2011 at 1:35 AM, Massimo Di Pierro
>

Massimo Di Pierro

unread,
May 30, 2011, 1:19:51 AM5/30/11
to web2py-users
In trunk, web2py tries to use markmin2pdflatex is installed. If not it
uses pyfpdf. pyfpdf fails on some html, for example if table do not
follow the pyfpdf specs. I believe Marino is working on making pyfpdf
more forgiving.

Massimo

Martin Weissenboeck

unread,
May 30, 2011, 1:22:34 AM5/30/11
to web...@googlegroups.com
Massimo, does markmin2pdflatex understand utf-8?

2011/5/30 Massimo Di Pierro <massimo....@gmail.com>

Mariano Reingart

unread,
May 30, 2011, 10:39:27 AM5/30/11
to web...@googlegroups.com
@mart: yes, the visual designer requires only wxpython (and pyfpdf).

I'm working on html conversion enhancements and there are some advance
on utf-8 support, they will be fixed soon.

Best regards,

Jason Brower

unread,
May 30, 2011, 2:06:32 PM5/30/11
to web...@googlegroups.com
Me thinks of an HTML version in Javascript built into web2py.
Me faints.
---
Jason

Massimo Di Pierro

unread,
May 30, 2011, 4:48:52 PM5/30/11
to web2py-users
I think we just need ANY html editor... the only issue are TABLEs.

On May 30, 1:06 pm, Jason Brower <encomp...@gmail.com> wrote:
> Me thinks of an HTML version in Javascript built into web2py.
> Me faints.
> ---
> Jason
>
> On 05/30/2011 05:39 PM, Mariano Reingart wrote:
>
>
>
>
>
>
>
> > @mart: yes, the visual designer requires only wxpython (and pyfpdf).
>
> > I'm working on html conversion enhancements and there are some advance
> > on utf-8 support, they will be fixed soon.
>
> > Best regards,
>
> > Mariano Reingart
> >http://www.sistemasagiles.com.ar
> >http://reingart.blogspot.com
>
> > Mariano Reingart
> >http://www.sistemasagiles.com.ar
> >http://reingart.blogspot.com
>
> > On Mon, May 30, 2011 at 2:19 AM, Massimo Di Pierro
> > <massimo.dipie...@gmail.com>  wrote:
Reply all
Reply to author
Forward
0 new messages