Forum Archive

Export code and output as pdf file

johnsilvabr

Hello guys! how are you doing?
Ireally need to know how can I export in PDF the code and the output of a program in Pythonista. I’m having this programming class where the professor asked for us to send only the .pdf files containing the solution of the exercises + the code that we wrote. It’s as simple as it sounds and still I’m so mad I didn’t figure it out, sorry..

I searched in quite a lot of topics but couldn’t find anywhere, only that maybe has something to do with Py2PDF on Pythonista.

cvp

@johnsilvabr Perhaps this?

mikael

@cvp, dependecy on PyQt seems problematic? Looks like @ccc could comment, listed as contributor.

cvp

@mikael You're right, I'll search another way, that should be easy, I hope

starting from this

mikael

@cvp, but aren’t we making this unnecessarily difficult? In Apple Shortcuts, there is a Create PDF action, and the Gallery includes a ready-made script for that (select the margins switch to make it look nicer).

When viewing the code in Pythonista, select wrench, Share, Shortcuts and pick this Shortcut - done.

Something fancy could be created to automate this for a large number of files and their outputs, but for the OP issue, probably enough?

cvp

@mikael Sorry, which shortcut? If it exists 😂,I agree with you. I often write a little script for the fun and that allows me to postpone my (too) big projects

Edit: bad read of your post, I think there was an Apple standard shortcut, sorry, one more time

Edit2: very good but I wanted to get the syntax highlighting like in editor

cvp

@johnsilvabr this little script
- is based on an @omz sample
- needs that you install xhtml2pdf via stash, then pip install xhtml2pdf
- can be added as a tool via wrench menu
- when executed on an edited script, creates a file script_name.pdf with highlighted code

# code needs to install xhtml2pdf in site-packages
# via stash/pip install xhtml2pdf
import editor
import os
from pygments import highlight
from pygments.lexers import PythonLexer
from pygments.formatters import HtmlFormatter
from pygments.styles import get_style_by_name
from xhtml2pdf import pisa

# Syntax-highlight code
# from omz code at https://forum.omz-software.com/topic/1950/syntax-highlight-python-code-on-screen-while-running
code = editor.get_text()
html_formatter = HtmlFormatter(style='colorful')
highlighted_code = highlight(code, PythonLexer(), html_formatter)
styles = html_formatter.get_style_defs()
html = '<html><head><style>%s</style></head><body>%s</body></html>' % (styles, highlighted_code)

# html -> pdf
path = editor.get_path()
file_name = os.path.basename(path)
i = file_name.rfind('.')
if i>= 0:
    file_name = file_name[:i] + '.pdf'

with open(file_name, 'wb') as fil:
    pisa.CreatePDF(html,fil)

mikael

@cvp, added an API call to hilite.me service to the Shortcut and got this (with line numbering included).

cvp

@mikael I had also thought to an online conversion html to pdf but it needs Internet and you have to share/select Shortcuts/select shortcut instead of tools/select tool
thus one step more 😂

all I deduce is that we have a great application with Pythonista

Edit: could you share the shortcut, I'm interested, thanks

Edit2: and your solution provides lines numbers, I'm giving up, you're the best

JonB

Note the professor wants both code AND program output.
(output, i can understand... i have no idea why anyone would ever want to see python code in pdf form)

I imagine also that he might expect some kind of header/format?

cvp

@JonB Agree, but passing via html helps for other infos like headers..., isn'it.

mikael

@cvp, I agree that an all-Pythonista solution would be nicer and provide more opportunities to handle several files with a single click. Anyway, here’s the shortcut.

cvp

@mikael Thanks a lot. I didn't even know this feature of posting to an API in Shortcuts app.
I like it.

I always try to process all in Pythonista but I wait the day when @omz would add the functionality to share/open a file to a specific app without passing via a menu, because Shortcuts can do it...

ccc
path = editor.get_path()
file_name = os.path.basename(path)
i = file_name.rfind('.')
if i>= 0:
    file_name = file_name[:i] + '.pdf'

# Can be rewritten as...

file_name = os.path.basename(os.path.splitext(editor.get_path())[0]) + '.pdf'
cvp

@ccc Thanks. Shame on me, I knew it.... 😢

Edit: also modified in my github

cvp

Still to find in the tool the way to get the console output to add it to the pdf...

mikael

@cvp, easier to redirect all output to a file?

cvp

@mikael Sure but needs to change the code?

cvp

This code should return the console content

from objc_util import *

def GetConsoleText():
    print('called')
    win = ObjCClass('UIApplication').sharedApplication().keyWindow()
    main_view = win.rootViewController().view() 
    ret = '' 
    def analyze(v):
        ret = None
        for sv in v.subviews():
            if 'textview' in str(sv._get_objc_classname()).lower():
                if 'OMTextEditorView' not in str(sv.superview()._get_objc_classname()): # not TextView of script
                    return sv.text()
            ret = analyze(sv)
            if ret:
                return ret
    ret = analyze(main_view)
    return ret

Thus full code can be found here

mikael

@cvp, no need to change the code:

import contextlib, runpy

with open('ex1_result.txt', 'w') as f:
  with contextlib.redirect_stdout(f):
    runpy.run_module('ex1')
cvp

@mikael I didn't know this functionality.
But, that will say that the whole console is redirected, even if your script asks questions...
Anyway, this is a shorter and general solution.

mikael

@cvp, agree, case by case either option may be more applicable. I wanted to remind us of both of these capabilities (running a py file and redirecting output), as both might come handy in various contexts.

cvp

@mikael "My" solution is not very elegant and I'm not sure it is robust and would stay operational in next versions of Pythonista.
I searched this way for the fun because I I thought that if the console is displayed and is scrollable, it has to be in a TextView...
And during my tests, I discovered the "console 🔽 " button and its pop up menu where you can copy all the console...In the past, I often selected the whole text and copied without knowing this possibility 😢