Do Flask/Jinja2 have a provision to save rendered templates during debugging? - emacs

While debugging it's useful to view the rendered HTML and JS templates through a "view source" menu item in a browser, but doing so forces one to use the UI of the browser.
Does Jinja2 (or Flask) provide a facility to save the last n rendered templates on the server? It would then be possible to use one's favorite editor to view the rendered files, along with using one's familiar font-locking and search facilities.
It's of course possible to implement such a facility by hand, but doing so smacks too much like peppering one's programs while debugging with print statements, an approach that doesn't scale. I'm seeking a better alternative.

I'd think the easiest thing to do would be to use the after_request hook.
from flask import g
#main.route('/')
def index():
models = Model.query.all()
g.template = 'index'
return render_template('index.html', models=models)
#main.after_request
def store_template(response):
if hasattr(g, 'template'):
with open('debug/{0}-{1}'.format(datetime.now(), g.template), 'w') as f:
f.write(response.data)
return response
Here are the docs.
http://flask.pocoo.org/snippets/53/
As far as only collecting the last n templates I'd likely setup a cron job to do that. Here is an example
import os
from datetime import datetime
def make_files(n):
text = '''
<html>
</html>
'''
for a in range(n):
with open('debug/index-{0}.html'.format(datetime.now()), 'w') as f:
f.write(text)
def get_files(dir):
return [file for file in os.listdir(dir) if file.endswith('.html')]
def delete_files(dir, files, amount_kept):
rev = files[::-1]
for file in rev[amount_kept:]:
loc = dir + '/' + file
os.remove(loc)
if __name__ == '__main__':
make_files(7)
files = get_files('debug')
print files
delete_files('debug', files, 5)
files = get_files('debug')
print files
EDIT
reversed order of files inside the delete function so it will keep the most recent files. Also unable to find a way of accessing the original template name to avoid hardcoding.
EDIT 2
Alright so updated it to show how you can use flask.g to pass the template name to the after_request function
docs http://flask.pocoo.org/docs/0.11/testing/#faking-resources

Related

Python w/QT Creator form - Possible to grab multiple values?

I'm surprised to not find a previous question about this, but I did give an honest try before posting.
I've created a ui with Qt Creator which contains quite a few QtWidgets of type QLineEdit, QTextEdit, and QCheckbox. I've used pyuic5 to convert to a .py file for use in a small python app. I've successfully got the form connected and working, but this is my first time using python with forms.
I'm searching to see if there is a built-in function or object that would allow me to pull the ObjectNames and Values of all widgets contained within the GUI form and store them in a dictionary with associated keys:values, because I need to send off the information for post-processing.
I guess something like this would work manually:
...
dict = []
dict['checkboxName1'] = self.checkboxName1.isChecked()
dict['checkboxName2'] = self.checkboxName2.isChecked()
dict['checkboxName3'] = self.checkboxName3.isChecked()
dict['checkboxName4'] = self.checkboxName4.isChecked()
dict['lineEditName1'] = self.lineEditName1.text()
... and on and on
But is there a way to grab all the objects and loop through them, even if each different type (i.e. checkboxes, lineedits, etc) needs to be done separately?
I hope I've explained that clearly.
Thank you.
Finally got it working. Couldn't find a python specific example anywhere, so through trial and error this worked perfectly. I'm including the entire working code of a .py file that can generate a list of all QCheckBox objectNames on a properly referenced form.
I named my form main_form.ui from within Qt Creator. I then converted it into a .py file with pyuic5
pyuic5 main_form.ui -o main_form.py
This is the contents of a sandbox.py file:
from PyQt5 import QtCore, QtGui, QtWidgets
import sys
import main_form
# the name of my Qt Creator .ui form converted to main_form.py with pyuic5
# pyuic5 original_form_name_in_creator.ui -o main_form.py
class MainApp(QtWidgets.QMainWindow, main_form.Ui_MainWindow):
def __init__(self):
super(self.__class__, self).__init__()
self.setupUi(self)
# Push button object on main_form named btn_test
self.btn_test.clicked.connect(self.runTest)
def runTest(self):
# I believe this creates a List of all QCheckBox objects on entire UI page
c = self.findChildren(QtWidgets.QCheckBox)
# This is just to show how to access objectName property as an example
for box in c:
print(box.objectName())
def main():
app = QtWidgets.QApplication(sys.argv) # A new instance of QApplication
form = MainApp() # We set the form to be our ExampleApp (design)
form.show() # Show the form
app.exec_() # and execute the app
if __name__ == '__main__': # if we're running file directly and not importing it
main() # run the main function
See QObject::findChildren()
In C++ the template argument would allow one to specify which type of widget to retrieve, e.g. to just retrieve the QLineEdit objects, but I don't know if or how that is mapped into Python.
Might need to retrieve all types and then switch handling while iterating over the resulting list.

Downloadable xml files in Play Framework

I am a Scala/PlayFramework noob here, so please be easy on me :).
I am trying to create an action (serving a GET request) so that when I enter the url in the browser, the browser should download the file. So far I have this:
def sepaCreditXml() = Action {
val data: SepaCreditTransfer = invoiceService.sepaCredit()
val content: HtmlFormat.Appendable = views.html.sepacredittransfer(data)
Ok(content)
}
What it does is basically show the XML in the browser (whereas I actually want it to download the file). Also, I have two problems with it:
I am not sure if using Play's templating "views.html..." is the best idea to create an XML template. Is it good/simple enough or should I use a different solution for this?
I have found Ok.sendFile in the Play's documentation. But it needs a java.io.File. I don't know how to create a File from HtmlFormat.Appendable. I would prefer to create a file in-memory, i.e. no new File("/tmp/temporary.xml").
EDIT: Here SepaCreditTransfer is a case class holding some data. Nothing special.
I think it's quite normal for browsers to visualize XML instead of downloading it. Have you tried to use the application/force-download content type header, like this?
def sepaCreditXml() = Action {
val data: SepaCreditTransfer = invoiceService.sepaCredit()
val content: HtmlFormat.Appendable = views.html.sepacredittransfer(data)
Ok(content).withHeaders("Content-Type" -> "application/force-download")
}

Rendering Plone SchemaAddForm without main_template?

I'm attempting to write a Plone add-on that requires an "Add new" form. So far, I've managed to get this working very nicely using plone.directives.form.SchemaAddForm. I have the '##create-snippet' view registered in configure.zcml, and it works perfectly when I view the page normally.
However, the ultimate goal of this project is to get this add form into a TinyMCE popup window. I've created a working TinyMCE plugin for another, irrelevant portion of the add-on, and gotten that working well. However, when I try to navigate to my "##create-snippets" view in a tinyMCE window, I get:
LocationError: (Products.Five.metaclass.DirectoryResource2 object at 0x107162fd0, 'main_template')
My understanding of this issue is that, essentially, the SchemaAddForm class (or one of it's super classes, to be exact) wraps the form with the main Plone main_template when it renders the form. Since TinyMCE windows are their own, isolated little worlds, the template isn't available, and, therefore, cannot be rendered....or something like that? Please correct me if I'm way off.
What I really want to know, is if it's possible to set things up so only the form itself will render, without using the main_template? I would REALLY like to be able to take advantage of the schema-based forms (and their built-in validation), but still be able to keep everything within a TinyMCE window.
I've toyed around with creating my own ViewPageTemplateFile() template, and getting the form to render (somehow?) within it, but frankly, I have no idea how....or if that's even possible.
Please feel free to ask for more information if there's something I've omitted. I'm kinda new to this type of Plone development.
The code generating the form:
from Products.Five.browser import BrowserView
from uwosh.snippets.snippet import SnippetManager
from plone.directives.form import SchemaAddForm
import zope.interface
from plone.autoform.form import AutoExtensibleForm
import zope.schema
from plone.directives import form
import z3c
from Products.statusmessages.interfaces import IStatusMessage
_ = zope.i18nmessageid.MessageFactory(u'uwosh.snippets')
class ISnippet(form.Schema):
title = zope.schema.TextLine(
title=u'Title',
description=u'The title to associate with the snippet.',
required=True)
description = zope.schema.TextLine(
title=u'Description',
description=u'A short explanation of the snippet.',
required=True)
body = zope.schema.Text(
title=u'Body',
description=u'The actual content to be rendered on the page.',
required=True)
class SnippetForm(SchemaAddForm):
schema = ISnippet
#z3c.form.button.buttonAndHandler(_('Save'), name='save')
def handleAdd(self, action):
data, errors = self.extractData()
if errors:
self.status = self.formErrorsMessage
return
obj = self.createAndAdd(data)
if obj is not None:
# mark only as finished if we get the new object
self._finishedAdd = True
IStatusMessage(self.request).addStatusMessage(_(u"Snippet saved"), "info")
#z3c.form.button.buttonAndHandler(_(u'Cancel'), name='cancel')
def handleCancel(self, action):
IStatusMessage(self.request).addStatusMessage(_(u"Add New Snippet operation cancelled"), "info")
self.request.response.redirect(self.nextURL())
def create(self, data):
sm = SnippetManager()
#TODO:
#Include support for different folders from this form.
snippet = sm.createSnippet(data['title'], None ,data)
return snippet
def add(self, object):
#Since, for now, snippets are based upon ATDocuments, their creation is fairly staight-forward.
#So, we don't really need separate Add/Create steps.
return
def nextURL(self):
return self.context.absolute_url() + '/##create-snippet'

How can I serve mostly static pages from a scala Play! application like an "About" page in different languages?

I am building an application using the Play! framework version 2.0.4. Some pages that are legally required such as an imprint mostly contain lots (some 10k each) of static text which I would like to provide in different languages.
In versions 1.x there was an #include directive that allowed to construct the actual resource path using the current Lang.
What is the recommended way of implementing sth similar with Play 2.x?
Thank you & best regards,
Erich
I'm not 100% certain how you implement it as of now, but here's what I've come up with.
You could just write your own include helper. Save the following in a file Helpers.scala in your views folder. Explanations are in the code's comments.
package views.html.helper
object include {
import play.api.templates.Html
import play.api.Play
import play.api.Play.current
import play.api.i18n._
// The default is to look in the public dir, but you can change it if necessary
def apply(filePath: String, rootDir: String = "public")(implicit lang: Lang): Html = {
// Split filePath at name and suffix to insert the language in between them
val (fileName, suffix) = filePath.splitAt(filePath.lastIndexOf("."))
// Retrieve the file with the current language, or as a fallback, without any suffix
val maybeFile =
Play.getExistingFile(rootDir + "/" + fileName + "_" + lang.language + suffix).
orElse(Play.getExistingFile(rootDir + "/" + filePath))
// Read the file's content and wrap it in HTML or return an error message
maybeFile map { file =>
val content = scala.io.Source.fromFile(file).mkString
Html(content)
} getOrElse Html("File Not Found")
}
}
Now in your imprint.scala.html you could call it like this:
#()(implicit lang: Lang)
#import helper._
#include("static/imprint.html")
Way showed by Schleichardt was used in play-authenticate to select mail templates in different languages and now it's changed to work with reflections on the controller, so maybe it can be interesting for you. Anyway it was intendent to keep standard templating possibilities (cause each mail need to be personalized before send)
For static info pages, you can just save the code for each language with suffix ie. impressum_en.html, impressum_de.html in the file system and use simple controller which will find file with proper suffix and return its content exactly as it is... all you need probably to return Ok(fileContent) and set the Content-Type manually to text/html.
Other option is doing the similar thing but storing it in the DB, so you can create simple back-end and edit it with browser.
If you still need to replace some elements, you can do it with some ###MARKER### in the code + simple String operations, or with JavaScript on the client side.
Templates in 2.0 work a bit differently. The Scala based templates are compiled. From one template instead of 'including' another, you can make a call to it. I'm not sure exactly what you mean by the language thing. In 2.0 though, a parameter to the template could be the language.
Example template named 'included' in package whateverpackage.
#(lang: Lang)
...
Example calling a template named 'included':
#import whateverpackage._
#included(Lang("en"))
#()(implicit lang: Lang)
#main(Messages("imprint")) {
#lang match {
case Lang("de", _) => { #germanImprint() #* uses app/views/germanImprint.scala.html file *#}
case _ => { #englishImprint() }
}
}

Trac - Get date of last commit of a specific repository file in wiki page

I'm using Trac to manage my projects. Some guys have to take a regular look to my wiki pages to watch changes in a special file. Therefore I have a link on my wikipage. Something link this:
[source:MyRepository/trunk/subfolder/file.pdf#head The file to read]
What I would like to have is the following output:
The file to read (last commited: 11/01/15 at 08:52am)
Any ideas how to manage that in trac wiki?
You will probably have to write a small plugin for that, something like the following:
from genshi.builder import tag
from trac.util.datefmt import format_datetime
from trac.util.translation import _
from trac.versioncontrol.api import RepositoryManager
from trac.wiki.api import parse_args
from trac.wiki.macros import WikiMacroBase
class SourceMacro(WikiMacroBase):
def expand_macro(self, formatter, name, content):
args, kwargs = parse_args(content)
path = args[0]
label = kwargs.get('label', path)
rm = RepositoryManager(self.env)
reponame, repos, path = rm.get_repository_by_path(path)
node = repos.get_node(path)
href = formatter.href.browser(reponame or None, path)
return tag(tag.a(label, href=href),
_(' (last committed: %(date)s)',
date=format_datetime(node.last_modified)))
(For Trac 0.12 or later, error handling left as the dreaded exercise to the reader.)
Place this in a file file named source_link.py in the plugins directory of your Trac environment. Then you can reference your files with the following macro:
[[Source(MyRepository/trunk/subfolder/file.pdf)]]
or if you want a specific label:
[[Source(MyRepository/trunk/subfolder/file.pdf, label=The file to read)]]