Hello, I am working on a HTML builder type Flask extension, similar to the HTML builder in Werkzeug, but with more features, which target full HTML document generation. It has support for HTML comments, doctype definition, and both escaped/unescaped HTML text, etc. It takes advantage of the Werkzeug endpoint system and defines template inheritance mechanisms using decorators around it. I targeted real-world HTML document generation with that. The source is still in a private repository, since I need to clean that up as much as possible and make sure test coverage is full, but I wrote a short use case application in which I included detailed description: https://gist.github.com/f5de9c33341400cc01b6 I will make the repository public in the following days. I will be glad if I receive some feedback about it. Any comments? Regards, Zahari
Hey guys, I just committed my Flask-HTMLBuilder extension: source: http://github.com/majorz/flask-htmlbuilder documentation: http://majorz.github.com/flask-htmlbuilder/ I used the Flask extension generator for initial skeleton creation. Documentation is using flask_small theme. I tried to follow closely the recommendations and looked how other extensions were done. I would to ask for an initial review process. Thanks, Zahari On Tue, Nov 2, 2010 at 7:39 PM, Zahari Petkov <zarchaoz@gmail.com> wrote: > Hello, > > I am working on a HTML builder type Flask extension, similar to the > HTML builder in Werkzeug, but with more features, which target full > HTML document generation. It has support for HTML comments, doctype > definition, and both escaped/unescaped HTML text, etc. It takes > advantage of the Werkzeug endpoint system and defines template > inheritance mechanisms using decorators around it. I targeted > real-world HTML document generation with that. > > The source is still in a private repository, since I need to clean > that up as much as possible and make sure test coverage is full, but I > wrote a short use case application in which I included detailed > description: > https://gist.github.com/f5de9c33341400cc01b6 > > I will make the repository public in the following days. > > I will be glad if I receive some feedback about it. Any comments? > > Regards, > Zahari >
On Mon, 2010-11-08 at 01:32 +0200, Zahari Petkov wrote: > Hey guys, > > I just committed my Flask-HTMLBuilder extension: > source: http://github.com/majorz/flask-htmlbuilder > documentation: http://majorz.github.com/flask-htmlbuilder/ > > I used the Flask extension generator for initial skeleton creation. > Documentation is using flask_small theme. I tried to follow closely > the recommendations and looked how other extensions were done. I would > to ask for an initial review process. > > Thanks, > Zahari > > On Tue, Nov 2, 2010 at 7:39 PM, Zahari Petkov <zarchaoz@gmail.com> wrote: > > Hello, > > > > I am working on a HTML builder type Flask extension, similar to the > > HTML builder in Werkzeug, but with more features, which target full > > HTML document generation. It has support for HTML comments, doctype > > definition, and both escaped/unescaped HTML text, etc. It takes > > advantage of the Werkzeug endpoint system and defines template > > inheritance mechanisms using decorators around it. I targeted > > real-world HTML document generation with that. > > > > The source is still in a private repository, since I need to clean > > that up as much as possible and make sure test coverage is full, but I > > wrote a short use case application in which I included detailed > > description: > > https://gist.github.com/f5de9c33341400cc01b6 > > > > I will make the repository public in the following days. > > > > I will be glad if I receive some feedback about it. Any comments? > > > > Regards, > > Zahari > > Some quick thoughts: - html.doctype() could take a format, type and version and generate a corresponding doctype, i.e. html.doctype('html', 4, 'strict'), with some useful defaults. - Markup() from Jinja and Genshi should work as substitutes for html.safe() if they don't already. Some Flask extensions rely on this. - I still think you should use genshi.builder. You'd get a lot for free, including doctypes. It's not possible to output valid HTML 4 with your implementation. I can help you with how to use Genshi.
Thanks Dag, my comments are inlined. On Mon, Nov 8, 2010 at 1:30 PM, Dag Odenhall <dag.odenhall@gmail.com> wrote: > On Mon, 2010-11-08 at 01:32 +0200, Zahari Petkov wrote: >> Hey guys, >> >> I just committed my Flask-HTMLBuilder extension: >> source: http://github.com/majorz/flask-htmlbuilder >> documentation: http://majorz.github.com/flask-htmlbuilder/ >> >> I used the Flask extension generator for initial skeleton creation. >> Documentation is using flask_small theme. I tried to follow closely >> the recommendations and looked how other extensions were done. I would >> to ask for an initial review process. >> >> Thanks, >> Zahari >> > > Some quick thoughts: > > - html.doctype() could take a format, type and version and generate a > corresponding doctype, i.e. html.doctype('html', 4, 'strict'), with some > useful defaults. That sounds a nice idea. I actually left thinking about compatibility with HTML4 for a later time, since I wanted to make sure HTML5 is covered well. But I will definitely do it, unless something convinces me that HTML5 support is far from enough. Basically HTML4 support in my library is needed only if someone wants to use my extension as snippets in existing HTML4 markup. Otherwise there is no reason he should not go with HTML5, since it is backwards compatible with HTML4 and cleaner. XHTML2 is officially dead now, and people from both working groups are working on HTML5. I particularly like that comic: http://www.smashingmagazine.com/2009/07/29/misunderstanding-markup-xhtml-2-comic-strip/ > - Markup() from Jinja and Genshi should work as substitutes for > html.safe() if they don't already. Some Flask extensions rely on this. I will look at Markup of Jinja and Genshi, to see whether I am missing something. html.safe is quite a simple operation in my extension - just returning a string as is without escaping it. > - I still think you should use genshi.builder. You'd get a lot for free, > including doctypes. It's not possible to output valid HTML 4 with your > implementation. I can help you with how to use Genshi. Yes, I will add support for closing void elements with and without slashes. Since HTML5 supports them both (and IMO xhtml way is cleaner), I thought for now it will suffice just the xhtml way. It is a matter of a few additional lines in the code. I am still not convinced that I should use Genshi, because I do not see why, but I guess I may miss something. Can you try to elaborate more on that, please? Thanks, Zahari
On Mon, 2010-11-08 at 14:17 +0200, Zahari Petkov wrote: > Thanks Dag, my comments are inlined. > > On Mon, Nov 8, 2010 at 1:30 PM, Dag Odenhall <dag.odenhall@gmail.com> wrote: > > On Mon, 2010-11-08 at 01:32 +0200, Zahari Petkov wrote: > >> Hey guys, > >> > >> I just committed my Flask-HTMLBuilder extension: > >> source: http://github.com/majorz/flask-htmlbuilder > >> documentation: http://majorz.github.com/flask-htmlbuilder/ > >> > >> I used the Flask extension generator for initial skeleton creation. > >> Documentation is using flask_small theme. I tried to follow closely > >> the recommendations and looked how other extensions were done. I would > >> to ask for an initial review process. > >> > >> Thanks, > >> Zahari > >> > > > > Some quick thoughts: > > > > - html.doctype() could take a format, type and version and generate a > > corresponding doctype, i.e. html.doctype('html', 4, 'strict'), with some > > useful defaults. > > That sounds a nice idea. I actually left thinking about compatibility > with HTML4 for a later time, since I wanted to make sure HTML5 is > covered well. But I will definitely do it, unless something convinces > me that HTML5 support is far from enough. Basically HTML4 support in > my library is needed only if someone wants to use my extension as > snippets in existing HTML4 markup. Otherwise there is no reason he > should not go with HTML5, since it is backwards compatible with HTML4 > and cleaner. XHTML2 is officially dead now, and people from both > working groups are working on HTML5. I particularly like that comic: > http://www.smashingmagazine.com/2009/07/29/misunderstanding-markup-xhtml-2-comic-strip/ http://www.infoworld.com/d/developer-world/w3c-hold-html5-in-websites-041 http://webkit.org/blog/68/understanding-html-xml-and-xhtml/ <tag /> is invalid HTML 4, and many browsers parse HTML 5 as HTML 4. No major browser actually supports XHTML. <tag /> isn't even sensible XML. <script src/> can screw up some engines a lot, does your implementation handle that situation? Genshi does all that for you, you can output HTML 4-ish, XHTML-ish or pure XML-ish, on the fly. HTML 5 is only backwards compatible if used as HTML 4, and you're using it as XHTML. > > > - Markup() from Jinja and Genshi should work as substitutes for > > html.safe() if they don't already. Some Flask extensions rely on this. > > I will look at Markup of Jinja and Genshi, to see whether I am missing > something. html.safe is quite a simple operation in my extension - > just returning a string as is without escaping it. Then it should work, but possibly you want to escape strings passed as content to a tag, unless it hasattr '__html__' and in that case use that. That might be safer, and should work with Markup(). Did I mention that Genshi's builder does this exactly already? :) > > > - I still think you should use genshi.builder. You'd get a lot for free, > > including doctypes. It's not possible to output valid HTML 4 with your > > implementation. I can help you with how to use Genshi. > > Yes, I will add support for closing void elements with and without > slashes. Since HTML5 supports them both (and IMO xhtml way is > cleaner), I thought for now it will suffice just the xhtml way. It is > a matter of a few additional lines in the code. Not that few, you'd have to keep track of which tags are content tags or not in HTML. Not that big a deal of course, but, hey guess what: Genshi does this exactly already. > > I am still not convinced that I should use Genshi, because I do not > see why, but I guess I may miss something. Can you try to elaborate > more on that, please? Why *not*? You seem to have a case of the NIH. You're complicating what should be a simple extension (Flask extensions should usually be thin wrappers around existing libraries), bloating your source, reinventing the wheel and ending up with a less powerful tool. Is it dependency fear, feeling Genshi does more than you need so it's a heavy dependency? Have you considered that Flask depends on Werkzeug, of which you don't use everything, and Jinja, which you don't use at all with your extension? Don't fear dependencies. BTW I think the Genshi builder has the exact same API as your builder, building-wise. Anything you don't like you can just hide in your extension. > > Thanks, > Zahari
On Mon, Nov 8, 2010 at 3:38 PM, Dag Odenhall <dag.odenhall@gmail.com> wrote: > On Mon, 2010-11-08 at 14:17 +0200, Zahari Petkov wrote: >> Thanks Dag, my comments are inlined. >> >> On Mon, Nov 8, 2010 at 1:30 PM, Dag Odenhall <dag.odenhall@gmail.com> wrote: >> > On Mon, 2010-11-08 at 01:32 +0200, Zahari Petkov wrote: >> >> Hey guys, >> >> >> >> I just committed my Flask-HTMLBuilder extension: >> >> source: http://github.com/majorz/flask-htmlbuilder >> >> documentation: http://majorz.github.com/flask-htmlbuilder/ >> >> >> >> I used the Flask extension generator for initial skeleton creation. >> >> Documentation is using flask_small theme. I tried to follow closely >> >> the recommendations and looked how other extensions were done. I would >> >> to ask for an initial review process. >> >> >> >> Thanks, >> >> Zahari >> >> >> > >> > Some quick thoughts: >> > >> > - html.doctype() could take a format, type and version and generate a >> > corresponding doctype, i.e. html.doctype('html', 4, 'strict'), with some >> > useful defaults. >> >> That sounds a nice idea. I actually left thinking about compatibility >> with HTML4 for a later time, since I wanted to make sure HTML5 is >> covered well. But I will definitely do it, unless something convinces >> me that HTML5 support is far from enough. Basically HTML4 support in >> my library is needed only if someone wants to use my extension as >> snippets in existing HTML4 markup. Otherwise there is no reason he >> should not go with HTML5, since it is backwards compatible with HTML4 >> and cleaner. XHTML2 is officially dead now, and people from both >> working groups are working on HTML5. I particularly like that comic: >> http://www.smashingmagazine.com/2009/07/29/misunderstanding-markup-xhtml-2-comic-strip/ > > http://www.infoworld.com/d/developer-world/w3c-hold-html5-in-websites-041 > That article is about the newest features in HTML5, not about the backwards compatibility, so I think it is misleading. Furthermore, taking into account that projects like Modernizr exist and prove to be working well across older browsers like IE6, a developer may use feature detection capabilities to decides on newer HTML5 features. BTW, the most used website in the world (google.com) is serving HTML5. > http://webkit.org/blog/68/understanding-html-xml-and-xhtml/ > > <tag /> is invalid HTML 4, and many browsers parse HTML 5 as HTML 4. No > major browser actually supports XHTML. <tag /> isn't even sensible XML. > <script src/> can screw up some engines a lot, does your implementation > handle that situation? Genshi does all that for you, you can output HTML > 4-ish, XHTML-ish or pure XML-ish, on the fly. HTML 5 is only backwards > compatible if used as HTML 4, and you're using it as XHTML. > As I said I will allow users to choose between both ways of closing void elements, I just need to figure out an elegant way of doing it. I do not intend to put validation capabilities to my extension for now. Let's take your script example actually: HTML: <script src="/js/mighty.js" /> Python: html.script(src='/js/mighty.js') - Bad HTML: <script src="/js/mighty.js"></script> Python: html.script(src='/js/mighty.js')() - Problem solved, yeah? Jeffrey Zeldman uses HTML5 with XHTML dialect for closing void elements. His website works nice in IE6. I think that clarifies pretty well that my approach is backwards compatible as well. >> >> > - Markup() from Jinja and Genshi should work as substitutes for >> > html.safe() if they don't already. Some Flask extensions rely on this. >> >> I will look at Markup of Jinja and Genshi, to see whether I am missing >> something. html.safe is quite a simple operation in my extension - >> just returning a string as is without escaping it. > > Then it should work, but possibly you want to escape strings passed as > content to a tag, unless it hasattr '__html__' and in that case use > that. That might be safer, and should work with Markup(). Did I mention > that Genshi's builder does this exactly already? :) Thanks. Armin clarified that I should work on that to get approval and will do it. > >> >> > - I still think you should use genshi.builder. You'd get a lot for free, >> > including doctypes. It's not possible to output valid HTML 4 with your >> > implementation. I can help you with how to use Genshi. >> >> Yes, I will add support for closing void elements with and without >> slashes. Since HTML5 supports them both (and IMO xhtml way is >> cleaner), I thought for now it will suffice just the xhtml way. It is >> a matter of a few additional lines in the code. > > Not that few, you'd have to keep track of which tags are content tags or > not in HTML. Not that big a deal of course, but, hey guess what: Genshi > does this exactly already. > Why should I do that? I prefer to leave those to the user and not provide validation as I talked above. >> >> I am still not convinced that I should use Genshi, because I do not >> see why, but I guess I may miss something. Can you try to elaborate >> more on that, please? > > Why *not*? You seem to have a case of the NIH. You're complicating what > should be a simple extension (Flask extensions should usually be thin > wrappers around existing libraries), bloating your source, reinventing > the wheel and ending up with a less powerful tool. > My source is definitely not bloated, nor is less powerful. We may say that it is still work in progress though - that's why my version there is 0.3 (the previous two were internal non-flask related). While Flask extensions normally are just wrappers (I agree), that does not invalidate the opposite approach in any way. > Is it dependency fear, feeling Genshi does more than you need so it's a > heavy dependency? Have you considered that Flask depends on Werkzeug, of > which you don't use everything, and Jinja, which you don't use at all > with your extension? Don't fear dependencies. > > BTW I think the Genshi builder has the exact same API as your builder, > building-wise. Anything you don't like you can just hide in your > extension. To tell a joke, IMO, Genshi builder is quite less-powerful. I have concrete evidence with the standard Big Table template benchmark: Flask-HTMLBuilder builder 261.97 ms Werkzeug HTMLBuilder 196.30 ms Genshi tag builder 831.50 ms Genshi template 482.97 ms Genshi text template 343.76 ms Genshi template + tag builder 912.09 ms ElementTree 350.67 ms cElementTree 198.58 ms Django template 1046.46 ms As we can see it is 3-4 times slower, what so powerful about it... Okay, more seriously now. My API is different actually though there are a lot of similarities. One quick example with what you talked about: Me: >>> str(html.script(src='/js/mighty.js')()) '<script src="/js/mighty.js"></script>' Genshi: >>> str(tag.script(src='/js/mighty.js')()) '<script src="/js/mighty.js"/>' >>> str(tag.script(src='/js/mighty.js')('')) '<script src="/js/mighty.js"></script>' I do not like how Genshi does not put a space before the closing slash as well. And there is more to that, but it is useless to continue. Anyway, my idea is to have a Python-only solution. Genshi's main purpose is different, though it provides the builder module. I do not like mixing those concepts by introducing such dependency.
On Mon, 2010-11-08 at 17:58 +0200, Zahari Petkov wrote: > On Mon, Nov 8, 2010 at 3:38 PM, Dag Odenhall <dag.odenhall@gmail.com> wrote: > > On Mon, 2010-11-08 at 14:17 +0200, Zahari Petkov wrote: > >> Thanks Dag, my comments are inlined. > >> > >> On Mon, Nov 8, 2010 at 1:30 PM, Dag Odenhall <dag.odenhall@gmail.com> wrote: > >> > On Mon, 2010-11-08 at 01:32 +0200, Zahari Petkov wrote: > >> >> Hey guys, > >> >> > >> >> I just committed my Flask-HTMLBuilder extension: > >> >> source: http://github.com/majorz/flask-htmlbuilder > >> >> documentation: http://majorz.github.com/flask-htmlbuilder/ > >> >> > >> >> I used the Flask extension generator for initial skeleton creation. > >> >> Documentation is using flask_small theme. I tried to follow closely > >> >> the recommendations and looked how other extensions were done. I would > >> >> to ask for an initial review process. > >> >> > >> >> Thanks, > >> >> Zahari > >> >> > >> > > >> > Some quick thoughts: > >> > > >> > - html.doctype() could take a format, type and version and generate a > >> > corresponding doctype, i.e. html.doctype('html', 4, 'strict'), with some > >> > useful defaults. > >> > >> That sounds a nice idea. I actually left thinking about compatibility > >> with HTML4 for a later time, since I wanted to make sure HTML5 is > >> covered well. But I will definitely do it, unless something convinces > >> me that HTML5 support is far from enough. Basically HTML4 support in > >> my library is needed only if someone wants to use my extension as > >> snippets in existing HTML4 markup. Otherwise there is no reason he > >> should not go with HTML5, since it is backwards compatible with HTML4 > >> and cleaner. XHTML2 is officially dead now, and people from both > >> working groups are working on HTML5. I particularly like that comic: > >> http://www.smashingmagazine.com/2009/07/29/misunderstanding-markup-xhtml-2-comic-strip/ > > > > http://www.infoworld.com/d/developer-world/w3c-hold-html5-in-websites-041 > > > > That article is about the newest features in HTML5, not about the > backwards compatibility, so I think it is misleading. Furthermore, > taking into account that projects like Modernizr exist and prove to be > working well across older browsers like IE6, a developer may use > feature detection capabilities to decides on newer HTML5 features. > BTW, the most used website in the world (google.com) is serving HTML5. Just a note: I'm all for HTML 5, but supporting HTML 4 is still important today. > > > http://webkit.org/blog/68/understanding-html-xml-and-xhtml/ > > > > <tag /> is invalid HTML 4, and many browsers parse HTML 5 as HTML 4. No > > major browser actually supports XHTML. <tag /> isn't even sensible XML. > > <script src/> can screw up some engines a lot, does your implementation > > handle that situation? Genshi does all that for you, you can output HTML > > 4-ish, XHTML-ish or pure XML-ish, on the fly. HTML 5 is only backwards > > compatible if used as HTML 4, and you're using it as XHTML. > > > > As I said I will allow users to choose between both ways of closing > void elements, I just need to figure out an elegant way of doing it. I > do not intend to put validation capabilities to my extension for now. > Let's take your script example actually: > HTML: <script src="/js/mighty.js" /> Python: > html.script(src='/js/mighty.js') - Bad > HTML: <script src="/js/mighty.js"></script> Python: > html.script(src='/js/mighty.js')() - Problem solved, yeah? > > Jeffrey Zeldman uses HTML5 with XHTML dialect for closing void > elements. His website works nice in IE6. I think that clarifies pretty > well that my approach is backwards compatible as well. > > >> > >> > - Markup() from Jinja and Genshi should work as substitutes for > >> > html.safe() if they don't already. Some Flask extensions rely on this. > >> > >> I will look at Markup of Jinja and Genshi, to see whether I am missing > >> something. html.safe is quite a simple operation in my extension - > >> just returning a string as is without escaping it. > > > > Then it should work, but possibly you want to escape strings passed as > > content to a tag, unless it hasattr '__html__' and in that case use > > that. That might be safer, and should work with Markup(). Did I mention > > that Genshi's builder does this exactly already? :) > > Thanks. Armin clarified that I should work on that to get approval and > will do it. > > > > >> > >> > - I still think you should use genshi.builder. You'd get a lot for free, > >> > including doctypes. It's not possible to output valid HTML 4 with your > >> > implementation. I can help you with how to use Genshi. > >> > >> Yes, I will add support for closing void elements with and without > >> slashes. Since HTML5 supports them both (and IMO xhtml way is > >> cleaner), I thought for now it will suffice just the xhtml way. It is > >> a matter of a few additional lines in the code. > > > > Not that few, you'd have to keep track of which tags are content tags or > > not in HTML. Not that big a deal of course, but, hey guess what: Genshi > > does this exactly already. > > > > Why should I do that? I prefer to leave those to the user and not > provide validation as I talked above. Makes sense for an XML builder, less so for rendering output for the web IMHO. > > >> > >> I am still not convinced that I should use Genshi, because I do not > >> see why, but I guess I may miss something. Can you try to elaborate > >> more on that, please? > > > > Why *not*? You seem to have a case of the NIH. You're complicating what > > should be a simple extension (Flask extensions should usually be thin > > wrappers around existing libraries), bloating your source, reinventing > > the wheel and ending up with a less powerful tool. > > > > My source is definitely not bloated, nor is less powerful. We may say > that it is still work in progress though - that's why my version there > is 0.3 (the previous two were internal non-flask related). Sorry, I didn't mean to say that it was - only compared to a hypothetical source where the builder is a separate library. > > While Flask extensions normally are just wrappers (I agree), that does > not invalidate the opposite approach in any way. > > > Is it dependency fear, feeling Genshi does more than you need so it's a > > heavy dependency? Have you considered that Flask depends on Werkzeug, of > > which you don't use everything, and Jinja, which you don't use at all > > with your extension? Don't fear dependencies. > > > > BTW I think the Genshi builder has the exact same API as your builder, > > building-wise. Anything you don't like you can just hide in your > > extension. > > To tell a joke, IMO, Genshi builder is quite less-powerful. I have > concrete evidence with the standard Big Table template benchmark: > Flask-HTMLBuilder builder 261.97 ms > Werkzeug HTMLBuilder 196.30 ms > Genshi tag builder 831.50 ms > Genshi template 482.97 ms > Genshi text template 343.76 ms > Genshi template + tag builder 912.09 ms > ElementTree 350.67 ms > cElementTree 198.58 ms > Django template 1046.46 ms Irrelevant for most people. Django is clearly the slowest and yet a great lot of people use it in production systems. Templating is rarely a culprit. > > As we can see it is 3-4 times slower, what so powerful about it... > Okay, more seriously now. My API is different actually though there > are a lot of similarities. > > One quick example with what you talked about: > Me: > >>> str(html.script(src='/js/mighty.js')()) > '<script src="/js/mighty.js"></script>' > Genshi: > >>> str(tag.script(src='/js/mighty.js')()) > '<script src="/js/mighty.js"/>' > >>> str(tag.script(src='/js/mighty.js')('')) > '<script src="/js/mighty.js"></script>' > > I do not like how Genshi does not put a space before the closing slash > as well. And there is more to that, but it is useless to continue. >>> tag.hr().generate().render('html') '<hr>' >>> tag.hr().generate().render('xhtml') '<hr />' > > Anyway, my idea is to have a Python-only solution. Genshi's main > purpose is different, though it provides the builder module. I do not > like mixing those concepts by introducing such dependency. I at least think you should separate the Flask extension and your builder and make the latter a library in its own right. (Just wanted to provide a friendly advice with genshi.builder, I hope I'm not coming off too strong about it. +1 for adding to the set of Flask extensions.)
On Tue, Nov 9, 2010 at 1:45 AM, Dag Odenhall <dag.odenhall@gmail.com> wrote: > On Mon, 2010-11-08 at 17:58 +0200, Zahari Petkov wrote: >> On Mon, Nov 8, 2010 at 3:38 PM, Dag Odenhall <dag.odenhall@gmail.com> wrote: >> > On Mon, 2010-11-08 at 14:17 +0200, Zahari Petkov wrote: >> >> Thanks Dag, my comments are inlined. >> >> >> >> On Mon, Nov 8, 2010 at 1:30 PM, Dag Odenhall <dag.odenhall@gmail.com> wrote: >> >> > On Mon, 2010-11-08 at 01:32 +0200, Zahari Petkov wrote: >> >> >> Hey guys, >> >> >> >> >> >> I just committed my Flask-HTMLBuilder extension: >> >> >> source: http://github.com/majorz/flask-htmlbuilder >> >> >> documentation: http://majorz.github.com/flask-htmlbuilder/ >> >> >> >> >> >> I used the Flask extension generator for initial skeleton creation. >> >> >> Documentation is using flask_small theme. I tried to follow closely >> >> >> the recommendations and looked how other extensions were done. I would >> >> >> to ask for an initial review process. >> >> >> >> >> >> Thanks, >> >> >> Zahari >> >> >> >> >> > >> >> > Some quick thoughts: >> >> > >> >> > - html.doctype() could take a format, type and version and generate a >> >> > corresponding doctype, i.e. html.doctype('html', 4, 'strict'), with some >> >> > useful defaults. >> >> >> >> That sounds a nice idea. I actually left thinking about compatibility >> >> with HTML4 for a later time, since I wanted to make sure HTML5 is >> >> covered well. But I will definitely do it, unless something convinces >> >> me that HTML5 support is far from enough. Basically HTML4 support in >> >> my library is needed only if someone wants to use my extension as >> >> snippets in existing HTML4 markup. Otherwise there is no reason he >> >> should not go with HTML5, since it is backwards compatible with HTML4 >> >> and cleaner. XHTML2 is officially dead now, and people from both >> >> working groups are working on HTML5. I particularly like that comic: >> >> http://www.smashingmagazine.com/2009/07/29/misunderstanding-markup-xhtml-2-comic-strip/ >> > >> > http://www.infoworld.com/d/developer-world/w3c-hold-html5-in-websites-041 >> > >> >> That article is about the newest features in HTML5, not about the >> backwards compatibility, so I think it is misleading. Furthermore, >> taking into account that projects like Modernizr exist and prove to be >> working well across older browsers like IE6, a developer may use >> feature detection capabilities to decides on newer HTML5 features. >> BTW, the most used website in the world (google.com) is serving HTML5. > > Just a note: I'm all for HTML 5, but supporting HTML 4 is still > important today. > Well, yeah, I guess I should live with that :D >> >> > http://webkit.org/blog/68/understanding-html-xml-and-xhtml/ >> > >> > <tag /> is invalid HTML 4, and many browsers parse HTML 5 as HTML 4. No >> > major browser actually supports XHTML. <tag /> isn't even sensible XML. >> > <script src/> can screw up some engines a lot, does your implementation >> > handle that situation? Genshi does all that for you, you can output HTML >> > 4-ish, XHTML-ish or pure XML-ish, on the fly. HTML 5 is only backwards >> > compatible if used as HTML 4, and you're using it as XHTML. >> > >> >> As I said I will allow users to choose between both ways of closing >> void elements, I just need to figure out an elegant way of doing it. I >> do not intend to put validation capabilities to my extension for now. >> Let's take your script example actually: >> HTML: <script src="/js/mighty.js" /> Python: >> html.script(src='/js/mighty.js') - Bad >> HTML: <script src="/js/mighty.js"></script> Python: >> html.script(src='/js/mighty.js')() - Problem solved, yeah? >> >> Jeffrey Zeldman uses HTML5 with XHTML dialect for closing void >> elements. His website works nice in IE6. I think that clarifies pretty >> well that my approach is backwards compatible as well. >> >> >> >> >> > - Markup() from Jinja and Genshi should work as substitutes for >> >> > html.safe() if they don't already. Some Flask extensions rely on this. >> >> >> >> I will look at Markup of Jinja and Genshi, to see whether I am missing >> >> something. html.safe is quite a simple operation in my extension - >> >> just returning a string as is without escaping it. >> > >> > Then it should work, but possibly you want to escape strings passed as >> > content to a tag, unless it hasattr '__html__' and in that case use >> > that. That might be safer, and should work with Markup(). Did I mention >> > that Genshi's builder does this exactly already? :) >> >> Thanks. Armin clarified that I should work on that to get approval and >> will do it. >> >> > >> >> >> >> > - I still think you should use genshi.builder. You'd get a lot for free, >> >> > including doctypes. It's not possible to output valid HTML 4 with your >> >> > implementation. I can help you with how to use Genshi. >> >> >> >> Yes, I will add support for closing void elements with and without >> >> slashes. Since HTML5 supports them both (and IMO xhtml way is >> >> cleaner), I thought for now it will suffice just the xhtml way. It is >> >> a matter of a few additional lines in the code. >> > >> > Not that few, you'd have to keep track of which tags are content tags or >> > not in HTML. Not that big a deal of course, but, hey guess what: Genshi >> > does this exactly already. >> > >> >> Why should I do that? I prefer to leave those to the user and not >> provide validation as I talked above. > > Makes sense for an XML builder, less so for rendering output for the web > IMHO. > Ah, okay, I got it now. I will keep in mind that.. >> >> >> >> >> I am still not convinced that I should use Genshi, because I do not >> >> see why, but I guess I may miss something. Can you try to elaborate >> >> more on that, please? >> > >> > Why *not*? You seem to have a case of the NIH. You're complicating what >> > should be a simple extension (Flask extensions should usually be thin >> > wrappers around existing libraries), bloating your source, reinventing >> > the wheel and ending up with a less powerful tool. >> > >> >> My source is definitely not bloated, nor is less powerful. We may say >> that it is still work in progress though - that's why my version there >> is 0.3 (the previous two were internal non-flask related). > > Sorry, I didn't mean to say that it was - only compared to a > hypothetical source where the builder is a separate library. > Yes, it will be 1/2--2/3 shorter this way and other people from the Python community will benefit from it. >> >> While Flask extensions normally are just wrappers (I agree), that does >> not invalidate the opposite approach in any way. >> >> > Is it dependency fear, feeling Genshi does more than you need so it's a >> > heavy dependency? Have you considered that Flask depends on Werkzeug, of >> > which you don't use everything, and Jinja, which you don't use at all >> > with your extension? Don't fear dependencies. >> > >> > BTW I think the Genshi builder has the exact same API as your builder, >> > building-wise. Anything you don't like you can just hide in your >> > extension. >> >> To tell a joke, IMO, Genshi builder is quite less-powerful. I have >> concrete evidence with the standard Big Table template benchmark: >> Flask-HTMLBuilder builder 261.97 ms >> Werkzeug HTMLBuilder 196.30 ms >> Genshi tag builder 831.50 ms >> Genshi template 482.97 ms >> Genshi text template 343.76 ms >> Genshi template + tag builder 912.09 ms >> ElementTree 350.67 ms >> cElementTree 198.58 ms >> Django template 1046.46 ms > > Irrelevant for most people. Django is clearly the slowest and yet a > great lot of people use it in production systems. Templating is rarely a > culprit. > I have the gut feeling that their performance penalty comes from their escaping mechanisms, but that is unrelated anyway. Talking about performance I am planning to do a Cython version of my extension when I have more time to play with that (at least the part that should be moved in a standalone package). It will be interesting to see the results. >> >> As we can see it is 3-4 times slower, what so powerful about it... >> Okay, more seriously now. My API is different actually though there >> are a lot of similarities. >> >> One quick example with what you talked about: >> Me: >> >>> str(html.script(src='/js/mighty.js')()) >> '<script src="/js/mighty.js"></script>' >> Genshi: >> >>> str(tag.script(src='/js/mighty.js')()) >> '<script src="/js/mighty.js"/>' >> >>> str(tag.script(src='/js/mighty.js')('')) >> '<script src="/js/mighty.js"></script>' >> >> I do not like how Genshi does not put a space before the closing slash >> as well. And there is more to that, but it is useless to continue. > >>>> tag.hr().generate().render('html') > '<hr>' >>>> tag.hr().generate().render('xhtml') > '<hr />' > Well, that is confusing -- whatever :) >>> str(tag.hr()) '<hr/>' >>> tag.hr().generate().render('xhtml') '<hr />' > >> >> Anyway, my idea is to have a Python-only solution. Genshi's main >> purpose is different, though it provides the builder module. I do not >> like mixing those concepts by introducing such dependency. > > I at least think you should separate the Flask extension and your > builder and make the latter a library in its own right. > > (Just wanted to provide a friendly advice with genshi.builder, I hope > I'm not coming off too strong about it. +1 for adding to the set of > Flask extensions.) > I understand you, no problem :) Thanks for the ideas and the response, it's always very appreciated. Zahari
> While Flask extensions normally are just wrappers (I agree), that does > not invalidate the opposite approach in any way. Why not have the HTMLBuilder as a separate package (and therefore useful to the greatest number of Python developers) and write a Flask-HTMLBuilder extension that can use it ?
On Mon, Nov 8, 2010 at 6:08 PM, danjac354@gmail.com <danjac354@gmail.com> wrote: >> While Flask extensions normally are just wrappers (I agree), that does >> not invalidate the opposite approach in any way. > > Why not have the HTMLBuilder as a separate package (and therefore > useful to the greatest number of Python developers) and write a > Flask-HTMLBuilder extension that can use it ? > I initially decided to get in this direction, but then decided to stay with Flask-only implementation. My code is half-dependent on Flask/Werkzeug, half-independent on them. But the basic HTML builder part can be isolated in a package of it's own, so I appreciate your suggestion very much. I may split the project soon so that more people can benefit from it. Thanks, Zahari
Hi, On 2010-11-08 1:17 PM, Zahari Petkov wrote: > I will look at Markup of Jinja and Genshi, to see whether I am missing > something. html.safe is quite a simple operation in my extension - > just returning a string as is without escaping it. Make sure to support Markup or its impossible for this extension to ever get a seal of approval :) Regards, Armin
On Mon, Nov 8, 2010 at 3:02 PM, Armin Ronacher <armin.ronacher@active-4.com> wrote: > Hi, > > On 2010-11-08 1:17 PM, Zahari Petkov wrote: >> I will look at Markup of Jinja and Genshi, to see whether I am missing >> something. html.safe is quite a simple operation in my extension - >> just returning a string as is without escaping it. > Make sure to support Markup or its impossible for this extension to ever > get a seal of approval :) > I committed Markup support but I am a bit confused about whether my __html__ method should return just a unicode string or a jinja2 Markup object? I made it returning a unicode for now. I added some tests as well. Thanks, Zahari
On Tue, 2010-11-09 at 03:02 +0200, Zahari Petkov wrote: > On Mon, Nov 8, 2010 at 3:02 PM, Armin Ronacher > <armin.ronacher@active-4.com> wrote: > > Hi, > > > > On 2010-11-08 1:17 PM, Zahari Petkov wrote: > >> I will look at Markup of Jinja and Genshi, to see whether I am missing > >> something. html.safe is quite a simple operation in my extension - > >> just returning a string as is without escaping it. > > Make sure to support Markup or its impossible for this extension to ever > > get a seal of approval :) > > > > I committed Markup support but I am a bit confused about whether my > __html__ method should return just a unicode string or a jinja2 Markup > object? I made it returning a unicode for now. I added some tests as > well. > > Thanks, > Zahari Markup() is pointless unless combined with escaping of markup, automatic or not. If you have a function for escaping markup, given an object that implements __html__, that method should be used unescaped. If you have automatic escaping (and you should) of strings used as content in a tag, the same logic applies. You don't need to reimplement Markup(), you can just from flask import Markup. >>> html.p('<em>Example</em>') '<p><em>Example</em></p>' >>> html.p(Markup('<em>Example</em>')) '<p><em>Example</em></p>' Flask's Markup() is just a subclass of unicode, adding __html__. If for some reason you want a html.safe() even though that's just a longer version of Markup() :) you just make it return Markup().
On Tue, Nov 9, 2010 at 9:33 AM, Dag Odenhall <dag.odenhall@gmail.com> wrote: > On Tue, 2010-11-09 at 03:02 +0200, Zahari Petkov wrote: >> On Mon, Nov 8, 2010 at 3:02 PM, Armin Ronacher >> <armin.ronacher@active-4.com> wrote: >> > Hi, >> > >> > On 2010-11-08 1:17 PM, Zahari Petkov wrote: >> >> I will look at Markup of Jinja and Genshi, to see whether I am missing >> >> something. html.safe is quite a simple operation in my extension - >> >> just returning a string as is without escaping it. >> > Make sure to support Markup or its impossible for this extension to ever >> > get a seal of approval :) >> > >> >> I committed Markup support but I am a bit confused about whether my >> __html__ method should return just a unicode string or a jinja2 Markup >> object? I made it returning a unicode for now. I added some tests as >> well. >> >> Thanks, >> Zahari > > Markup() is pointless unless combined with escaping of markup, automatic > or not. If you have a function for escaping markup, given an object that > implements __html__, that method should be used unescaped. If you have > automatic escaping (and you should) of strings used as content in a tag, > the same logic applies. You don't need to reimplement Markup(), you can > just from flask import Markup. > >>>> html.p('<em>Example</em>') > '<p><em>Example</em></p>' >>>> html.p(Markup('<em>Example</em>')) > '<p><em>Example</em></p>' > > Flask's Markup() is just a subclass of unicode, adding __html__. > > If for some reason you want a html.safe() even though that's just a > longer version of Markup() :) you just make it return Markup(). > > Thanks for pointing those out -- more things to be considered then. BTW, Markup is painfully slow, and that is a concern to me, but anyway, let see... Thanks, Zahari
On Tue, Nov 9, 2010 at 9:54 AM, Zahari Petkov <zarchaoz@gmail.com> wrote: > On Tue, Nov 9, 2010 at 9:33 AM, Dag Odenhall <dag.odenhall@gmail.com> wrote: >> On Tue, 2010-11-09 at 03:02 +0200, Zahari Petkov wrote: >>> On Mon, Nov 8, 2010 at 3:02 PM, Armin Ronacher >>> <armin.ronacher@active-4.com> wrote: >>> > Hi, >>> > >>> > On 2010-11-08 1:17 PM, Zahari Petkov wrote: >>> >> I will look at Markup of Jinja and Genshi, to see whether I am missing >>> >> something. html.safe is quite a simple operation in my extension - >>> >> just returning a string as is without escaping it. >>> > Make sure to support Markup or its impossible for this extension to ever >>> > get a seal of approval :) >>> > >>> >>> I committed Markup support but I am a bit confused about whether my >>> __html__ method should return just a unicode string or a jinja2 Markup >>> object? I made it returning a unicode for now. I added some tests as >>> well. >>> >>> Thanks, >>> Zahari >> >> Markup() is pointless unless combined with escaping of markup, automatic >> or not. If you have a function for escaping markup, given an object that >> implements __html__, that method should be used unescaped. If you have >> automatic escaping (and you should) of strings used as content in a tag, >> the same logic applies. You don't need to reimplement Markup(), you can >> just from flask import Markup. >> >>>>> html.p('<em>Example</em>') >> '<p><em>Example</em></p>' >>>>> html.p(Markup('<em>Example</em>')) >> '<p><em>Example</em></p>' >> >> Flask's Markup() is just a subclass of unicode, adding __html__. >> >> If for some reason you want a html.safe() even though that's just a >> longer version of Markup() :) you just make it return Markup(). >> > > Thanks for pointing those out -- more things to be considered then. > BTW, Markup is painfully slow, and that is a concern to me, but > anyway, let see... > I was not aware till that moment, that besides side-effect, there are a few specialized versions - left side-effect, right side-effect, and, yes, the one that comes from left and from right simultaneously. Well, I am a bit troubled here :) >>> from jinja2 import Markup >>> Markup(' ') Markup(u' ') Okay... >>> ' ' + Markup(' ') Markup(u' ') Meh!? >>> ' ' + Markup(' ') + ' ' Markup(u' ') Wow, it is spreading like a decease :-D Okay, that was funny (for me at least) but I think this is a serous design flaw.. Since Markup is overloading `unicode`, it should not change so drastically it's protocol behavior, and now it is definitely not a `unicode` instance which should be by definition of class overloading. It is a monster eating strings and escaping them in it's belly :-D Why? Thanks, Zahari
Hi, On 2010-11-09 9:48 AM, Zahari Petkov wrote: >>>> ' ' + Markup(' ') > Markup(u' ') > > Meh!? > >>>> ' ' + Markup(' ') + ' ' > Markup(u' ') > > Wow, it is spreading like a decease :-D Okay, that was funny (for me > at least) but I think this is a serous design flaw.. That's not a design flaw, that's the whole point. >>> Markup(u'<strong>%s</strong>') % '<foo>' Markup(u'<strong><foo></strong>') Regards, Armin
> That's not a design flaw, that's the whole point. > > >>> Markup(u'<strong>%s</strong>') % '<foo>' > Markup(u'<strong><foo></strong>') > > > Regards, > Armin > Yes, I was wrong. I was thinking in a too dogmatic way with some OOP concepts in my mind. Looking at the bigger picture, I think the Markup class as a whole is quite innovative and doing the job well. Sorry about stirring the discussion in the wrong direction, I will be more careful next time. Anyway, I will look further what my implementation is still missing and set those right. I am working on some cool things with it now and I think the outcome will be quite good. I appreciate the help extended from various members of the community a lot and thanks for that guys. Zahari
On Tue, 2010-11-09 at 10:48 +0200, Zahari Petkov wrote: > On Tue, Nov 9, 2010 at 9:54 AM, Zahari Petkov <zarchaoz@gmail.com> wrote: > > On Tue, Nov 9, 2010 at 9:33 AM, Dag Odenhall <dag.odenhall@gmail.com> wrote: > >> On Tue, 2010-11-09 at 03:02 +0200, Zahari Petkov wrote: > >>> On Mon, Nov 8, 2010 at 3:02 PM, Armin Ronacher > >>> <armin.ronacher@active-4.com> wrote: > >>> > Hi, > >>> > > >>> > On 2010-11-08 1:17 PM, Zahari Petkov wrote: > >>> >> I will look at Markup of Jinja and Genshi, to see whether I am missing > >>> >> something. html.safe is quite a simple operation in my extension - > >>> >> just returning a string as is without escaping it. > >>> > Make sure to support Markup or its impossible for this extension to ever > >>> > get a seal of approval :) > >>> > > >>> > >>> I committed Markup support but I am a bit confused about whether my > >>> __html__ method should return just a unicode string or a jinja2 Markup > >>> object? I made it returning a unicode for now. I added some tests as > >>> well. > >>> > >>> Thanks, > >>> Zahari > >> > >> Markup() is pointless unless combined with escaping of markup, automatic > >> or not. If you have a function for escaping markup, given an object that > >> implements __html__, that method should be used unescaped. If you have > >> automatic escaping (and you should) of strings used as content in a tag, > >> the same logic applies. You don't need to reimplement Markup(), you can > >> just from flask import Markup. > >> > >>>>> html.p('<em>Example</em>') > >> '<p><em>Example</em></p>' > >>>>> html.p(Markup('<em>Example</em>')) > >> '<p><em>Example</em></p>' > >> > >> Flask's Markup() is just a subclass of unicode, adding __html__. > >> > >> If for some reason you want a html.safe() even though that's just a > >> longer version of Markup() :) you just make it return Markup(). > >> > > > > Thanks for pointing those out -- more things to be considered then. > > BTW, Markup is painfully slow, and that is a concern to me, but > > anyway, let see... > > > > I was not aware till that moment, that besides side-effect, there are > a few specialized versions - left side-effect, right side-effect, and, > yes, the one that comes from left and from right simultaneously. > > Well, I am a bit troubled here :) > > >>> from jinja2 import Markup > >>> Markup(' ') > Markup(u' ') > > Okay... > > >>> ' ' + Markup(' ') > Markup(u' ') > > Meh!? > > >>> ' ' + Markup(' ') + ' ' > Markup(u' ') > > Wow, it is spreading like a decease :-D Okay, that was funny (for me > at least) but I think this is a serous design flaw.. > > Since Markup is overloading `unicode`, it should not change so > drastically it's protocol behavior, and now it is definitely not a > `unicode` instance which should be by definition of class overloading. > It is a monster eating strings and escaping them in it's belly :-D > Why? > > Thanks, > Zahari It's intentional, only what is explicitly Markup() is "safe" and left unescaped. >>> Markup(' ') + Markup(' ') Markup(u' ')
On Tue, Nov 9, 2010 at 11:31 AM, Dag Odenhall <dag.odenhall@gmail.com> wrote: > On Tue, 2010-11-09 at 10:48 +0200, Zahari Petkov wrote: >> On Tue, Nov 9, 2010 at 9:54 AM, Zahari Petkov <zarchaoz@gmail.com> wrote: >> > On Tue, Nov 9, 2010 at 9:33 AM, Dag Odenhall <dag.odenhall@gmail.com> wrote: >> >> On Tue, 2010-11-09 at 03:02 +0200, Zahari Petkov wrote: >> >>> On Mon, Nov 8, 2010 at 3:02 PM, Armin Ronacher >> >>> <armin.ronacher@active-4.com> wrote: >> >>> > Hi, >> >>> > >> >>> > On 2010-11-08 1:17 PM, Zahari Petkov wrote: >> >>> >> I will look at Markup of Jinja and Genshi, to see whether I am missing >> >>> >> something. html.safe is quite a simple operation in my extension - >> >>> >> just returning a string as is without escaping it. >> >>> > Make sure to support Markup or its impossible for this extension to ever >> >>> > get a seal of approval :) >> >>> > >> >>> >> >>> I committed Markup support but I am a bit confused about whether my >> >>> __html__ method should return just a unicode string or a jinja2 Markup >> >>> object? I made it returning a unicode for now. I added some tests as >> >>> well. >> >>> >> >>> Thanks, >> >>> Zahari >> >> >> >> Markup() is pointless unless combined with escaping of markup, automatic >> >> or not. If you have a function for escaping markup, given an object that >> >> implements __html__, that method should be used unescaped. If you have >> >> automatic escaping (and you should) of strings used as content in a tag, >> >> the same logic applies. You don't need to reimplement Markup(), you can >> >> just from flask import Markup. >> >> >> >>>>> html.p('<em>Example</em>') >> >> '<p><em>Example</em></p>' >> >>>>> html.p(Markup('<em>Example</em>')) >> >> '<p><em>Example</em></p>' >> >> >> >> Flask's Markup() is just a subclass of unicode, adding __html__. >> >> >> >> If for some reason you want a html.safe() even though that's just a >> >> longer version of Markup() :) you just make it return Markup(). >> >> >> > >> > Thanks for pointing those out -- more things to be considered then. >> > BTW, Markup is painfully slow, and that is a concern to me, but >> > anyway, let see... >> > >> >> I was not aware till that moment, that besides side-effect, there are >> a few specialized versions - left side-effect, right side-effect, and, >> yes, the one that comes from left and from right simultaneously. >> >> Well, I am a bit troubled here :) >> >> >>> from jinja2 import Markup >> >>> Markup(' ') >> Markup(u' ') >> >> Okay... >> >> >>> ' ' + Markup(' ') >> Markup(u' ') >> >> Meh!? >> >> >>> ' ' + Markup(' ') + ' ' >> Markup(u' ') >> >> Wow, it is spreading like a decease :-D Okay, that was funny (for me >> at least) but I think this is a serous design flaw.. >> >> Since Markup is overloading `unicode`, it should not change so >> drastically it's protocol behavior, and now it is definitely not a >> `unicode` instance which should be by definition of class overloading. >> It is a monster eating strings and escaping them in it's belly :-D >> Why? >> >> Thanks, >> Zahari > > It's intentional, only what is explicitly Markup() is "safe" and left > unescaped. > I see it is intentional and the purpose is obvious. I am questioning the design decisions made, and more specifically I am asking whether I should protect myself from them or not :) Even if `Markup` was not a sub-class of `unicode`, which is definitely a hack disregarding basic principles of OOP (that's fine, everyone is free to break a couple of rules). that is still pretty aggressive behavior, which forces me into two possible directions: 1. protecting my extension against such aggressiveness. If that is okay, I am okay as well. 2. adopting it, which will lead to a significant performance penalty, which I am not eager to sacrifice. Basically, when someone is telling me that everything is internally converted to `unicode`, so that I do not worry about encoding exceptions, and my text that should not be escaped should stay un-escaped whatever we try to do to it, it reads to me the following: you will get a significant penalty by multiple `unicode` instantiations, because we are taking care of you not to do stupid things. And sometimes it reads that we are not 100% sure what's going on inside our code, or we just think this is the only way to go, and we will trade speed for stability. But when I use Jinja 2 `escape` which uses `Markup`, and when I run the Big Table performance test, my extension is 4x slower. This is a huge trade-off for me, and I am not eager to sacrifice it. I am not criticizing the design decisions made, actually, they are just not suitable for me to adopt them. Thanks, Zahari
On Tue, 2010-11-09 at 12:13 +0200, Zahari Petkov wrote: > On Tue, Nov 9, 2010 at 11:31 AM, Dag Odenhall <dag.odenhall@gmail.com> wrote: > > On Tue, 2010-11-09 at 10:48 +0200, Zahari Petkov wrote: > >> On Tue, Nov 9, 2010 at 9:54 AM, Zahari Petkov <zarchaoz@gmail.com> wrote: > >> > On Tue, Nov 9, 2010 at 9:33 AM, Dag Odenhall <dag.odenhall@gmail.com> wrote: > >> >> On Tue, 2010-11-09 at 03:02 +0200, Zahari Petkov wrote: > >> >>> On Mon, Nov 8, 2010 at 3:02 PM, Armin Ronacher > >> >>> <armin.ronacher@active-4.com> wrote: > >> >>> > Hi, > >> >>> > > >> >>> > On 2010-11-08 1:17 PM, Zahari Petkov wrote: > >> >>> >> I will look at Markup of Jinja and Genshi, to see whether I am missing > >> >>> >> something. html.safe is quite a simple operation in my extension - > >> >>> >> just returning a string as is without escaping it. > >> >>> > Make sure to support Markup or its impossible for this extension to ever > >> >>> > get a seal of approval :) > >> >>> > > >> >>> > >> >>> I committed Markup support but I am a bit confused about whether my > >> >>> __html__ method should return just a unicode string or a jinja2 Markup > >> >>> object? I made it returning a unicode for now. I added some tests as > >> >>> well. > >> >>> > >> >>> Thanks, > >> >>> Zahari > >> >> > >> >> Markup() is pointless unless combined with escaping of markup, automatic > >> >> or not. If you have a function for escaping markup, given an object that > >> >> implements __html__, that method should be used unescaped. If you have > >> >> automatic escaping (and you should) of strings used as content in a tag, > >> >> the same logic applies. You don't need to reimplement Markup(), you can > >> >> just from flask import Markup. > >> >> > >> >>>>> html.p('<em>Example</em>') > >> >> '<p><em>Example</em></p>' > >> >>>>> html.p(Markup('<em>Example</em>')) > >> >> '<p><em>Example</em></p>' > >> >> > >> >> Flask's Markup() is just a subclass of unicode, adding __html__. > >> >> > >> >> If for some reason you want a html.safe() even though that's just a > >> >> longer version of Markup() :) you just make it return Markup(). > >> >> > >> > > >> > Thanks for pointing those out -- more things to be considered then. > >> > BTW, Markup is painfully slow, and that is a concern to me, but > >> > anyway, let see... > >> > > >> > >> I was not aware till that moment, that besides side-effect, there are > >> a few specialized versions - left side-effect, right side-effect, and, > >> yes, the one that comes from left and from right simultaneously. > >> > >> Well, I am a bit troubled here :) > >> > >> >>> from jinja2 import Markup > >> >>> Markup(' ') > >> Markup(u' ') > >> > >> Okay... > >> > >> >>> ' ' + Markup(' ') > >> Markup(u' ') > >> > >> Meh!? > >> > >> >>> ' ' + Markup(' ') + ' ' > >> Markup(u' ') > >> > >> Wow, it is spreading like a decease :-D Okay, that was funny (for me > >> at least) but I think this is a serous design flaw.. > >> > >> Since Markup is overloading `unicode`, it should not change so > >> drastically it's protocol behavior, and now it is definitely not a > >> `unicode` instance which should be by definition of class overloading. > >> It is a monster eating strings and escaping them in it's belly :-D > >> Why? > >> > >> Thanks, > >> Zahari > > > > It's intentional, only what is explicitly Markup() is "safe" and left > > unescaped. > > > > I see it is intentional and the purpose is obvious. I am questioning > the design decisions made, and more specifically I am asking whether I > should protect myself from them or not :) > > Even if `Markup` was not a sub-class of `unicode`, which is > definitely a hack disregarding basic principles of OOP (that's fine, > everyone is free to break a couple of rules). that is still pretty > aggressive behavior, which forces me into two possible directions: > > 1. protecting my extension against such aggressiveness. If that is > okay, I am okay as well. > 2. adopting it, which will lead to a significant performance penalty, > which I am not eager to sacrifice. > > Basically, when someone is telling me that everything is internally > converted to `unicode`, so that I do not worry about encoding > exceptions, and my text that should not be escaped should stay > un-escaped whatever we try to do to it, it reads to me the following: > you will get a significant penalty by multiple `unicode` > instantiations, because we are taking care of you not to do stupid > things. And sometimes it reads that we are not 100% sure what's going > on inside our code, or we just think this is the only way to go, and > we will trade speed for stability. But when I use Jinja 2 `escape` > which uses `Markup`, and when I run the Big Table performance test, my > extension is 4x slower. This is a huge trade-off for me, and I am not > eager to sacrifice it. I am not criticizing the design decisions made, > actually, they are just not suitable for me to adopt them. > > Thanks, > Zahari Have you tried benchmarking after installing the MarkupSafe package? It has a C extension for speedups and Jinja bundles it without the speedups, but it will use the package if it is installed.
On Tue, Nov 9, 2010 at 1:18 PM, Dag Odenhall <dag.odenhall@gmail.com> wrote: > On Tue, 2010-11-09 at 12:13 +0200, Zahari Petkov wrote: >> On Tue, Nov 9, 2010 at 11:31 AM, Dag Odenhall <dag.odenhall@gmail.com> wrote: >> > On Tue, 2010-11-09 at 10:48 +0200, Zahari Petkov wrote: >> >> On Tue, Nov 9, 2010 at 9:54 AM, Zahari Petkov <zarchaoz@gmail.com> wrote: >> >> > On Tue, Nov 9, 2010 at 9:33 AM, Dag Odenhall <dag.odenhall@gmail.com> wrote: >> >> >> On Tue, 2010-11-09 at 03:02 +0200, Zahari Petkov wrote: >> >> >>> On Mon, Nov 8, 2010 at 3:02 PM, Armin Ronacher >> >> >>> <armin.ronacher@active-4.com> wrote: >> >> >>> > Hi, >> >> >>> > >> >> >>> > On 2010-11-08 1:17 PM, Zahari Petkov wrote: >> >> >>> >> I will look at Markup of Jinja and Genshi, to see whether I am missing >> >> >>> >> something. html.safe is quite a simple operation in my extension - >> >> >>> >> just returning a string as is without escaping it. >> >> >>> > Make sure to support Markup or its impossible for this extension to ever >> >> >>> > get a seal of approval :) >> >> >>> > >> >> >>> >> >> >>> I committed Markup support but I am a bit confused about whether my >> >> >>> __html__ method should return just a unicode string or a jinja2 Markup >> >> >>> object? I made it returning a unicode for now. I added some tests as >> >> >>> well. >> >> >>> >> >> >>> Thanks, >> >> >>> Zahari >> >> >> >> >> >> Markup() is pointless unless combined with escaping of markup, automatic >> >> >> or not. If you have a function for escaping markup, given an object that >> >> >> implements __html__, that method should be used unescaped. If you have >> >> >> automatic escaping (and you should) of strings used as content in a tag, >> >> >> the same logic applies. You don't need to reimplement Markup(), you can >> >> >> just from flask import Markup. >> >> >> >> >> >>>>> html.p('<em>Example</em>') >> >> >> '<p><em>Example</em></p>' >> >> >>>>> html.p(Markup('<em>Example</em>')) >> >> >> '<p><em>Example</em></p>' >> >> >> >> >> >> Flask's Markup() is just a subclass of unicode, adding __html__. >> >> >> >> >> >> If for some reason you want a html.safe() even though that's just a >> >> >> longer version of Markup() :) you just make it return Markup(). >> >> >> >> >> > >> >> > Thanks for pointing those out -- more things to be considered then. >> >> > BTW, Markup is painfully slow, and that is a concern to me, but >> >> > anyway, let see... >> >> > >> >> >> >> I was not aware till that moment, that besides side-effect, there are >> >> a few specialized versions - left side-effect, right side-effect, and, >> >> yes, the one that comes from left and from right simultaneously. >> >> >> >> Well, I am a bit troubled here :) >> >> >> >> >>> from jinja2 import Markup >> >> >>> Markup(' ') >> >> Markup(u' ') >> >> >> >> Okay... >> >> >> >> >>> ' ' + Markup(' ') >> >> Markup(u' ') >> >> >> >> Meh!? >> >> >> >> >>> ' ' + Markup(' ') + ' ' >> >> Markup(u' ') >> >> >> >> Wow, it is spreading like a decease :-D Okay, that was funny (for me >> >> at least) but I think this is a serous design flaw.. >> >> >> >> Since Markup is overloading `unicode`, it should not change so >> >> drastically it's protocol behavior, and now it is definitely not a >> >> `unicode` instance which should be by definition of class overloading. >> >> It is a monster eating strings and escaping them in it's belly :-D >> >> Why? >> >> >> >> Thanks, >> >> Zahari >> > >> > It's intentional, only what is explicitly Markup() is "safe" and left >> > unescaped. >> > >> >> I see it is intentional and the purpose is obvious. I am questioning >> the design decisions made, and more specifically I am asking whether I >> should protect myself from them or not :) >> >> Even if `Markup` was not a sub-class of `unicode`, which is >> definitely a hack disregarding basic principles of OOP (that's fine, >> everyone is free to break a couple of rules). that is still pretty >> aggressive behavior, which forces me into two possible directions: >> >> 1. protecting my extension against such aggressiveness. If that is >> okay, I am okay as well. >> 2. adopting it, which will lead to a significant performance penalty, >> which I am not eager to sacrifice. >> >> Basically, when someone is telling me that everything is internally >> converted to `unicode`, so that I do not worry about encoding >> exceptions, and my text that should not be escaped should stay >> un-escaped whatever we try to do to it, it reads to me the following: >> you will get a significant penalty by multiple `unicode` >> instantiations, because we are taking care of you not to do stupid >> things. And sometimes it reads that we are not 100% sure what's going >> on inside our code, or we just think this is the only way to go, and >> we will trade speed for stability. But when I use Jinja 2 `escape` >> which uses `Markup`, and when I run the Big Table performance test, my >> extension is 4x slower. This is a huge trade-off for me, and I am not >> eager to sacrifice it. I am not criticizing the design decisions made, >> actually, they are just not suitable for me to adopt them. >> >> Thanks, >> Zahari > > Have you tried benchmarking after installing the MarkupSafe package? It > has a C extension for speedups and Jinja bundles it without the > speedups, but it will use the package if it is installed. > > Nope, actually, my laptop motherboard died a couple of weeks ago and I am now using an old XP machine. I did not found the Jinja 2 speedups for win32 in a pre-compiled package, and VMs are quite a pain with so less RAM to run Ubuntu now. Additionally there is no C stuff allowed on GAE, and there is where you pay for CPU, which alone is enough for me to disregard that as an option.
On Tue, Nov 9, 2010 at 1:26 PM, Zahari Petkov <zarchaoz@gmail.com> wrote: > On Tue, Nov 9, 2010 at 1:18 PM, Dag Odenhall <dag.odenhall@gmail.com> wrote: >> On Tue, 2010-11-09 at 12:13 +0200, Zahari Petkov wrote: >>> On Tue, Nov 9, 2010 at 11:31 AM, Dag Odenhall <dag.odenhall@gmail.com> wrote: >>> > On Tue, 2010-11-09 at 10:48 +0200, Zahari Petkov wrote: >>> >> On Tue, Nov 9, 2010 at 9:54 AM, Zahari Petkov <zarchaoz@gmail.com> wrote: >>> >> > On Tue, Nov 9, 2010 at 9:33 AM, Dag Odenhall <dag.odenhall@gmail.com> wrote: >>> >> >> On Tue, 2010-11-09 at 03:02 +0200, Zahari Petkov wrote: >>> >> >>> On Mon, Nov 8, 2010 at 3:02 PM, Armin Ronacher >>> >> >>> <armin.ronacher@active-4.com> wrote: >>> >> >>> > Hi, >>> >> >>> > >>> >> >>> > On 2010-11-08 1:17 PM, Zahari Petkov wrote: >>> >> >>> >> I will look at Markup of Jinja and Genshi, to see whether I am missing >>> >> >>> >> something. html.safe is quite a simple operation in my extension - >>> >> >>> >> just returning a string as is without escaping it. >>> >> >>> > Make sure to support Markup or its impossible for this extension to ever >>> >> >>> > get a seal of approval :) >>> >> >>> > >>> >> >>> >>> >> >>> I committed Markup support but I am a bit confused about whether my >>> >> >>> __html__ method should return just a unicode string or a jinja2 Markup >>> >> >>> object? I made it returning a unicode for now. I added some tests as >>> >> >>> well. >>> >> >>> >>> >> >>> Thanks, >>> >> >>> Zahari >>> >> >> >>> >> >> Markup() is pointless unless combined with escaping of markup, automatic >>> >> >> or not. If you have a function for escaping markup, given an object that >>> >> >> implements __html__, that method should be used unescaped. If you have >>> >> >> automatic escaping (and you should) of strings used as content in a tag, >>> >> >> the same logic applies. You don't need to reimplement Markup(), you can >>> >> >> just from flask import Markup. >>> >> >> >>> >> >>>>> html.p('<em>Example</em>') >>> >> >> '<p><em>Example</em></p>' >>> >> >>>>> html.p(Markup('<em>Example</em>')) >>> >> >> '<p><em>Example</em></p>' >>> >> >> >>> >> >> Flask's Markup() is just a subclass of unicode, adding __html__. >>> >> >> >>> >> >> If for some reason you want a html.safe() even though that's just a >>> >> >> longer version of Markup() :) you just make it return Markup(). >>> >> >> >>> >> > >>> >> > Thanks for pointing those out -- more things to be considered then. >>> >> > BTW, Markup is painfully slow, and that is a concern to me, but >>> >> > anyway, let see... >>> >> > >>> >> >>> >> I was not aware till that moment, that besides side-effect, there are >>> >> a few specialized versions - left side-effect, right side-effect, and, >>> >> yes, the one that comes from left and from right simultaneously. >>> >> >>> >> Well, I am a bit troubled here :) >>> >> >>> >> >>> from jinja2 import Markup >>> >> >>> Markup(' ') >>> >> Markup(u' ') >>> >> >>> >> Okay... >>> >> >>> >> >>> ' ' + Markup(' ') >>> >> Markup(u' ') >>> >> >>> >> Meh!? >>> >> >>> >> >>> ' ' + Markup(' ') + ' ' >>> >> Markup(u' ') >>> >> >>> >> Wow, it is spreading like a decease :-D Okay, that was funny (for me >>> >> at least) but I think this is a serous design flaw.. >>> >> >>> >> Since Markup is overloading `unicode`, it should not change so >>> >> drastically it's protocol behavior, and now it is definitely not a >>> >> `unicode` instance which should be by definition of class overloading. >>> >> It is a monster eating strings and escaping them in it's belly :-D >>> >> Why? >>> >> >>> >> Thanks, >>> >> Zahari >>> > >>> > It's intentional, only what is explicitly Markup() is "safe" and left >>> > unescaped. >>> > >>> >>> I see it is intentional and the purpose is obvious. I am questioning >>> the design decisions made, and more specifically I am asking whether I >>> should protect myself from them or not :) >>> >>> Even if `Markup` was not a sub-class of `unicode`, which is >>> definitely a hack disregarding basic principles of OOP (that's fine, >>> everyone is free to break a couple of rules). that is still pretty >>> aggressive behavior, which forces me into two possible directions: >>> >>> 1. protecting my extension against such aggressiveness. If that is >>> okay, I am okay as well. >>> 2. adopting it, which will lead to a significant performance penalty, >>> which I am not eager to sacrifice. >>> >>> Basically, when someone is telling me that everything is internally >>> converted to `unicode`, so that I do not worry about encoding >>> exceptions, and my text that should not be escaped should stay >>> un-escaped whatever we try to do to it, it reads to me the following: >>> you will get a significant penalty by multiple `unicode` >>> instantiations, because we are taking care of you not to do stupid >>> things. And sometimes it reads that we are not 100% sure what's going >>> on inside our code, or we just think this is the only way to go, and >>> we will trade speed for stability. But when I use Jinja 2 `escape` >>> which uses `Markup`, and when I run the Big Table performance test, my >>> extension is 4x slower. This is a huge trade-off for me, and I am not >>> eager to sacrifice it. I am not criticizing the design decisions made, >>> actually, they are just not suitable for me to adopt them. >>> >>> Thanks, >>> Zahari >> >> Have you tried benchmarking after installing the MarkupSafe package? It >> has a C extension for speedups and Jinja bundles it without the >> speedups, but it will use the package if it is installed. >> >> > > Nope, actually, my laptop motherboard died a couple of weeks ago and I > am now using an old XP machine. I did not found the Jinja 2 speedups > for win32 in a pre-compiled package, and VMs are quite a pain with so > less RAM to run Ubuntu now. Additionally there is no C stuff allowed > on GAE, and there is where you pay for CPU, which alone is enough for > me to disregard that as an option. > All that said, I do not see any contradiction anyway in the approach I took. Werkzeug HTMLBuilder is doing the same. They just are friendly to Markup, without adopting it fully.
On Tue, Nov 9, 2010 at 12:13 PM, Zahari Petkov <zarchaoz@gmail.com> wrote: > On Tue, Nov 9, 2010 at 11:31 AM, Dag Odenhall <dag.odenhall@gmail.com> wrote: >> On Tue, 2010-11-09 at 10:48 +0200, Zahari Petkov wrote: >>> On Tue, Nov 9, 2010 at 9:54 AM, Zahari Petkov <zarchaoz@gmail.com> wrote: >>> > On Tue, Nov 9, 2010 at 9:33 AM, Dag Odenhall <dag.odenhall@gmail.com> wrote: >>> >> On Tue, 2010-11-09 at 03:02 +0200, Zahari Petkov wrote: >>> >>> On Mon, Nov 8, 2010 at 3:02 PM, Armin Ronacher >>> >>> <armin.ronacher@active-4.com> wrote: >>> >>> > Hi, >>> >>> > >>> >>> > On 2010-11-08 1:17 PM, Zahari Petkov wrote: >>> >>> >> I will look at Markup of Jinja and Genshi, to see whether I am missing >>> >>> >> something. html.safe is quite a simple operation in my extension - >>> >>> >> just returning a string as is without escaping it. >>> >>> > Make sure to support Markup or its impossible for this extension to ever >>> >>> > get a seal of approval :) >>> >>> > >>> >>> >>> >>> I committed Markup support but I am a bit confused about whether my >>> >>> __html__ method should return just a unicode string or a jinja2 Markup >>> >>> object? I made it returning a unicode for now. I added some tests as >>> >>> well. >>> >>> >>> >>> Thanks, >>> >>> Zahari >>> >> >>> >> Markup() is pointless unless combined with escaping of markup, automatic >>> >> or not. If you have a function for escaping markup, given an object that >>> >> implements __html__, that method should be used unescaped. If you have >>> >> automatic escaping (and you should) of strings used as content in a tag, >>> >> the same logic applies. You don't need to reimplement Markup(), you can >>> >> just from flask import Markup. >>> >> >>> >>>>> html.p('<em>Example</em>') >>> >> '<p><em>Example</em></p>' >>> >>>>> html.p(Markup('<em>Example</em>')) >>> >> '<p><em>Example</em></p>' >>> >> >>> >> Flask's Markup() is just a subclass of unicode, adding __html__. >>> >> >>> >> If for some reason you want a html.safe() even though that's just a >>> >> longer version of Markup() :) you just make it return Markup(). >>> >> >>> > >>> > Thanks for pointing those out -- more things to be considered then. >>> > BTW, Markup is painfully slow, and that is a concern to me, but >>> > anyway, let see... >>> > >>> >>> I was not aware till that moment, that besides side-effect, there are >>> a few specialized versions - left side-effect, right side-effect, and, >>> yes, the one that comes from left and from right simultaneously. >>> >>> Well, I am a bit troubled here :) >>> >>> >>> from jinja2 import Markup >>> >>> Markup(' ') >>> Markup(u' ') >>> >>> Okay... >>> >>> >>> ' ' + Markup(' ') >>> Markup(u' ') >>> >>> Meh!? >>> >>> >>> ' ' + Markup(' ') + ' ' >>> Markup(u' ') >>> >>> Wow, it is spreading like a decease :-D Okay, that was funny (for me >>> at least) but I think this is a serous design flaw.. >>> >>> Since Markup is overloading `unicode`, it should not change so >>> drastically it's protocol behavior, and now it is definitely not a >>> `unicode` instance which should be by definition of class overloading. >>> It is a monster eating strings and escaping them in it's belly :-D >>> Why? >>> >>> Thanks, >>> Zahari >> >> It's intentional, only what is explicitly Markup() is "safe" and left >> unescaped. >> > > I see it is intentional and the purpose is obvious. I am questioning > the design decisions made, and more specifically I am asking whether I > should protect myself from them or not :) > > Even if `Markup` was not a sub-class of `unicode`, which is > definitely a hack disregarding basic principles of OOP (that's fine, > everyone is free to break a couple of rules). that is still pretty > aggressive behavior, which forces me into two possible directions: > > 1. protecting my extension against such aggressiveness. If that is > okay, I am okay as well. > 2. adopting it, which will lead to a significant performance penalty, > which I am not eager to sacrifice. > > Basically, when someone is telling me that everything is internally > converted to `unicode`, so that I do not worry about encoding > exceptions, and my text that should not be escaped should stay > un-escaped whatever we try to do to it, it reads to me the following: > you will get a significant penalty by multiple `unicode` > instantiations, because we are taking care of you not to do stupid > things. And sometimes it reads that we are not 100% sure what's going > on inside our code, or we just think this is the only way to go, and > we will trade speed for stability. But when I use Jinja 2 `escape` > which uses `Markup`, and when I run the Big Table performance test, my > extension is 4x slower. This is a huge trade-off for me, and I am not > eager to sacrifice it. I am not criticizing the design decisions made, > actually, they are just not suitable for me to adopt them. > > Thanks, > Zahari > I committed full support for Markup: >>> str(html.p(Markup('<strong> Text </strong>')))) '<p><strong> Text </strong></p>' >>> str(Markup(html.p(html.safe('<strong> Text </strong>')))) '<p><strong> Text </strong></p>' As I said earlier I protected my extension to the aggressive Markup behavior. Tests are working fine, I would count that task for completed, unless some objections arise. Thanks, Zahari
Sounds good, I will work on that now. Thanks, Zahari On Mon, Nov 8, 2010 at 3:02 PM, Armin Ronacher <armin.ronacher@active-4.com> wrote: > Hi, > > On 2010-11-08 1:17 PM, Zahari Petkov wrote: >> I will look at Markup of Jinja and Genshi, to see whether I am missing >> something. html.safe is quite a simple operation in my extension - >> just returning a string as is without escaping it. > Make sure to support Markup or its impossible for this extension to ever > get a seal of approval :) > > > Regards, > Armin >
Looks awesome. Nice work on the documentation. -- Jonas On Sun, Nov 7, 2010 at 9:32 PM, Zahari Petkov <zarchaoz@gmail.com> wrote: > Hey guys, > > I just committed my Flask-HTMLBuilder extension: > source: http://github.com/majorz/flask-htmlbuilder > documentation: http://majorz.github.com/flask-htmlbuilder/ > > I used the Flask extension generator for initial skeleton creation. > Documentation is using flask_small theme. I tried to follow closely > the recommendations and looked how other extensions were done. I would > to ask for an initial review process. > > Thanks, > Zahari > > On Tue, Nov 2, 2010 at 7:39 PM, Zahari Petkov <zarchaoz@gmail.com> wrote: > > Hello, > > > > I am working on a HTML builder type Flask extension, similar to the > > HTML builder in Werkzeug, but with more features, which target full > > HTML document generation. It has support for HTML comments, doctype > > definition, and both escaped/unescaped HTML text, etc. It takes > > advantage of the Werkzeug endpoint system and defines template > > inheritance mechanisms using decorators around it. I targeted > > real-world HTML document generation with that. > > > > The source is still in a private repository, since I need to clean > > that up as much as possible and make sure test coverage is full, but I > > wrote a short use case application in which I included detailed > > description: > > https://gist.github.com/f5de9c33341400cc01b6 > > > > I will make the repository public in the following days. > > > > I will be glad if I receive some feedback about it. Any comments? > > > > Regards, > > Zahari > > >
Thanks for the nice words Jonas, writing that documentation was time consuming, but necessary. I will improve it further, and I will add an examples (or contrib) folder with some real-world edgy HTML, so that people may get started even quicker using it. Zahari On Mon, Nov 8, 2010 at 7:23 AM, Jonas Galvez <jonasgalvez@gmail.com> wrote: > Looks awesome. Nice work on the documentation. > -- Jonas > > On Sun, Nov 7, 2010 at 9:32 PM, Zahari Petkov <zarchaoz@gmail.com> wrote: >> >> Hey guys, >> >> I just committed my Flask-HTMLBuilder extension: >> source: http://github.com/majorz/flask-htmlbuilder >> documentation: http://majorz.github.com/flask-htmlbuilder/ >> >> I used the Flask extension generator for initial skeleton creation. >> Documentation is using flask_small theme. I tried to follow closely >> the recommendations and looked how other extensions were done. I would >> to ask for an initial review process. >> >> Thanks, >> Zahari >> >> On Tue, Nov 2, 2010 at 7:39 PM, Zahari Petkov <zarchaoz@gmail.com> wrote: >> > Hello, >> > >> > I am working on a HTML builder type Flask extension, similar to the >> > HTML builder in Werkzeug, but with more features, which target full >> > HTML document generation. It has support for HTML comments, doctype >> > definition, and both escaped/unescaped HTML text, etc. It takes >> > advantage of the Werkzeug endpoint system and defines template >> > inheritance mechanisms using decorators around it. I targeted >> > real-world HTML document generation with that. >> > >> > The source is still in a private repository, since I need to clean >> > that up as much as possible and make sure test coverage is full, but I >> > wrote a short use case application in which I included detailed >> > description: >> > https://gist.github.com/f5de9c33341400cc01b6 >> > >> > I will make the repository public in the following days. >> > >> > I will be glad if I receive some feedback about it. Any comments? >> > >> > Regards, >> > Zahari >> > > >
Zahari Petkov wrote:
> I will be glad if I receive some feedback about it. Any comments?
You might want to try html5witch[1]. I've been meaning to write a
Flask extension for it for some time now, but haven't gotten around to
it yet.
One particularly interesting feature I'm thinking of is being able to
keep standalone "html.py" templates with zero boilerplate, by using
Python 2.7's runpy.run_path() method[2]. Here's a very crude (and
untested) example of how it could work:
Inside templates/index.html.py:
with doc.html:
with doc.head:
doc.title('Title')
with doc.body:
doc.p('Hello World')
Inside app.py:
@app.route('/')
def index():
doc = html5witch.builder()
template = runpy.run_path('templates/index.html.py', init_globals=locals())
return Response(str(template.doc), 200)
--Jonas
[1] http://github.com/galvez/html5witch
[2] http://docs.python.org/library/runpy.html
Hey Jonas, I looked at your implementation a while ago and actually liked the indentation approach you took and borrowed the idea :) The with statement approach you are using is interesting and I like the innovation in it, but I prefer to stick with my current syntax. I will definitely follow your ongoing work with interest. Thanks, Zahari On Tue, Nov 2, 2010 at 10:48 PM, Jonas Galvez <jonasgalvez@gmail.com> wrote: > Zahari Petkov wrote: >> I will be glad if I receive some feedback about it. Any comments? > > You might want to try html5witch[1]. I've been meaning to write a > Flask extension for it for some time now, but haven't gotten around to > it yet. > > One particularly interesting feature I'm thinking of is being able to > keep standalone "html.py" templates with zero boilerplate, by using > Python 2.7's runpy.run_path() method[2]. Here's a very crude (and > untested) example of how it could work: > > Inside templates/index.html.py: > > with doc.html: > with doc.head: > doc.title('Title') > with doc.body: > doc.p('Hello World') > > Inside app.py: > > @app.route('/') > def index(): > doc = html5witch.builder() > template = runpy.run_path('templates/index.html.py', init_globals=locals()) > return Response(str(template.doc), 200) > > --Jonas > > [1] http://github.com/galvez/html5witch > [2] http://docs.python.org/library/runpy.html >