Lucumr CogitationsArmin Ronacher thinkingtag:localhost,2008-02-18/zxa_export:fullZineXA Export2008-02-18T10:06:17Zvessel_theme::blue.cssFalse/adminsqlite://zine.dbvessel_theme300Lucumr CogitationsTruezeml25TrueUTCvesselTrueTrue/tags/authors1/categoriesArmin Ronacher thinkingFalse10localhost1098503af9d94df0a1774a4bac5e3cf3TruedebugcacheFalseennullentrytextzine_sessionTruehttp://localhost:4000/g#YpbBKk9`y<TPD#jB#J>;.b^R9j$j>=^;x:|5F>@_hOw]`n@wzgxaxyrk0qYA$Izine.logFalseHow not to do XMLhttp://lucumr.pocoo.org/cogitations/2008/02/18/how-not-to-do-xml/2008-02-18T10:06:17Z2008-02-18T10:06:17ZArmin Ronacherhow-not-to-do-xmlyesyes2Imagine for the moment there <a href="http://wordpress.org/">was a PHP blog software</a> that has the ability to dump the blog posts into some sort of extended RSS 2 feed and import from there later and probably from a different installation. That's nice, XML is a flexible format and RSS allows extensions via namespaces. Even better, there are XML parsers for all major programming languages and from python working with XML is especially cool because of lxml and element tree. But there is a problem with that... ...that XML, is not XML. It's called WordPress eXtended RSS (WXR) but it's not XML? And why in god's name did nobody notice so far? I mean, WordPress must have an importer for that. Why it's not XML? It has XML syntax, XML namespace declarations but what doesn't it have? A doctype. What's the problem? It's referencing HTML entities! So step one for parsing: inject an inline DTD that defines those entities. Great fun isn't it? Then it parses. I was happy and finished my work. That XML doesn't have HTML entities is something PHP developers probably don't know and their parser isn't resolving any entities during the parsing process. Or worse, their XML parser expands HTML entites. But it's worse! I loaded another dump that happened to have some broken HTML in comments (could happen, does happen, thanks broken trackback support). What happens next? THE XML DOESN'T PARSE ANY MORE! Why? Because comments are neither escaped nor marked as CDATA. I wonder why, especially because it's so much easier to handle embedded HTML/XHTML for dumping as cdata and not XML, especially if you are working with PHP. But WordPress was able to import that.... so I looked at their parser.... <a href="http://trac.wordpress.org/browser/trunk/wp-admin/import/wordpress.php?rev=6870">WORDPRESS PARSES THAT WXR FILE</a> USING REGULAR EXPRESSIONS!!! Argharhgarhghargh. That's not XML what you are doing there, that's nothing. WordPress can't even parse it's own file if you bind the WordPress exporter namespace to a different prefix! WordPress can't handle it's own file if you replace their CDATA foobar against properly escaped stuff. Dammit! I can't even write a proper exporter using XML tools because what my XML tools generate is not compatible to WordPress. And what tops it all? Reading that in the #wordpress channel: <!-- PYGMENTS_CACHE><div class="highlight"><pre><span class="nt">&lt;nickname_deleted&gt; </span>why does it matter what wp&#39;s xml format has flaws? adapt your importer to the flaws </pre></div> <PYGMENTS_CACHE --><!-- PYGMENTS_RAW(irc)><nickname_deleted> why does it matter what wp's xml format has flaws? adapt your importer to the flaws<PYGMENTS_RAW --> ARGHARGHARGHARGH. and then the webpage says: <blockquote>WordPress is a state-of-the-art semantic personal publishing platform with a focus on aesthetics, web standards, and usability.</blockquote> Without further comments... I lost my faith into standards that moment. Wait a second, I lost it earlier. Still sad.Imagine for the moment there <a href="http://wordpress.org/">was a PHP blog software</a> that has the ability to dump the blog posts into some sort of extended RSS 2 feed and import from there later and probably from a different installation. That's nice, XML is a flexible format and RSS allows extensions via namespaces. Even better, there are XML parsers for all major programming languages and from python working with XML is especially cool because of lxml and element tree. But there is a problem with that... ...that XML, is not XML. It's called WordPress eXtended RSS (WXR) but it's not XML? And why in god's name did nobody notice so far? I mean, WordPress must have an importer for that. Why it's not XML? It has XML syntax, XML namespace declarations but what doesn't it have? A doctype. What's the problem? It's referencing HTML entities! So step one for parsing: inject an inline DTD that defines those entities. Great fun isn't it? Then it parses. I was happy and finished my work. That XML doesn't have HTML entities is something PHP developers probably don't know and their parser isn't resolving any entities during the parsing process. Or worse, their XML parser expands HTML entites. But it's worse! I loaded another dump that happened to have some broken HTML in comments (could happen, does happen, thanks broken trackback support). What happens next? THE XML DOESN'T PARSE ANY MORE! Why? Because comments are neither escaped nor marked as CDATA. I wonder why, especially because it's so much easier to handle embedded HTML/XHTML for dumping as cdata and not XML, especially if you are working with PHP. But WordPress was able to import that.... so I looked at their parser.... <a href="http://trac.wordpress.org/browser/trunk/wp-admin/import/wordpress.php?rev=6870">WORDPRESS PARSES THAT WXR FILE</a> USING REGULAR EXPRESSIONS!!! Argharhgarhghargh. That's not XML what you are doing there, that's nothing. WordPress can't even parse it's own file if you bind the WordPress exporter namespace to a different prefix! WordPress can't handle it's own file if you replace their CDATA foobar against properly escaped stuff. Dammit! I can't even write a proper exporter using XML tools because what my XML tools generate is not compatible to WordPress. And what tops it all? Reading that in the #wordpress channel: ARGHARGHARGHARGH. and then the webpage says: <blockquote>WordPress is a state-of-the-art semantic personal publishing platform with a focus on aesthetics, web standards, and usability.</blockquote> Without further comments... I lost my faith into standards that moment. Wait a second, I lost it earlier. Still sad.SQAAAANTAAAABGJvZHlSUwAAAB1JbWFnaW5lIGZvciB0aGUgbW9tZW50IHRoZXJlIEwAA0VTAAAA AWFMAABNAAFTAAAABGhyZWZTAAAAFWh0dHA6Ly93b3JkcHJlc3Mub3JnL1MAAAAXd2FzIGEgUEhQ IGJsb2cgc29mdHdhcmVTAAAGTyB0aGF0IGhhcyB0aGUgYWJpbGl0eSB0byBkdW1wIHRoZSBibG9n IHBvc3RzIGludG8gc29tZSBzb3J0IG9mIGV4dGVuZGVkIFJTUyAyIGZlZWQgYW5kIGltcG9ydCBm cm9tIHRoZXJlIGxhdGVyIGFuZCBwcm9iYWJseSBmcm9tIGEgZGlmZmVyZW50IGluc3RhbGxhdGlv bi4gVGhhdCdzIG5pY2UsIFhNTCBpcyBhIGZsZXhpYmxlIGZvcm1hdCBhbmQgUlNTIGFsbG93cyBl eHRlbnNpb25zIHZpYSBuYW1lc3BhY2VzLiBFdmVuIGJldHRlciwgdGhlcmUgYXJlIFhNTCBwYXJz ZXJzIGZvciBhbGwgbWFqb3IgcHJvZ3JhbW1pbmcgbGFuZ3VhZ2VzIGFuZCBmcm9tIHB5dGhvbiB3 b3JraW5nIHdpdGggWE1MIGlzIGVzcGVjaWFsbHkgY29vbCBiZWNhdXNlIG9mIGx4bWwgYW5kIGVs ZW1lbnQgdHJlZS4gQnV0IHRoZXJlIGlzIGEgcHJvYmxlbSB3aXRoIHRoYXQuLi4KCi4uLnRoYXQg WE1MLCBpcyBub3QgWE1MLiBJdCdzIGNhbGxlZCBXb3JkUHJlc3MgZVh0ZW5kZWQgUlNTIChXWFIp IGJ1dCBpdCdzIG5vdCBYTUw/IEFuZCB3aHkgaW4gZ29kJ3MgbmFtZSBkaWQgbm9ib2R5IG5vdGlj ZSBzbyBmYXI/IEkgbWVhbiwgV29yZFByZXNzIG11c3QgaGF2ZSBhbiBpbXBvcnRlciBmb3IgdGhh dC4KCldoeSBpdCdzIG5vdCBYTUw/IEl0IGhhcyBYTUwgc3ludGF4LCBYTUwgbmFtZXNwYWNlIGRl Y2xhcmF0aW9ucyBidXQgd2hhdCBkb2Vzbid0IGl0IGhhdmU/IEEgZG9jdHlwZS4gV2hhdCdzIHRo ZSBwcm9ibGVtPyBJdCdzIHJlZmVyZW5jaW5nIEhUTUwgZW50aXRpZXMhIFNvIHN0ZXAgb25lIGZv ciBwYXJzaW5nOiBpbmplY3QgYW4gaW5saW5lIERURCB0aGF0IGRlZmluZXMgdGhvc2UgZW50aXRp ZXMuIEdyZWF0IGZ1biBpc24ndCBpdD8gVGhlbiBpdCBwYXJzZXMuIEkgd2FzIGhhcHB5IGFuZCBm aW5pc2hlZCBteSB3b3JrLiBUaGF0IFhNTCBkb2Vzbid0IGhhdmUgSFRNTCBlbnRpdGllcyBpcyBz b21ldGhpbmcgUEhQIGRldmVsb3BlcnMgcHJvYmFibHkgZG9uJ3Qga25vdyBhbmQgdGhlaXIgcGFy c2VyIGlzbid0IHJlc29sdmluZyBhbnkgZW50aXRpZXMgZHVyaW5nIHRoZSBwYXJzaW5nIHByb2Nl c3MuIE9yIHdvcnNlLCB0aGVpciBYTUwgcGFyc2VyIGV4cGFuZHMgSFRNTCBlbnRpdGVzLgoKQnV0 IGl0J3Mgd29yc2UhIEkgbG9hZGVkIGFub3RoZXIgZHVtcCB0aGF0IGhhcHBlbmVkIHRvIGhhdmUg c29tZSBicm9rZW4gSFRNTCBpbiBjb21tZW50cyAoY291bGQgaGFwcGVuLCBkb2VzIGhhcHBlbiwg dGhhbmtzIGJyb2tlbiB0cmFja2JhY2sgc3VwcG9ydCkuIFdoYXQgaGFwcGVucyBuZXh0PyBUSEUg WE1MIERPRVNOJ1QgUEFSU0UgQU5ZIE1PUkUhIFdoeT8gQmVjYXVzZSBjb21tZW50cyBhcmUgbmVp dGhlciBlc2NhcGVkIG5vciBtYXJrZWQgYXMgQ0RBVEEuIEkgd29uZGVyIHdoeSwgZXNwZWNpYWxs eSBiZWNhdXNlIGl0J3Mgc28gbXVjaCBlYXNpZXIgdG8gaGFuZGxlIGVtYmVkZGVkIEhUTUwvWEhU TUwgZm9yIGR1bXBpbmcgYXMgY2RhdGEgYW5kIG5vdCBYTUwsIGVzcGVjaWFsbHkgaWYgeW91IGFy ZSB3b3JraW5nIHdpdGggUEhQLgoKQnV0IFdvcmRQcmVzcyB3YXMgYWJsZSB0byBpbXBvcnQgdGhh dC4uLi4gc28gSSBsb29rZWQgYXQgdGhlaXIgcGFyc2VyLi4uLiBFUwAAAAFhTAAATQABUwAAAARo cmVmUwAAAE5odHRwOi8vdHJhYy53b3JkcHJlc3Mub3JnL2Jyb3dzZXIvdHJ1bmsvd3AtYWRtaW4v aW1wb3J0L3dvcmRwcmVzcy5waHA/cmV2PTY4NzBTAAAAHldPUkRQUkVTUyBQQVJTRVMgVEhBVCBX WFIgRklMRVMAAAIsIFVTSU5HIFJFR1VMQVIgRVhQUkVTU0lPTlMhISEgQXJnaGFyaGdhcmhnaGFy Z2guIFRoYXQncyBub3QgWE1MIHdoYXQgeW91IGFyZSBkb2luZyB0aGVyZSwgdGhhdCdzIG5vdGhp bmcuIFdvcmRQcmVzcyBjYW4ndCBldmVuIHBhcnNlIGl0J3Mgb3duIGZpbGUgaWYgeW91IGJpbmQg dGhlIFdvcmRQcmVzcyBleHBvcnRlciBuYW1lc3BhY2UgdG8gYSBkaWZmZXJlbnQgcHJlZml4ISBX b3JkUHJlc3MgY2FuJ3QgaGFuZGxlIGl0J3Mgb3duIGZpbGUgaWYgeW91IHJlcGxhY2UgdGhlaXIg Q0RBVEEgZm9vYmFyIGFnYWluc3QgcHJvcGVybHkgZXNjYXBlZCBzdHVmZi4gRGFtbWl0IQoKSSBj YW4ndCBldmVuIHdyaXRlIGEgcHJvcGVyIGV4cG9ydGVyIHVzaW5nIFhNTCB0b29scyBiZWNhdXNl IHdoYXQgbXkgWE1MIHRvb2xzIGdlbmVyYXRlIGlzIG5vdCBjb21wYXRpYmxlIHRvIFdvcmRQcmVz cy4gQW5kIHdoYXQgdG9wcyBpdCBhbGw/CgpSZWFkaW5nIHRoYXQgaW4gdGhlICN3b3JkcHJlc3Mg Y2hhbm5lbDoKCkFSR0hBUkdIQVJHSEFSR0guIGFuZCB0aGVuIHRoZSB3ZWJwYWdlIHNheXM6CkVT AAAACmJsb2NrcXVvdGVMAABNAABTAAAAf1dvcmRQcmVzcyBpcyBhIHN0YXRlLW9mLXRoZS1hcnQg c2VtYW50aWMgcGVyc29uYWwgcHVibGlzaGluZyBwbGF0Zm9ybSB3aXRoIGEgZm9jdXMgb24gYWVz dGhldGljcywgd2ViIHN0YW5kYXJkcywgYW5kIHVzYWJpbGl0eS5TAAAAdQpXaXRob3V0IGZ1cnRo ZXIgY29tbWVudHMuLi4gSSBsb3N0IG15IGZhaXRoIGludG8gc3RhbmRhcmRzIHRoYXQgbW9tZW50 LiBXYWl0IGEgc2Vjb25kLCBJIGxvc3QgaXQgZWFybGllci4gU3RpbGwgc2FkLlMAAAAGcGFyc2Vy UwAAAARodG1sUwAAAAVpbnRyb1JTAAAAAEwAAA== Gustaf Eriksongerikson+comments@gmail.comhttp://gustaf.symbiandiaries.com/weblog/2008-02-18T12:06:28Znono0Those that do not understand XML will be forced to reimplement it badly, using regexps. To be honest, RSS2.0 is notoriously badly specced, hence Atom. One of the issues is embedded HTML. At least it's something that's close to XML, try looking at Movable Type's export "format" for something that will sear your soul.Those that do not understand XML will be forced to reimplement it badly, using regexps. To be honest, RSS2.0 is notoriously badly specced, hence Atom. One of the issues is embedded HTML. At least it's something that's close to XML, try looking at Movable Type's export "format" for something that will sear your soul.SQAAAAJTAAAABGJvZHlSUwAAAUBUaG9zZSB0aGF0IGRvIG5vdCB1bmRlcnN0YW5kIFhNTCB3aWxs IGJlIGZvcmNlZCB0byByZWltcGxlbWVudCBpdCBiYWRseSwgdXNpbmcgcmVnZXhwcy4KClRvIGJl IGhvbmVzdCwgUlNTMi4wIGlzIG5vdG9yaW91c2x5IGJhZGx5IHNwZWNjZWQsIGhlbmNlIEF0b20u IE9uZSBvZiB0aGUgaXNzdWVzIGlzIGVtYmVkZGVkIEhUTUwuIAoKQXQgbGVhc3QgaXQncyBzb21l dGhpbmcgdGhhdCdzIGNsb3NlIHRvIFhNTCwgdHJ5IGxvb2tpbmcgYXQgTW92YWJsZSBUeXBlJ3Mg ZXhwb3J0ICJmb3JtYXQiIGZvciBzb21ldGhpbmcgdGhhdCB3aWxsIHNlYXIgeW91ciBzb3VsLkwA AFMAAAAGcGFyc2VyUwAAAARodG1s Mikkel KamstruErlandsenmikkel.kamstrup@gmail.comhttp://grillbar.org2008-02-18T13:35:51Znono0If you try an use a non-sloppy XML parser on something you snooped of the web you are naiive. Atleast, that's what I've learned over the past year. Even if you pay a data provider for XML data (signed in the contract) you can not expect proper XML (also personal experience). You can yell and scream, complain, and refuse to pay - but in the end your users are waiting. You write that darn sloppy parser and get on with your life. Sorry - but that is how it is.If you try an use a non-sloppy XML parser on something you snooped of the web you are naiive. Atleast, that's what I've learned over the past year. Even if you pay a data provider for XML data (signed in the contract) you can not expect proper XML (also personal experience). You can yell and scream, complain, and refuse to pay - but in the end your users are waiting. You write that darn sloppy parser and get on with your life. Sorry - but that is how it is.SQAAAAJTAAAABGJvZHlSUwAAAc9JZiB5b3UgdHJ5IGFuIHVzZSBhIG5vbi1zbG9wcHkgWE1MIHBh cnNlciBvbiBzb21ldGhpbmcgeW91IHNub29wZWQgb2YgdGhlIHdlYiB5b3UgYXJlIG5haWl2ZS4g QXRsZWFzdCwgdGhhdCdzIHdoYXQgSSd2ZSBsZWFybmVkIG92ZXIgdGhlIHBhc3QgeWVhci4KCkV2 ZW4gaWYgeW91IHBheSBhIGRhdGEgcHJvdmlkZXIgZm9yIFhNTCBkYXRhIChzaWduZWQgaW4gdGhl IGNvbnRyYWN0KSB5b3UgY2FuIG5vdCBleHBlY3QgcHJvcGVyIFhNTCAoYWxzbyBwZXJzb25hbCBl eHBlcmllbmNlKS4gWW91IGNhbiB5ZWxsIGFuZCBzY3JlYW0sIGNvbXBsYWluLCBhbmQgcmVmdXNl IHRvIHBheSAtIGJ1dCBpbiB0aGUgZW5kIHlvdXIgdXNlcnMgYXJlIHdhaXRpbmcuIFlvdSB3cml0 ZSB0aGF0IGRhcm4gc2xvcHB5IHBhcnNlciBhbmQgZ2V0IG9uIHdpdGggeW91ciBsaWZlLgoKU29y cnkgLSBidXQgdGhhdCBpcyBob3cgaXQgaXMuTAAAUwAAAAZwYXJzZXJTAAAABGh0bWw= Florianpyalot@gmail.com2008-02-18T13:53:08Znono0php software, what do you expect?php software, what do you expect?SQAAAAJTAAAABGJvZHlSUwAAACFwaHAgc29mdHdhcmUsIHdoYXQgZG8geW91IGV4cGVjdD9MAABT AAAABnBhcnNlclMAAAAEaHRtbA== Meneer RRalf.Nieuwenhuijsen@gmail.com2008-02-18T15:09:34Znono0The real reason for this is that XML is so difficult to map onto most programming languages. The datatypes you end up working with are usually complicated. It seems designed without any knowledge of programming languages and the common ADT's. I tend to use json for machiene-talk (when I get to program both the client and server). It maps nicely onto most programming languages. Ways XML is abused: 1) people treat it like XHTML (cause: the default escaping in XML sucks, example: RSS) 2) people map another structure onto XML (cause: its a syntactic not a semantic spec, it does not tell a programming language which types correspond to the parsed string, example: xml-rpc) 3) people use it as a database (cause: they follow the hype, example: rhythmbox, gconf) People that do not understand XML are doomed to make the mistake of using it. We need a semantic interpretation. Such that a valid XML parser would turn a XML-integer into a signed integer, rather than returning only legal XML-integers as string which are then fed into some utility function of the programming language to be parsed. That utility function may accept a completely domain. Et voila, a nice, almost untraceble creepy bug introduced. We need a new data-standard. One that also specifies the semantic interpretation of the data. We also need a database-query-language-standard (to replace SQL, another horrible standard) that uses that new data-standard as the communication language. Also it would be nice (read: extremely important) if the data-standard not only included things such as integers, floats, strings, unicode, but also anynimous functions. (off course this requires some sort of minimal programming language model) The closest thing so far? Data-standard: JSON, Query-standard: CouchDB-style-queries Language-standard: Javascript? Lambda-calculus? Even javascript is already too complicated to easily create a parser and evaluator for. Perhaps just a lambda calculus? Just enough to communicate a piece of logic as data. I can't wait to see XML die. It's the wrong solution to the wrong problem.The real reason for this is that XML is so difficult to map onto most programming languages. The datatypes you end up working with are usually complicated. It seems designed without any knowledge of programming languages and the common ADT's. I tend to use json for machiene-talk (when I get to program both the client and server). It maps nicely onto most programming languages. Ways XML is abused: 1) people treat it like XHTML (cause: the default escaping in XML sucks, example: RSS) 2) people map another structure onto XML (cause: its a syntactic not a semantic spec, it does not tell a programming language which types correspond to the parsed string, example: xml-rpc) 3) people use it as a database (cause: they follow the hype, example: rhythmbox, gconf) People that do not understand XML are doomed to make the mistake of using it. We need a semantic interpretation. Such that a valid XML parser would turn a XML-integer into a signed integer, rather than returning only legal XML-integers as string which are then fed into some utility function of the programming language to be parsed. That utility function may accept a completely domain. Et voila, a nice, almost untraceble creepy bug introduced. We need a new data-standard. One that also specifies the semantic interpretation of the data. We also need a database-query-language-standard (to replace SQL, another horrible standard) that uses that new data-standard as the communication language. Also it would be nice (read: extremely important) if the data-standard not only included things such as integers, floats, strings, unicode, but also anynimous functions. (off course this requires some sort of minimal programming language model) The closest thing so far? Data-standard: JSON, Query-standard: CouchDB-style-queries Language-standard: Javascript? Lambda-calculus? Even javascript is already too complicated to easily create a parser and evaluator for. Perhaps just a lambda calculus? Just enough to communicate a piece of logic as data. I can't wait to see XML die. It's the wrong solution to the wrong problem.SQAAAAJTAAAABGJvZHlSUwAACDtUaGUgcmVhbCByZWFzb24gZm9yIHRoaXMgaXMgdGhhdCBYTUwg aXMgc28gZGlmZmljdWx0IHRvIG1hcCBvbnRvIG1vc3QgcHJvZ3JhbW1pbmcgbGFuZ3VhZ2VzLiBU aGUgZGF0YXR5cGVzIHlvdSBlbmQgdXAgd29ya2luZyB3aXRoIGFyZSB1c3VhbGx5IGNvbXBsaWNh dGVkLgoKSXQgc2VlbXMgZGVzaWduZWQgd2l0aG91dCBhbnkga25vd2xlZGdlIG9mIHByb2dyYW1t aW5nIGxhbmd1YWdlcyBhbmQgdGhlIGNvbW1vbiBBRFQncy4gIEkgdGVuZCB0byB1c2UganNvbiBm b3IgbWFjaGllbmUtdGFsayAod2hlbiBJIGdldCB0byBwcm9ncmFtIGJvdGggdGhlIGNsaWVudCBh bmQgc2VydmVyKS4gSXQgbWFwcyBuaWNlbHkgb250byBtb3N0IHByb2dyYW1taW5nIGxhbmd1YWdl cy4KCldheXMgWE1MIGlzIGFidXNlZDoKICAxKSBwZW9wbGUgdHJlYXQgaXQgbGlrZSBYSFRNTCAo Y2F1c2U6IHRoZSBkZWZhdWx0IGVzY2FwaW5nIGluIFhNTCBzdWNrcywgZXhhbXBsZTogUlNTKQog IDIpIHBlb3BsZSBtYXAgYW5vdGhlciBzdHJ1Y3R1cmUgb250byBYTUwgKGNhdXNlOiBpdHMgYSBz eW50YWN0aWMgbm90IGEgc2VtYW50aWMgc3BlYywgaXQgZG9lcyBub3QgdGVsbCBhIHByb2dyYW1t aW5nIGxhbmd1YWdlIHdoaWNoIHR5cGVzIGNvcnJlc3BvbmQgdG8gdGhlIHBhcnNlZCBzdHJpbmcs IGV4YW1wbGU6IHhtbC1ycGMpCiAgMykgcGVvcGxlIHVzZSBpdCBhcyBhIGRhdGFiYXNlIChjYXVz ZTogdGhleSBmb2xsb3cgdGhlIGh5cGUsIGV4YW1wbGU6IHJoeXRobWJveCwgZ2NvbmYpCgpQZW9w bGUgdGhhdCBkbyBub3QgdW5kZXJzdGFuZCBYTUwgYXJlIGRvb21lZCB0byBtYWtlIHRoZSBtaXN0 YWtlIG9mIHVzaW5nIGl0LiBXZSBuZWVkIGEgc2VtYW50aWMgaW50ZXJwcmV0YXRpb24uIFN1Y2gg dGhhdCBhIHZhbGlkIFhNTCBwYXJzZXIgd291bGQgdHVybiBhIFhNTC1pbnRlZ2VyIGludG8gYSBz aWduZWQgaW50ZWdlciwgcmF0aGVyIHRoYW4gcmV0dXJuaW5nIG9ubHkgbGVnYWwgWE1MLWludGVn ZXJzIGFzIHN0cmluZyB3aGljaCBhcmUgdGhlbiBmZWQgaW50byBzb21lIHV0aWxpdHkgZnVuY3Rp b24gb2YgdGhlIHByb2dyYW1taW5nIGxhbmd1YWdlIHRvIGJlIHBhcnNlZC4gVGhhdCB1dGlsaXR5 IGZ1bmN0aW9uIG1heSBhY2NlcHQgYSBjb21wbGV0ZWx5IGRvbWFpbi4gRXQgdm9pbGEsIGEgbmlj ZSwgYWxtb3N0IHVudHJhY2VibGUgY3JlZXB5IGJ1ZyBpbnRyb2R1Y2VkLgoKV2UgbmVlZCBhIG5l dyBkYXRhLXN0YW5kYXJkLiBPbmUgdGhhdCBhbHNvIHNwZWNpZmllcyB0aGUgc2VtYW50aWMgaW50 ZXJwcmV0YXRpb24gb2YgdGhlIGRhdGEuIFdlIGFsc28gbmVlZCBhIGRhdGFiYXNlLXF1ZXJ5LWxh bmd1YWdlLXN0YW5kYXJkICh0byByZXBsYWNlIFNRTCwgYW5vdGhlciBob3JyaWJsZSBzdGFuZGFy ZCkgdGhhdCB1c2VzIHRoYXQgbmV3IGRhdGEtc3RhbmRhcmQgYXMgdGhlIGNvbW11bmljYXRpb24g bGFuZ3VhZ2UuIEFsc28gaXQgd291bGQgYmUgbmljZSAocmVhZDogZXh0cmVtZWx5IGltcG9ydGFu dCkgaWYgdGhlIGRhdGEtc3RhbmRhcmQgbm90IG9ubHkgaW5jbHVkZWQgdGhpbmdzIHN1Y2ggYXMg aW50ZWdlcnMsIGZsb2F0cywgc3RyaW5ncywgdW5pY29kZSwgYnV0IGFsc28gYW55bmltb3VzIGZ1 bmN0aW9ucy4gKG9mZiBjb3Vyc2UgdGhpcyByZXF1aXJlcyBzb21lIHNvcnQgb2YgbWluaW1hbCBw cm9ncmFtbWluZyBsYW5ndWFnZSBtb2RlbCkKClRoZSBjbG9zZXN0IHRoaW5nIHNvIGZhcj8gCiAg RGF0YS1zdGFuZGFyZDogSlNPTiwKICBRdWVyeS1zdGFuZGFyZDogQ291Y2hEQi1zdHlsZS1xdWVy aWVzCiAgTGFuZ3VhZ2Utc3RhbmRhcmQ6IEphdmFzY3JpcHQ/IExhbWJkYS1jYWxjdWx1cz8KCkV2 ZW4gamF2YXNjcmlwdCBpcyBhbHJlYWR5IHRvbyBjb21wbGljYXRlZCB0byBlYXNpbHkgY3JlYXRl IGEgcGFyc2VyIGFuZCBldmFsdWF0b3IgZm9yLiBQZXJoYXBzIGp1c3QgYSBsYW1iZGEgY2FsY3Vs dXM/IEp1c3QgZW5vdWdoIHRvIGNvbW11bmljYXRlIGEgcGllY2Ugb2YgbG9naWMgYXMgZGF0YS4K CkkgY2FuJ3Qgd2FpdCB0byBzZWUgWE1MIGRpZS4gSXQncyB0aGUgd3Jvbmcgc29sdXRpb24gdG8g dGhlIHdyb25nIHByb2JsZW0uTAAAUwAAAAZwYXJzZXJTAAAABGh0bWw= Shanti Brafordshantibraford@gmail.comhttp://onwebapps.com/2008-02-18T15:17:37Znono0Worse is better =)Worse is better =)SQAAAAJTAAAABGJvZHlSUwAAABJXb3JzZSBpcyBiZXR0ZXIgPSlMAABTAAAABnBhcnNlclMAAAAE aHRtbA== Meneer RRalf.Nieuwenhuijsen@gmail.com2008-02-18T15:18:45Znono0Typo, it should have been: &gt;&gt; That utility function may accept a completely DIFFERENT domain. Et voila, a nice, almost untraceble creepy bug introduced. I was talking about using a correct XML parser with a correct DOCTYPE that specifies legal integers. Yet the parser will return the legal integer as a STRING. This is not something easily overcome. It is an inherent aspect of the xml specification. If anything doctypes _only_ are like a parser specification, except you can only specify a subset of all parsers. Other than saying a document is legal, it does not associate any interpretation with the data at all.Typo, it should have been: &gt;&gt; That utility function may accept a completely DIFFERENT domain. Et voila, a nice, almost untraceble creepy bug introduced. I was talking about using a correct XML parser with a correct DOCTYPE that specifies legal integers. Yet the parser will return the legal integer as a STRING. This is not something easily overcome. It is an inherent aspect of the xml specification. If anything doctypes _only_ are like a parser specification, except you can only specify a subset of all parsers. Other than saying a document is legal, it does not associate any interpretation with the data at all.SQAAAAJTAAAABGJvZHlSUwAAAm1UeXBvLCBpdCBzaG91bGQgaGF2ZSBiZWVuOgoKPj4gVGhhdCB1 dGlsaXR5IGZ1bmN0aW9uIG1heSBhY2NlcHQgYSBjb21wbGV0ZWx5IERJRkZFUkVOVCBkb21haW4u IEV0IHZvaWxhLCBhIG5pY2UsIGFsbW9zdCB1bnRyYWNlYmxlIGNyZWVweSBidWcgaW50cm9kdWNl ZC4KCkkgd2FzIHRhbGtpbmcgYWJvdXQgdXNpbmcgYSBjb3JyZWN0IFhNTCBwYXJzZXIgd2l0aCBh IGNvcnJlY3QgRE9DVFlQRSB0aGF0IHNwZWNpZmllcyBsZWdhbCBpbnRlZ2Vycy4gWWV0IHRoZSBw YXJzZXIgd2lsbCByZXR1cm4gdGhlIGxlZ2FsIGludGVnZXIgYXMgYSBTVFJJTkcuIFRoaXMgaXMg bm90IHNvbWV0aGluZyBlYXNpbHkgb3ZlcmNvbWUuIEl0IGlzIGFuIGluaGVyZW50IGFzcGVjdCBv ZiB0aGUgeG1sIHNwZWNpZmljYXRpb24uIAoKSWYgYW55dGhpbmcgZG9jdHlwZXMgX29ubHlfIGFy ZSBsaWtlIGEgcGFyc2VyIHNwZWNpZmljYXRpb24sIGV4Y2VwdCB5b3UgY2FuIG9ubHkgc3BlY2lm eSBhIHN1YnNldCBvZiBhbGwgcGFyc2Vycy4gT3RoZXIgdGhhbiBzYXlpbmcgYSBkb2N1bWVudCBp cyBsZWdhbCwgaXQgZG9lcyBub3QgYXNzb2NpYXRlIGFueSBpbnRlcnByZXRhdGlvbiB3aXRoIHRo ZSBkYXRhIGF0IGFsbC5MAABTAAAABnBhcnNlclMAAAAEaHRtbA== Philluminatiprt_faber@hotmail.com2008-02-18T15:20:02Znono0Gustaf Erikson, please do not abuse or miss reference quotes. The quote originally goes "those who do not understand UNIX are condemned to reimplement it poorly".Gustaf Erikson, please do not abuse or miss reference quotes. The quote originally goes "those who do not understand UNIX are condemned to reimplement it poorly".SQAAAAJTAAAABGJvZHlSUwAAAKJHdXN0YWYgRXJpa3NvbiwgcGxlYXNlIGRvIG5vdCBhYnVzZSBv ciBtaXNzIHJlZmVyZW5jZSBxdW90ZXMuIFRoZSBxdW90ZSBvcmlnaW5hbGx5IGdvZXMgInRob3Nl IHdobyBkbyBub3QgdW5kZXJzdGFuZCBVTklYIGFyZSBjb25kZW1uZWQgdG8gcmVpbXBsZW1lbnQg aXQgcG9vcmx5Ii5MAABTAAAABnBhcnNlclMAAAAEaHRtbA== Aliaafshar@gmail.comhttp://unpythonic.blogspot.com/2008-02-18T16:07:09Znono0Use the regular expressions as a cross-language library, they are a feature here!Use the regular expressions as a cross-language library, they are a feature here!SQAAAAJTAAAABGJvZHlSUwAAAFFVc2UgdGhlIHJlZ3VsYXIgZXhwcmVzc2lvbnMgYXMgYSBjcm9z cy1sYW5ndWFnZSBsaWJyYXJ5LCB0aGV5IGFyZSBhIGZlYXR1cmUgaGVyZSFMAABTAAAABnBhcnNl clMAAAAEaHRtbA== Rudd-Orudd-o@rudd-o.comhttp://rudd-o.com/2008-02-18T16:07:20Znono0This type of moronic attitude favoring sloppiness over correctness is endemic in the WP developers. It explains why WP is always coming up with security vulnerabilities. It explains WP's choice of PHP as a language. It explains a lot. Have you seen the internal WP machinery? Have you seen how slow it is? Serving a page is comparably slow to Plone, but the difference is Plone does *so much, much more* than WP.This type of moronic attitude favoring sloppiness over correctness is endemic in the WP developers. It explains why WP is always coming up with security vulnerabilities. It explains WP's choice of PHP as a language. It explains a lot. Have you seen the internal WP machinery? Have you seen how slow it is? Serving a page is comparably slow to Plone, but the difference is Plone does *so much, much more* than WP.SQAAAAJTAAAABGJvZHlSUwAAAaJUaGlzIHR5cGUgb2YgbW9yb25pYyBhdHRpdHVkZSBmYXZvcmlu ZyBzbG9wcGluZXNzIG92ZXIgY29ycmVjdG5lc3MgaXMgZW5kZW1pYyBpbiB0aGUgV1AgZGV2ZWxv cGVycy4gIEl0IGV4cGxhaW5zIHdoeSBXUCBpcyBhbHdheXMgY29taW5nIHVwIHdpdGggc2VjdXJp dHkgdnVsbmVyYWJpbGl0aWVzLiAgSXQgZXhwbGFpbnMgV1AncyBjaG9pY2Ugb2YgUEhQIGFzIGEg bGFuZ3VhZ2UuICBJdCBleHBsYWlucyBhIGxvdC4KCkhhdmUgeW91IHNlZW4gdGhlIGludGVybmFs IFdQIG1hY2hpbmVyeT8gIEhhdmUgeW91IHNlZW4gaG93IHNsb3cgaXQgaXM/ICBTZXJ2aW5nIGEg cGFnZSBpcyBjb21wYXJhYmx5IHNsb3cgdG8gUGxvbmUsIGJ1dCB0aGUgZGlmZmVyZW5jZSBpcyBQ bG9uZSBkb2VzICpzbyBtdWNoLCBtdWNoIG1vcmUqIHRoYW4gV1AuTAAAUwAAAAZwYXJzZXJTAAAA BGh0bWw= Gustaf Eriksongerikson+comments@gmail.comhttp://gustaf.symbiandiaries.com/weblog/2008-02-18T16:22:22Znono0@Philluminati: I'm quite aware of the source and provenance of the quote you mention, I was paraphrasing it in a humorous way :)@Philluminati: I'm quite aware of the source and provenance of the quote you mention, I was paraphrasing it in a humorous way :)SQAAAAJTAAAABGJvZHlSUwAAAIBAUGhpbGx1bWluYXRpOiBJJ20gcXVpdGUgYXdhcmUgb2YgdGhl IHNvdXJjZSBhbmQgcHJvdmVuYW5jZSBvZiB0aGUgcXVvdGUgeW91IG1lbnRpb24sIEkgd2FzIHBh cmFwaHJhc2luZyBpdCBpbiBhIGh1bW9yb3VzIHdheSA6KUwAAFMAAAAGcGFyc2VyUwAAAARodG1s mridkashmrid_kash@yahoo.co.in2008-02-18T16:49:07Znono0@Meneer R "3) people use it as a database (cause: they follow the hype, example: rhythmbox, gconf)" I didn't get you. Please explain. As I know XML is generally used for storage of data. And w3c website says, "XML was designed to transport and store data." Link: http://www.w3schools.com/xml/default.asp@Meneer R "3) people use it as a database (cause: they follow the hype, example: rhythmbox, gconf)" I didn't get you. Please explain. As I know XML is generally used for storage of data. And w3c website says, "XML was designed to transport and store data." Link: http://www.w3schools.com/xml/default.aspSQAAAAJTAAAABGJvZHlSUwAAATFATWVuZWVyIFIgCiIzKSBwZW9wbGUgdXNlIGl0IGFzIGEgZGF0 YWJhc2UgKGNhdXNlOiB0aGV5IGZvbGxvdyB0aGUgaHlwZSwgZXhhbXBsZTogcmh5dGhtYm94LCBn Y29uZikiCgpJIGRpZG4ndCBnZXQgeW91LiBQbGVhc2UgZXhwbGFpbi4KQXMgSSBrbm93IFhNTCBp cyBnZW5lcmFsbHkgdXNlZCBmb3Igc3RvcmFnZSBvZiBkYXRhLiBBbmQgdzNjIHdlYnNpdGUgc2F5 cywKIlhNTCB3YXMgZGVzaWduZWQgdG8gdHJhbnNwb3J0IGFuZCBzdG9yZSBkYXRhLiIgTGluazog aHR0cDovL3d3dy53M3NjaG9vbHMuY29tL3htbC9kZWZhdWx0LmFzcEwAAFMAAAAGcGFyc2VyUwAA AARodG1s Armin Ronacherarmin.ronacher@active-4.comhttp://lucumr.pocoo.org/2008-02-18T17:52:50Znono0Just to clarify something: I love XML, I just find it very sad that there are very popular applications which just implement it so terrible wrong that it hurts.Just to clarify something: I love XML, I just find it very sad that there are very popular applications which just implement it so terrible wrong that it hurts.SQAAAAJTAAAABGJvZHlSUwAAAKBKdXN0IHRvIGNsYXJpZnkgc29tZXRoaW5nOiBJIGxvdmUgWE1M LCBJIGp1c3QgZmluZCBpdCB2ZXJ5IHNhZCB0aGF0IHRoZXJlIGFyZSB2ZXJ5IHBvcHVsYXIgYXBw bGljYXRpb25zIHdoaWNoIGp1c3QgaW1wbGVtZW50IGl0IHNvIHRlcnJpYmxlIHdyb25nIHRoYXQg aXQgaHVydHMuTAAAUwAAAAZwYXJzZXJTAAAABGh0bWw= Biffbiff@mailinator.com2008-02-18T18:12:35Znono0"Also it would be nice (read: extremely important) if the data-standard not only included things such as integers, floats, strings, unicode, but also anynimous functions." XML is not, and was never meant to be, a programming language."Also it would be nice (read: extremely important) if the data-standard not only included things such as integers, floats, strings, unicode, but also anynimous functions." XML is not, and was never meant to be, a programming language.SQAAAAJTAAAABGJvZHlSUwAAAOsiQWxzbyBpdCB3b3VsZCBiZSBuaWNlIChyZWFkOiBleHRyZW1l bHkgaW1wb3J0YW50KSBpZiB0aGUgZGF0YS1zdGFuZGFyZCBub3Qgb25seSBpbmNsdWRlZCB0aGlu Z3Mgc3VjaCBhcyBpbnRlZ2VycywgZmxvYXRzLCBzdHJpbmdzLCB1bmljb2RlLCBidXQgYWxzbyBh bnluaW1vdXMgZnVuY3Rpb25zLiIKClhNTCBpcyBub3QsIGFuZCB3YXMgbmV2ZXIgbWVhbnQgdG8g YmUsIGEgcHJvZ3JhbW1pbmcgbGFuZ3VhZ2UuTAAAUwAAAAZwYXJzZXJTAAAABGh0bWw= Ronny Pfannschmidtronny.pfannschmidt@gmx.de2008-02-18T18:14:08Znono0@Meneer R if you want lambda calculus - lisp has been there since ages - its parsable darn easy, and one of the most neat languages out there (simply cause its so extensible)@Meneer R if you want lambda calculus - lisp has been there since ages - its parsable darn easy, and one of the most neat languages out there (simply cause its so extensible)SQAAAAJTAAAABGJvZHlSUwAAAK5ATWVuZWVyIFIKaWYgeW91IHdhbnQgbGFtYmRhIGNhbGN1bHVz IC0gbGlzcCBoYXMgYmVlbiB0aGVyZSBzaW5jZSBhZ2VzIC0gaXRzIHBhcnNhYmxlIGRhcm4gZWFz eSwgYW5kIG9uZSBvZiB0aGUgbW9zdCBuZWF0IGxhbmd1YWdlcyBvdXQgdGhlcmUgKHNpbXBseSBj YXVzZSBpdHMgc28gZXh0ZW5zaWJsZSlMAABTAAAABnBhcnNlclMAAAAEaHRtbA== TextPress Development Blog Onlinehttp://lucumr.pocoo.org/cogitations/2008/02/16/textpress-development-blog-online/2008-02-16T14:38:34Z2008-02-16T14:38:34ZArmin Ronachertextpress-development-blog-onlineyesyes2TextPress has now a dedicated <a href="http://textpress.pocoo.org/">development blog</a>. That means two things. For one development on TextPress is active again and we are looking for help on converters, missing extensions (especially ATOM publishing support) and more. That development blog is of course running on TextPress ;-)TextPress has now a dedicated <a href="http://textpress.pocoo.org/">development blog</a>. That means two things. For one development on TextPress is active again and we are looking for help on converters, missing extensions (especially ATOM publishing support) and more. That development blog is of course running on TextPress ;-)SQAAAANTAAAABGJvZHlSUwAAAB5UZXh0UHJlc3MgaGFzIG5vdyBhIGRlZGljYXRlZCBMAAFFUwAA AAFhTAAATQABUwAAAARocmVmUwAAABtodHRwOi8vdGV4dHByZXNzLnBvY29vLm9yZy9TAAAAEGRl dmVsb3BtZW50IGJsb2dTAAAA8y4gVGhhdCBtZWFucyB0d28gdGhpbmdzLiBGb3Igb25lIGRldmVs b3BtZW50IG9uIFRleHRQcmVzcyBpcyBhY3RpdmUgYWdhaW4gYW5kIHdlIGFyZSBsb29raW5nIGZv ciBoZWxwIG9uIGNvbnZlcnRlcnMsIG1pc3NpbmcgZXh0ZW5zaW9ucyAoZXNwZWNpYWxseSBBVE9N IHB1Ymxpc2hpbmcgc3VwcG9ydCkgYW5kIG1vcmUuCgpUaGF0IGRldmVsb3BtZW50IGJsb2cgaXMg b2YgY291cnNlIHJ1bm5pbmcgb24gVGV4dFByZXNzIDstKVMAAAAGcGFyc2VyUwAAAARodG1sUwAA AAVpbnRyb1JTAAAAAEwAAA== GHRML — Haml for Genshihttp://lucumr.pocoo.org/cogitations/2008/02/15/ghrml-haml-for-genshi/2008-02-15T22:34:03Z2008-02-15T22:34:03ZArmin Ronacherghrml-haml-for-genshiyesyes2May I introduce: GHRML, the <strong>G</strong>enshi <strong>H</strong>uman <strong>r</strong>eadable <strong>m</strong>arkup <strong>l</strong>anguage. <small>name not final of course, <a href="http://michael-prokop.at/blog/">mika</a> would kill me ^^</small>. What's GHRML? First of all it's work in progress. But beside that it's a pretty cool clone of <a href="http://haml.hamptoncatlin.com/">Haml</a> for Python. But no, it's not another templating language, just a different representation for genshi markup templates. This way we can reuse all the genshi features like the directives or serializers. This gives you the full capabilities of the genshi templating language in a nice alternative syntax. So how does it look like? Here a small example: <!-- PYGMENTS_CACHE><div class="highlight"><pre>%html %head %title Hello World %style{&#39;type&#39;: &#39;text/css&#39;} body { font-family: sans-serif; } %script{&#39;type&#39;: &#39;text/javascript&#39;, &#39;src&#39;: &#39;foo.js&#39;} %body #header %h1 Hello World %ul.navigation %li[for item in navigation] %a{&#39;href&#39;: item.href} $item.caption #contents Hello World! </pre></div> <PYGMENTS_CACHE --><!-- PYGMENTS_RAW(text)> %html %head %title Hello World %style{'type': 'text/css'} body { font-family: sans-serif; } %script{'type': 'text/javascript', 'src': 'foo.js'} %body #header %h1 Hello World %ul.navigation %li[for item in navigation] %a{'href': item.href} $item.caption #contents Hello World!<PYGMENTS_RAW --> Most of the syntax is directly stolen from <a href="http://haml.hamptoncatlin.com/">Haml</a>. The only real change is that we don't need explicitly marked self closing elements because genshi knows that already in the serializer. Additionally you can use brackets for genshi directives like the for-loop above. And the parser works with variable indentation, if you want an indention level of four, just do so, the parser will recognize that. Sourcecode in the sandbox for those of you who want to try it, some updates later ;-)May I introduce: GHRML, the <strong>G</strong>enshi <strong>H</strong>uman <strong>r</strong>eadable <strong>m</strong>arkup <strong>l</strong>anguage. <small>name not final of course, <a href="http://michael-prokop.at/blog/">mika</a> would kill me ^^</small>. What's GHRML? First of all it's work in progress. But beside that it's a pretty cool clone of <a href="http://haml.hamptoncatlin.com/">Haml</a> for Python. But no, it's not another templating language, just a different representation for genshi markup templates. This way we can reuse all the genshi features like the directives or serializers. This gives you the full capabilities of the genshi templating language in a nice alternative syntax. So how does it look like? Here a small example: Most of the syntax is directly stolen from <a href="http://haml.hamptoncatlin.com/">Haml</a>. The only real change is that we don't need explicitly marked self closing elements because genshi knows that already in the serializer. Additionally you can use brackets for genshi directives like the for-loop above. And the parser works with variable indentation, if you want an indention level of four, just do so, the parser will recognize that. Sourcecode in the sandbox for those of you who want to try it, some updates later ;-)SQAAAANTAAAABGJvZHlSUwAAABxNYXkgSSBpbnRyb2R1Y2U6IEdIUk1MLCB0aGUgTAAIRVMAAAAG c3Ryb25nTAAATQAAUwAAAAFHUwAAAAZlbnNoaSBFUwAAAAZzdHJvbmdMAABNAABTAAAAAUhTAAAA BXVtYW4gRVMAAAAGc3Ryb25nTAAATQAAUwAAAAFyUwAAAAhlYWRhYmxlIEVTAAAABnN0cm9uZ0wA AE0AAFMAAAABbVMAAAAGYXJrdXAgRVMAAAAGc3Ryb25nTAAATQAAUwAAAAFsUwAAAAlhbmd1YWdl LiBFUwAAAAVzbWFsbEwAAUVTAAAAAWFMAABNAAFTAAAABGhyZWZTAAAAHmh0dHA6Ly9taWNoYWVs LXByb2tvcC5hdC9ibG9nL1MAAAAEbWlrYVMAAAARIHdvdWxkIGtpbGwgbWUgXl5NAABTAAAAGm5h bWUgbm90IGZpbmFsIG9mIGNvdXJzZSwgUwAAAGEuCgpXaGF0J3MgR0hSTUw/IEZpcnN0IG9mIGFs bCBpdCdzIHdvcmsgaW4gcHJvZ3Jlc3MuIEJ1dCBiZXNpZGUgdGhhdCBpdCdzIGEgcHJldHR5IGNv b2wgY2xvbmUgb2YgRVMAAAABYUwAAE0AAVMAAAAEaHJlZlMAAAAeaHR0cDovL2hhbWwuaGFtcHRv bmNhdGxpbi5jb20vUwAAAARIYW1sUwAAAY4gZm9yIFB5dGhvbi4gQnV0IG5vLCBpdCdzIG5vdCBh bm90aGVyIHRlbXBsYXRpbmcgbGFuZ3VhZ2UsIGp1c3QgYSBkaWZmZXJlbnQgcmVwcmVzZW50YXRp b24gZm9yIGdlbnNoaSBtYXJrdXAgdGVtcGxhdGVzLiBUaGlzIHdheSB3ZSBjYW4gcmV1c2UgYWxs IHRoZSBnZW5zaGkgZmVhdHVyZXMgbGlrZSB0aGUgZGlyZWN0aXZlcyBvciBzZXJpYWxpemVycy4g VGhpcyBnaXZlcyB5b3UgdGhlIGZ1bGwgY2FwYWJpbGl0aWVzIG9mIHRoZSBnZW5zaGkgdGVtcGxh dGluZyBsYW5ndWFnZSBpbiBhIG5pY2UgYWx0ZXJuYXRpdmUgc3ludGF4LgoKU28gaG93IGRvZXMg aXQgbG9vayBsaWtlPyBIZXJlIGEgc21hbGwgZXhhbXBsZToKCgoKTW9zdCBvZiB0aGUgc3ludGF4 IGlzIGRpcmVjdGx5IHN0b2xlbiBmcm9tIEVTAAAAAWFMAABNAAFTAAAABGhyZWZTAAAAHmh0dHA6 Ly9oYW1sLmhhbXB0b25jYXRsaW4uY29tL1MAAAAESGFtbFMAAAG1LiBUaGUgb25seSByZWFsIGNo YW5nZSBpcyB0aGF0IHdlIGRvbid0IG5lZWQgZXhwbGljaXRseSBtYXJrZWQgc2VsZiBjbG9zaW5n IGVsZW1lbnRzIGJlY2F1c2UgZ2Vuc2hpIGtub3dzIHRoYXQgYWxyZWFkeSBpbiB0aGUgc2VyaWFs aXplci4gQWRkaXRpb25hbGx5IHlvdSBjYW4gdXNlIGJyYWNrZXRzIGZvciBnZW5zaGkgZGlyZWN0 aXZlcyBsaWtlIHRoZSBmb3ItbG9vcCBhYm92ZS4gQW5kIHRoZSBwYXJzZXIgd29ya3Mgd2l0aCB2 YXJpYWJsZSBpbmRlbnRhdGlvbiwgaWYgeW91IHdhbnQgYW4gaW5kZW50aW9uIGxldmVsIG9mIGZv dXIsIGp1c3QgZG8gc28sIHRoZSBwYXJzZXIgd2lsbCByZWNvZ25pemUgdGhhdC4KClNvdXJjZWNv ZGUgaW4gdGhlIHNhbmRib3ggZm9yIHRob3NlIG9mIHlvdSB3aG8gd2FudCB0byB0cnkgaXQsIHNv bWUgdXBkYXRlcyBsYXRlciA7LSlTAAAABnBhcnNlclMAAAAEaHRtbFMAAAAFaW50cm9SUwAAAABM AAA= Toothynomail@for.me2008-02-16T01:15:38Znono0Dude, why are you wasting your time with this? It is ugly, it is inefficient and generating HTML from a silly approximated tag soup that is barely different from HTML is stupid.Dude, why are you wasting your time with this? It is ugly, it is inefficient and generating HTML from a silly approximated tag soup that is barely different from HTML is stupid.SQAAAAJTAAAABGJvZHlSUwAAALJEdWRlLCB3aHkgYXJlIHlvdSB3YXN0aW5nIHlvdXIgdGltZSB3 aXRoIHRoaXM/CgpJdCBpcyB1Z2x5LCBpdCBpcyBpbmVmZmljaWVudCBhbmQgZ2VuZXJhdGluZyBI VE1MIGZyb20gYSBzaWxseSBhcHByb3hpbWF0ZWQgdGFnIHNvdXAgdGhhdCBpcyBiYXJlbHkgZGlm ZmVyZW50IGZyb20gSFRNTCBpcyBzdHVwaWQuTAAAUwAAAAZwYXJzZXJTAAAABGh0bWw= Ronny Pfannschmidtronny.pfannschmidt@gmx.de2008-02-16T10:18:19Znono0great work - its much more pleasant than html/xhtml and gets both correct in the output :)great work - its much more pleasant than html/xhtml and gets both correct in the output :)SQAAAAJTAAAABGJvZHlSUwAAAFpncmVhdCB3b3JrIC0gaXRzIG11Y2ggbW9yZSBwbGVhc2FudCB0 aGFuIGh0bWwveGh0bWwgYW5kIGdldHMgYm90aCBjb3JyZWN0IGluIHRoZSBvdXRwdXQgOilMAABT AAAABnBhcnNlclMAAAAEaHRtbA== Waldemar Kornewaldwkornewald@freenet.de2008-02-16T11:29:20Znono0Wonderful! I've been waiting for this *so* long (you know it ;). I hope that soon we can get rid of that redundant HTML markup. Django already makes the underlying Python code more compact. This is the first step towards more compact template code (apart from generic views). Thank a lot! The next problem areas are CSS and JS (both of which need more than just syntax changes, I'd say).Wonderful! I've been waiting for this *so* long (you know it ;). I hope that soon we can get rid of that redundant HTML markup. Django already makes the underlying Python code more compact. This is the first step towards more compact template code (apart from generic views). Thank a lot! The next problem areas are CSS and JS (both of which need more than just syntax changes, I'd say).SQAAAAJTAAAABGJvZHlSUwAAAYRXb25kZXJmdWwhIEkndmUgYmVlbiB3YWl0aW5nIGZvciB0aGlz ICpzbyogbG9uZyAoeW91IGtub3cgaXQgOykuIEkgaG9wZSB0aGF0IHNvb24gd2UgY2FuIGdldCBy aWQgb2YgdGhhdCByZWR1bmRhbnQgSFRNTCBtYXJrdXAuIERqYW5nbyBhbHJlYWR5IG1ha2VzIHRo ZSB1bmRlcmx5aW5nIFB5dGhvbiBjb2RlIG1vcmUgY29tcGFjdC4gVGhpcyBpcyB0aGUgZmlyc3Qg c3RlcCB0b3dhcmRzIG1vcmUgY29tcGFjdCB0ZW1wbGF0ZSBjb2RlIChhcGFydCBmcm9tIGdlbmVy aWMgdmlld3MpLiBUaGFuayBhIGxvdCEKClRoZSBuZXh0IHByb2JsZW0gYXJlYXMgYXJlIENTUyBh bmQgSlMgKGJvdGggb2Ygd2hpY2ggbmVlZCBtb3JlIHRoYW4ganVzdCBzeW50YXggY2hhbmdlcywg SSdkIHNheSkuTAAAUwAAAAZwYXJzZXJTAAAABGh0bWw= Ronny Pfannschmidtronny.pfannschmidt@gmx.de2008-02-18T09:02:51Znono0take a look at clevercss - its in the pocoo sandboxtake a look at clevercss - its in the pocoo sandboxSQAAAAJTAAAABGJvZHlSUwAAADN0YWtlIGEgbG9vayBhdCBjbGV2ZXJjc3MgLSBpdHMgaW4gdGhl IHBvY29vIHNhbmRib3hMAABTAAAABnBhcnNlclMAAAAEaHRtbA== Meneer RRalf.Nieuwenhuijsen@gmail.com2008-02-18T15:24:18Znono0This looks like ruby. A fragment for your imagination: <pre> %li[for item in navigation] %a{'href': item.href} $item.caption </pre> woud be: <pre> navigation.foreach |item| -&gt; li.do a {href =&gt; item.href} item.caption end end</pre>This looks like ruby. A fragment for your imagination: <pre> %li[for item in navigation] %a{'href': item.href} $item.caption </pre> woud be: <pre> navigation.foreach |item| -&gt; li.do a {href =&gt; item.href} item.caption end end</pre>SQAAAAJTAAAABGJvZHlSUwAAADpUaGlzIGxvb2tzIGxpa2UgcnVieS4gCgpBIGZyYWdtZW50IGZv ciB5b3VyIGltYWdpbmF0aW9uOgoKTAACRVMAAAADcHJlTAAATQAAUwAAAEsgICVsaVtmb3IgaXRl bSBpbiBuYXZpZ2F0aW9uXQogICAgICAgICVheydocmVmJzogaXRlbS5ocmVmfSAkaXRlbS5jYXB0 aW9uICBTAAAADAoKd291ZCBiZToKCkVTAAAAA3ByZUwAAE0AAFMAAABiICBuYXZpZ2F0aW9uLmZv cmVhY2ggfGl0ZW18IC0+CiAgICAgbGkuZG8KICAgICAgIGEge2hyZWYgPT4gaXRlbS5ocmVmfSBp dGVtLmNhcHRpb24KICAgICBlbmQKICBlbmRTAAAAAFMAAAAGcGFyc2VyUwAAAARodG1s Werkzeug 0.2 Released!http://lucumr.pocoo.org/cogitations/2008/02/13/werkzeug-02-released/2008-02-13T23:01:12Z2008-02-13T23:01:12ZArmin Ronacherwerkzeug-02-releasedyesyes2Wohoo. <a href="http://werkzeug.pocoo.org/">Werkzeug</a> 0.2 is out now. Werkzeug started as simple collection of various utilities for WSGI applications and has become one of the most advanced WSGI utility modules. It includes a powerful debugger, full featured request and response objects, HTTP utilities to handle entity tags, cache control headers, HTTP dates, cookie handling, file uploads, a powerful URL routing system and a bunch of community contributed addon modules. So, what's new in 0.2? Countless things and too many for this small list, but here the most important ones: <ul> <li>The path converter limitation is gone. rejoice!</li> <li>In the contrib package there is now a secure cookie (basically a hashed a client side session storage)</li> <li>Exceptions can now return response objects so that you can add headers etc.</li> <li>You can now convert a response object to a different type of response objects on the fly (for example if you have your own response object subclass with special features but the response object returned by a function is a simple BaseResponse)</li> <li>There are a bunch of extra features for response and request objects now (available as mixin classes) for HTTP header parsing and dumping</li> <li>All the routing exceptions are now HTTPExceptions which simplifies dispatching a lot</li> <li>werkzeug.script has a much simpler way of specifying boolean parameters</li> <li>lazy_property is now called cached_property, update your code!</li> <li>many cool small helper functions that deal with python modules and packages. There is find_modules which can return a generator for all the modules below a package and import_string which allows you to simply import objects from a string. No more __import__ hackery needed.</li> <li>the usage of the map adapter is much easier now too and a lot more rest compliant. See the new documentation</li> <li>dozens of small fixes and additions!</li> </ul> There is also a <a href="http://werkzeug.pocoo.org/">new website</a> and <a href="http://werkzeug.pocoo.org/documentation/">documentation</a> and the tutorial was translated to German. For 0.3 we hopefully have some more translations for the tutorial and a better documentation for the contrib modules which are currently just documented in docstrings. <a href="http://pypi.python.org/pypi/Werkzeug/0.2">Grab it from the cheeseshop</a> while it's hot.Wohoo. <a href="http://werkzeug.pocoo.org/">Werkzeug</a> 0.2 is out now. Werkzeug started as simple collection of various utilities for WSGI applications and has become one of the most advanced WSGI utility modules. It includes a powerful debugger, full featured request and response objects, HTTP utilities to handle entity tags, cache control headers, HTTP dates, cookie handling, file uploads, a powerful URL routing system and a bunch of community contributed addon modules. So, what's new in 0.2? Countless things and too many for this small list, but here the most important ones: <ul> <li>The path converter limitation is gone. rejoice!</li> <li>In the contrib package there is now a secure cookie (basically a hashed a client side session storage)</li> <li>Exceptions can now return response objects so that you can add headers etc.</li> <li>You can now convert a response object to a different type of response objects on the fly (for example if you have your own response object subclass with special features but the response object returned by a function is a simple BaseResponse)</li> <li>There are a bunch of extra features for response and request objects now (available as mixin classes) for HTTP header parsing and dumping</li> <li>All the routing exceptions are now HTTPExceptions which simplifies dispatching a lot</li> <li>werkzeug.script has a much simpler way of specifying boolean parameters</li> <li>lazy_property is now called cached_property, update your code!</li> <li>many cool small helper functions that deal with python modules and packages. There is find_modules which can return a generator for all the modules below a package and import_string which allows you to simply import objects from a string. No more __import__ hackery needed.</li> <li>the usage of the map adapter is much easier now too and a lot more rest compliant. See the new documentation</li> <li>dozens of small fixes and additions!</li> </ul> There is also a <a href="http://werkzeug.pocoo.org/">new website</a> and <a href="http://werkzeug.pocoo.org/documentation/">documentation</a> and the tutorial was translated to German. For 0.3 we hopefully have some more translations for the tutorial and a better documentation for the contrib modules which are currently just documented in docstrings. <a href="http://pypi.python.org/pypi/Werkzeug/0.2">Grab it from the cheeseshop</a> while it's hot.SQAAAANTAAAABGJvZHlSUwAAAAdXb2hvby4gTAAFRVMAAAABYUwAAE0AAVMAAAAEaHJlZlMAAAAa aHR0cDovL3dlcmt6ZXVnLnBvY29vLm9yZy9TAAAACFdlcmt6ZXVnUwAAAhQgMC4yIGlzIG91dCBu b3cuIFdlcmt6ZXVnIHN0YXJ0ZWQgYXMgc2ltcGxlIGNvbGxlY3Rpb24gb2YgdmFyaW91cyB1dGls aXRpZXMgZm9yIFdTR0kgYXBwbGljYXRpb25zIGFuZCBoYXMgYmVjb21lIG9uZSBvZiB0aGUgbW9z dCBhZHZhbmNlZCBXU0dJIHV0aWxpdHkgbW9kdWxlcy4gSXQgaW5jbHVkZXMgYSBwb3dlcmZ1bCBk ZWJ1Z2dlciwgZnVsbCBmZWF0dXJlZCByZXF1ZXN0IGFuZCByZXNwb25zZSBvYmplY3RzLCBIVFRQ IHV0aWxpdGllcyB0byBoYW5kbGUgZW50aXR5IHRhZ3MsIGNhY2hlIGNvbnRyb2wgaGVhZGVycywg SFRUUCBkYXRlcywgY29va2llIGhhbmRsaW5nLCBmaWxlIHVwbG9hZHMsIGEgcG93ZXJmdWwgVVJM IHJvdXRpbmcgc3lzdGVtIGFuZCBhIGJ1bmNoIG9mIGNvbW11bml0eSBjb250cmlidXRlZCBhZGRv biBtb2R1bGVzLgoKU28sIHdoYXQncyBuZXcgaW4gMC4yPyBDb3VudGxlc3MgdGhpbmdzIGFuZCB0 b28gbWFueSBmb3IgdGhpcyBzbWFsbCBsaXN0LCBidXQgaGVyZSB0aGUgbW9zdCBpbXBvcnRhbnQg b25lczoKRVMAAAACdWxMAAtFUwAAAAJsaUwAAE0AAFMAAAAvVGhlIHBhdGggY29udmVydGVyIGxp bWl0YXRpb24gaXMgZ29uZS4gcmVqb2ljZSFTAAAAAQpFUwAAAAJsaUwAAE0AAFMAAABmSW4gdGhl IGNvbnRyaWIgcGFja2FnZSB0aGVyZSBpcyBub3cgYSBzZWN1cmUgY29va2llIChiYXNpY2FsbHkg YSBoYXNoZWQgYSBjbGllbnQgc2lkZSBzZXNzaW9uIHN0b3JhZ2UpUwAAAAEKRVMAAAACbGlMAABN AABTAAAAS0V4Y2VwdGlvbnMgY2FuIG5vdyByZXR1cm4gcmVzcG9uc2Ugb2JqZWN0cyBzbyB0aGF0 IHlvdSBjYW4gYWRkIGhlYWRlcnMgZXRjLlMAAAABCkVTAAAAAmxpTAAATQAAUwAAAPJZb3UgY2Fu IG5vdyBjb252ZXJ0IGEgcmVzcG9uc2Ugb2JqZWN0IHRvIGEgZGlmZmVyZW50IHR5cGUgb2YgcmVz cG9uc2Ugb2JqZWN0cyBvbiB0aGUgZmx5IChmb3IgZXhhbXBsZSBpZiB5b3UgaGF2ZSB5b3VyIG93 biByZXNwb25zZSBvYmplY3Qgc3ViY2xhc3Mgd2l0aCBzcGVjaWFsIGZlYXR1cmVzIGJ1dCB0aGUg cmVzcG9uc2Ugb2JqZWN0IHJldHVybmVkIGJ5IGEgZnVuY3Rpb24gaXMgYSBzaW1wbGUgQmFzZVJl c3BvbnNlKVMAAAABCkVTAAAAAmxpTAAATQAAUwAAAIlUaGVyZSBhcmUgYSBidW5jaCBvZiBleHRy YSBmZWF0dXJlcyBmb3IgcmVzcG9uc2UgYW5kIHJlcXVlc3Qgb2JqZWN0cyBub3cgKGF2YWlsYWJs ZSBhcyBtaXhpbiBjbGFzc2VzKSBmb3IgSFRUUCBoZWFkZXIgcGFyc2luZyBhbmQgZHVtcGluZ1MA AAABCkVTAAAAAmxpTAAATQAAUwAAAFRBbGwgdGhlIHJvdXRpbmcgZXhjZXB0aW9ucyBhcmUgbm93 IEhUVFBFeGNlcHRpb25zIHdoaWNoIHNpbXBsaWZpZXMgZGlzcGF0Y2hpbmcgYSBsb3RTAAAAAQpF UwAAAAJsaUwAAE0AAFMAAABHd2Vya3pldWcuc2NyaXB0IGhhcyBhIG11Y2ggc2ltcGxlciB3YXkg b2Ygc3BlY2lmeWluZyBib29sZWFuIHBhcmFtZXRlcnNTAAAAAQpFUwAAAAJsaUwAAE0AAFMAAAA+ bGF6eV9wcm9wZXJ0eSBpcyBub3cgY2FsbGVkIGNhY2hlZF9wcm9wZXJ0eSwgdXBkYXRlIHlvdXIg Y29kZSFTAAAAAQpFUwAAAAJsaUwAAE0AAFMAAAERbWFueSBjb29sIHNtYWxsIGhlbHBlciBmdW5j dGlvbnMgdGhhdCBkZWFsIHdpdGggcHl0aG9uIG1vZHVsZXMgYW5kIHBhY2thZ2VzLiBUaGVyZSBp cyBmaW5kX21vZHVsZXMgd2hpY2ggY2FuIHJldHVybiBhIGdlbmVyYXRvciBmb3IgYWxsIHRoZSBt b2R1bGVzIGJlbG93IGEgcGFja2FnZSBhbmQgaW1wb3J0X3N0cmluZyB3aGljaCBhbGxvd3MgeW91 IHRvIHNpbXBseSBpbXBvcnQgb2JqZWN0cyBmcm9tIGEgc3RyaW5nLiBObyBtb3JlIF9faW1wb3J0 X18gaGFja2VyeSBuZWVkZWQuUwAAAAEKRVMAAAACbGlMAABNAABTAAAAbHRoZSB1c2FnZSBvZiB0 aGUgbWFwIGFkYXB0ZXIgaXMgbXVjaCBlYXNpZXIgbm93IHRvbyBhbmQgYSBsb3QgbW9yZSByZXN0 IGNvbXBsaWFudC4gU2VlIHRoZSBuZXcgZG9jdW1lbnRhdGlvblMAAAABCkVTAAAAAmxpTAAATQAA UwAAACRkb3plbnMgb2Ygc21hbGwgZml4ZXMgYW5kIGFkZGl0aW9ucyFTAAAAAQpNAABTAAAAAQpT AAAAEgoKVGhlcmUgaXMgYWxzbyBhIEVTAAAAAWFMAABNAAFTAAAABGhyZWZTAAAAGmh0dHA6Ly93 ZXJremV1Zy5wb2Nvby5vcmcvUwAAAAtuZXcgd2Vic2l0ZVMAAAAFIGFuZCBFUwAAAAFhTAAATQAB UwAAAARocmVmUwAAAChodHRwOi8vd2Vya3pldWcucG9jb28ub3JnL2RvY3VtZW50YXRpb24vUwAA AA1kb2N1bWVudGF0aW9uUwAAANUgYW5kIHRoZSB0dXRvcmlhbCB3YXMgdHJhbnNsYXRlZCB0byBH ZXJtYW4uIEZvciAwLjMgd2UgaG9wZWZ1bGx5IGhhdmUgc29tZSBtb3JlIHRyYW5zbGF0aW9ucyBm b3IgdGhlIHR1dG9yaWFsIGFuZCBhIGJldHRlciBkb2N1bWVudGF0aW9uIGZvciB0aGUgY29udHJp YiBtb2R1bGVzIHdoaWNoIGFyZSBjdXJyZW50bHkganVzdCBkb2N1bWVudGVkIGluIGRvY3N0cmlu Z3MuCgpFUwAAAAFhTAAATQABUwAAAARocmVmUwAAAChodHRwOi8vcHlwaS5weXRob24ub3JnL3B5 cGkvV2Vya3pldWcvMC4yUwAAABtHcmFiIGl0IGZyb20gdGhlIGNoZWVzZXNob3BTAAAAECB3aGls ZSBpdCdzIGhvdC5TAAAABnBhcnNlclMAAAAEaHRtbFMAAAAFaW50cm9SUwAAAABMAAA= Ronny Pfannschmidtronny.pfannschmidt@gmx.de2008-02-13T23:07:36Znono0sweet - thanks for the good worksweet - thanks for the good workSQAAAAJTAAAABGJvZHlSUwAAACBzd2VldCAtIHRoYW5rcyBmb3IgdGhlIGdvb2Qgd29ya0wAAFMA AAAGcGFyc2VyUwAAAARodG1s Stuff you should buyhttp://lucumr.pocoo.org/cogitations/2008/02/13/stuff-you-should-buy/2008-02-13T17:47:03Z2008-02-13T17:47:03ZArmin Ronacherstuff-you-should-buyyesyes2The "Falco Symphonic" DVD. I know Falco is hyped currently here in Austria because that month ten years back he died (damn, I'm getting old) but the DVD is really worth it. For those of you who don't know the story behind that DVD here a small summary: 1994 Falco gave a concert with an orchestra. However the only record of that concert was a already (and bad mixed) tape from three cameras and a DAT tape directly from the mixer unit with the same quality. Because it was the only concert of that kind from Falco the band decided to record the instruments again and mix the original voice back into the new record. And the result is great. They even managed to get some records by fans so there are multiple angles for some scenes now. Great piece of music history and a brilliant production. Small hint: the CD features a different recording thatn the DVD, the DVD has eh live recording of the voice whereas the CD has a different arrangement of the instruments and Falco's voice from the studio recordings. Yes, it's not a real live version because the instruments are recorded in the studio afterwards but the impression is great. And in the studio the same musicians play and it's the only chance for us to get such a great recording in that quality so I think it's perfectly okay to listen to that ;-)The "Falco Symphonic" DVD. I know Falco is hyped currently here in Austria because that month ten years back he died (damn, I'm getting old) but the DVD is really worth it. For those of you who don't know the story behind that DVD here a small summary: 1994 Falco gave a concert with an orchestra. However the only record of that concert was a already (and bad mixed) tape from three cameras and a DAT tape directly from the mixer unit with the same quality. Because it was the only concert of that kind from Falco the band decided to record the instruments again and mix the original voice back into the new record. And the result is great. They even managed to get some records by fans so there are multiple angles for some scenes now. Great piece of music history and a brilliant production. Small hint: the CD features a different recording thatn the DVD, the DVD has eh live recording of the voice whereas the CD has a different arrangement of the instruments and Falco's voice from the studio recordings. Yes, it's not a real live version because the instruments are recorded in the studio afterwards but the impression is great. And in the studio the same musicians play and it's the only chance for us to get such a great recording in that quality so I think it's perfectly okay to listen to that ;-)SQAAAANTAAAABGJvZHlSUwAABR9UaGUgIkZhbGNvIFN5bXBob25pYyIgRFZELiBJIGtub3cgRmFs Y28gaXMgaHlwZWQgY3VycmVudGx5IGhlcmUgaW4gQXVzdHJpYSBiZWNhdXNlIHRoYXQgbW9udGgg dGVuIHllYXJzIGJhY2sgaGUgZGllZCAoZGFtbiwgSSdtIGdldHRpbmcgb2xkKSBidXQgdGhlIERW RCBpcyByZWFsbHkgd29ydGggaXQuIEZvciB0aG9zZSBvZiB5b3Ugd2hvIGRvbid0IGtub3cgdGhl IHN0b3J5IGJlaGluZCB0aGF0IERWRCBoZXJlIGEgc21hbGwgc3VtbWFyeToKCjE5OTQgRmFsY28g Z2F2ZSBhIGNvbmNlcnQgd2l0aCBhbiBvcmNoZXN0cmEuIEhvd2V2ZXIgdGhlIG9ubHkgcmVjb3Jk IG9mIHRoYXQgY29uY2VydCB3YXMgYSBhbHJlYWR5IChhbmQgYmFkIG1peGVkKSB0YXBlIGZyb20g dGhyZWUgY2FtZXJhcyBhbmQgYSBEQVQgdGFwZSBkaXJlY3RseSBmcm9tIHRoZSBtaXhlciB1bml0 IHdpdGggdGhlIHNhbWUgcXVhbGl0eS4gQmVjYXVzZSBpdCB3YXMgdGhlIG9ubHkgY29uY2VydCBv ZiB0aGF0IGtpbmQgZnJvbSBGYWxjbyB0aGUgYmFuZCBkZWNpZGVkIHRvIHJlY29yZCB0aGUgaW5z dHJ1bWVudHMgYWdhaW4gYW5kIG1peCB0aGUgb3JpZ2luYWwgdm9pY2UgYmFjayBpbnRvIHRoZSBu ZXcgcmVjb3JkLiBBbmQgdGhlIHJlc3VsdCBpcyBncmVhdC4gVGhleSBldmVuIG1hbmFnZWQgdG8g Z2V0IHNvbWUgcmVjb3JkcyBieSBmYW5zIHNvIHRoZXJlIGFyZSBtdWx0aXBsZSBhbmdsZXMgZm9y IHNvbWUgc2NlbmVzIG5vdy4KCkdyZWF0IHBpZWNlIG9mIG11c2ljIGhpc3RvcnkgYW5kIGEgYnJp bGxpYW50IHByb2R1Y3Rpb24uIFNtYWxsIGhpbnQ6IHRoZSBDRCBmZWF0dXJlcyBhIGRpZmZlcmVu dCByZWNvcmRpbmcgdGhhdG4gdGhlIERWRCwgdGhlIERWRCBoYXMgZWggbGl2ZSByZWNvcmRpbmcg b2YgdGhlIHZvaWNlIHdoZXJlYXMgdGhlIENEIGhhcyBhIGRpZmZlcmVudCBhcnJhbmdlbWVudCBv ZiB0aGUgaW5zdHJ1bWVudHMgYW5kIEZhbGNvJ3Mgdm9pY2UgZnJvbSB0aGUgc3R1ZGlvIHJlY29y ZGluZ3MuCgpZZXMsIGl0J3Mgbm90IGEgcmVhbCBsaXZlIHZlcnNpb24gYmVjYXVzZSB0aGUgaW5z dHJ1bWVudHMgYXJlIHJlY29yZGVkIGluIHRoZSBzdHVkaW8gYWZ0ZXJ3YXJkcyBidXQgdGhlIGlt cHJlc3Npb24gaXMgZ3JlYXQuIEFuZCBpbiB0aGUgc3R1ZGlvIHRoZSBzYW1lIG11c2ljaWFucyBw bGF5IGFuZCBpdCdzIHRoZSBvbmx5IGNoYW5jZSBmb3IgdXMgdG8gZ2V0IHN1Y2ggYSBncmVhdCBy ZWNvcmRpbmcgaW4gdGhhdCBxdWFsaXR5IHNvIEkgdGhpbmsgaXQncyBwZXJmZWN0bHkgb2theSB0 byBsaXN0ZW4gdG8gdGhhdCA7LSlMAABTAAAABnBhcnNlclMAAAAEaHRtbFMAAAAFaW50cm9SUwAA AABMAAA= How To Kill a Gamehttp://lucumr.pocoo.org/cogitations/2008/02/09/how-to-kill-a-game/2008-02-09T23:49:48Z2008-02-09T23:49:48ZArmin Ronacherhow-to-kill-a-gameyesyes2<img src="http://pocoo.org/~mitsuhiko/ssw_01.jpeg" class="thumbright" alt="A Söldner Screenshot" />About four years ago I stumbled about a promising game called "<a href="http://www.secretwars.net/">Söldner --- Secret Wars</a>" in a magazine. It was an online tactical shooter and featured a fully destroyable environment, more than one hundred weapons I think, many different vehicles, aircrafts and much more. It was hyped back then in the German gaming community, probably because it was developed by a German studio called "Wings". Long before the game was released the developers updated their online dairy about recent changes in the code, about what the game will feature and a lot more. Unfortunately they decided to release their game by <a href="http://www.jowood.com/">Jowood</a>, an Austrian publisher. Why was that bad? Back then Jowood once again had financial problems and they tried to solve it by convincing the sharedholders that their next game will be a major success. They set an totally unachievable release date and the developer team at wings had to live with that. It went that far that they had to design the box are themselves even though the game was still buggy. The game was released and was still buggy. I think GameStar even omitted the rating because they wanted to wait for the first patch. <img src="http://pocoo.org/~mitsuhiko/ssw_02.jpeg" class="thumbleft" alt="A Söldner Screenshot" />However the game sold pretty well the first two weeks despite the bad quality of the release version and the bad reviews. It even outsold the greatest competitor at that time (Joint Operations). I was one of the early adopters and I loved to play it. Owning a bad ISDN connection at that time it was terrible lagging, especially because their netcode was a catastrophe. Still, it was great fun and the destructible environment was great. Not only that, the game was somewhat revolutionary. It was the first online game I played with an (albeit bad configured) physics engine, it used python as scripting language, it had one big map that was generated from satellite images with detailed areas where the fights took place. You could buy yourself a jet and leave the map and visit all off Siberia. Not like Battlefield Vietnam where you hit the borders of the map with a jet after roughly 15 seconds. Dammit, it would still be fun and I bet it would have been bug-less by now. The community that appeared around that game was incredible. A wiki appeared, people tried to hack around on the code to get extra features into the game, unofficial mods appeared. There was even a project that wanted to create a mod for a medieval setting. Hell, it was great back then. But instead of fixing the bugs Jowood forced the developers to start an addon project... <img src="http://pocoo.org/~mitsuhiko/ssw_03.jpeg" class="thumbright" alt="A Söldner Screenshot" />Shortly after the addon was finished the company developing that game was liquidated. The developers lost their job and the community continued developing the closed code. The group around "project zero" continued maintaining the game until that group broke apart and the gEasy team took over the work. The gEasy team was basically just the project zero team without the founder. They did an tremendous job but Jowood once again destroyed everything. They refused to pay their bills, then the gEasy team took down the master server and Ivan Ertlov appeared on the scene. He managed to resolve the problems between Jowood and gEasy team to some extend that the master server was up and running again. Who's that Ivan Ertlov? Very good question indeed and I personally don't know the full story but from what I've read on the forums he is called Johann Ertl and owns a company that sells guerrilla marketing and similar services. And he worked for Jowood and apparently still does, at least he is listed as community manager in the official forums. He also brought up the topic "Open Sourcing" the code after it was clear that there will be no Söldner 2. A sequel was actually under consideration and gEasy started working on that till the day they took down the master server because there was no payment by Jowood. But since some time there was no feedback any more and an open source version is somewhat unlikely. <img src="http://pocoo.org/~mitsuhiko/ssw_04.jpeg" class="thumbleft" alt="A Söldner Screenshot" />Frankly I don't know if Jowood payed or didn't. What Jowood did was destroying the game by forcing an early release, forcing an addon when the code was still unfinished, fired the developers. Even worse: they are telling their shareholders that everything is working perfectly and that they are releasing dozens of new games. Hell, they released Spellforce 1 and 2 which both are awesome games (just happen to have the worst copy protection ever designed), the Gothic games (the 3rd part was buggy like Söldner but probably also because Jowood forced an early release). Jowood however claims that they payed and that gEasy was lying. Who is running the portal now? Apparently Ivan's company. So why am I blogging about all that? Mainly because I think that topic hasn't gained a lot of attraction. I stopped playing that game after Wings was liquidated. For one because I switched to ubuntu and on the other hand because my Söldner plugin (an in-game Winamp controller) disappeared when the forum was updated to reflect the new ownership. All the old topics where either deleted or made unreadable when Wings was closed down. <img src="http://pocoo.org/~mitsuhiko/ssw_05.jpeg" class="thumbright" alt="A Söldner Screenshot" />What nobody really notices is that the game had a tremendous German community. Hell, some of them even took over the development! If Jowood would have noticed that earlier they could have made that game the freaking best online shooter available at that time. But because of their small horizon they just thought about their next quarter and decided to do what shareholders want, not what players want. But not only Jowood is to blame but the root of all evil in that case. Krawall supported Jowood in the beginning to host their initial infrastructure needed for the game. Unfortunately the server software needed Direct X to run properly which caused a lot of trouble. One the one hand it was hard to get multiple servers running on one machine do to the way the server was designed, on the other hand you needed a windows server to host games. And because the initial code base was that buggy all the magazines flamed to game. Despite the good sales figures it magazines never wrote about the game and forced an early dead which harmed the community. A release six month later, a linux server from the beginning, no addon and good press coverage would have avoided all the problems this game was facing in the past. And it would have saved Wings, the game they were working on beside Söldner, and in the end of course Jowood which would have had a lot less bad press. Especially the gamers hate Jowood for their buggy products now and I doubt that they will be able to continue to ignore all the user feedback and push alpha versions as release versions for much longer. I'm especially interested what the Wings guys are doing now. I know that former Wings community manager and sound designed Marc Olbertz is working at Blizzard but that's about it. It's sad what happened there and that Austrian's only game publisher caused all that. <small><strong>Funky fact:</strong> The communication with the master server worked via jabber, the physics engine was ODE and the scripting language was Python. All open source technologies I never saw in a commercial game before :-)</small> <small><strong>Disclaimer:</strong> the information on this page should be accurate but it's hard to say for sure because there is few information about this topic actually available. If you are able to understand German you can find some information in this thread on the Söldner forums: <a href="http://www.secretwars.net/forum/showthread.php?t=41591">Söldner ein Abenteuer mit ungewissem Ausgang</a></small><img src="http://pocoo.org/~mitsuhiko/ssw_01.jpeg" alt="A Söldner Screenshot" class="thumbright">About four years ago I stumbled about a promising game called "<a href="http://www.secretwars.net/">Söldner --- Secret Wars</a>" in a magazine. It was an online tactical shooter and featured a fully destroyable environment, more than one hundred weapons I think, many different vehicles, aircrafts and much more. It was hyped back then in the German gaming community, probably because it was developed by a German studio called "Wings". Long before the game was released the developers updated their online dairy about recent changes in the code, about what the game will feature and a lot more. Unfortunately they decided to release their game by <a href="http://www.jowood.com/">Jowood</a>, an Austrian publisher. Why was that bad? Back then Jowood once again had financial problems and they tried to solve it by convincing the sharedholders that their next game will be a major success. They set an totally unachievable release date and the developer team at wings had to live with that. It went that far that they had to design the box are themselves even though the game was still buggy. The game was released and was still buggy. I think GameStar even omitted the rating because they wanted to wait for the first patch. <img src="http://pocoo.org/~mitsuhiko/ssw_02.jpeg" alt="A Söldner Screenshot" class="thumbleft">However the game sold pretty well the first two weeks despite the bad quality of the release version and the bad reviews. It even outsold the greatest competitor at that time (Joint Operations). I was one of the early adopters and I loved to play it. Owning a bad ISDN connection at that time it was terrible lagging, especially because their netcode was a catastrophe. Still, it was great fun and the destructible environment was great. Not only that, the game was somewhat revolutionary. It was the first online game I played with an (albeit bad configured) physics engine, it used python as scripting language, it had one big map that was generated from satellite images with detailed areas where the fights took place. You could buy yourself a jet and leave the map and visit all off Siberia. Not like Battlefield Vietnam where you hit the borders of the map with a jet after roughly 15 seconds. Dammit, it would still be fun and I bet it would have been bug-less by now. The community that appeared around that game was incredible. A wiki appeared, people tried to hack around on the code to get extra features into the game, unofficial mods appeared. There was even a project that wanted to create a mod for a medieval setting. Hell, it was great back then. But instead of fixing the bugs Jowood forced the developers to start an addon project... <img src="http://pocoo.org/~mitsuhiko/ssw_03.jpeg" alt="A Söldner Screenshot" class="thumbright">Shortly after the addon was finished the company developing that game was liquidated. The developers lost their job and the community continued developing the closed code. The group around "project zero" continued maintaining the game until that group broke apart and the gEasy team took over the work. The gEasy team was basically just the project zero team without the founder. They did an tremendous job but Jowood once again destroyed everything. They refused to pay their bills, then the gEasy team took down the master server and Ivan Ertlov appeared on the scene. He managed to resolve the problems between Jowood and gEasy team to some extend that the master server was up and running again. Who's that Ivan Ertlov? Very good question indeed and I personally don't know the full story but from what I've read on the forums he is called Johann Ertl and owns a company that sells guerrilla marketing and similar services. And he worked for Jowood and apparently still does, at least he is listed as community manager in the official forums. He also brought up the topic "Open Sourcing" the code after it was clear that there will be no Söldner 2. A sequel was actually under consideration and gEasy started working on that till the day they took down the master server because there was no payment by Jowood. But since some time there was no feedback any more and an open source version is somewhat unlikely. <img src="http://pocoo.org/~mitsuhiko/ssw_04.jpeg" alt="A Söldner Screenshot" class="thumbleft">Frankly I don't know if Jowood payed or didn't. What Jowood did was destroying the game by forcing an early release, forcing an addon when the code was still unfinished, fired the developers. Even worse: they are telling their shareholders that everything is working perfectly and that they are releasing dozens of new games. Hell, they released Spellforce 1 and 2 which both are awesome games (just happen to have the worst copy protection ever designed), the Gothic games (the 3rd part was buggy like Söldner but probably also because Jowood forced an early release). Jowood however claims that they payed and that gEasy was lying. Who is running the portal now? Apparently Ivan's company. So why am I blogging about all that? Mainly because I think that topic hasn't gained a lot of attraction. I stopped playing that game after Wings was liquidated. For one because I switched to ubuntu and on the other hand because my Söldner plugin (an in-game Winamp controller) disappeared when the forum was updated to reflect the new ownership. All the old topics where either deleted or made unreadable when Wings was closed down. <img src="http://pocoo.org/~mitsuhiko/ssw_05.jpeg" alt="A Söldner Screenshot" class="thumbright">What nobody really notices is that the game had a tremendous German community. Hell, some of them even took over the development! If Jowood would have noticed that earlier they could have made that game the freaking best online shooter available at that time. But because of their small horizon they just thought about their next quarter and decided to do what shareholders want, not what players want. But not only Jowood is to blame but the root of all evil in that case. Krawall supported Jowood in the beginning to host their initial infrastructure needed for the game. Unfortunately the server software needed Direct X to run properly which caused a lot of trouble. One the one hand it was hard to get multiple servers running on one machine do to the way the server was designed, on the other hand you needed a windows server to host games. And because the initial code base was that buggy all the magazines flamed to game. Despite the good sales figures it magazines never wrote about the game and forced an early dead which harmed the community. A release six month later, a linux server from the beginning, no addon and good press coverage would have avoided all the problems this game was facing in the past. And it would have saved Wings, the game they were working on beside Söldner, and in the end of course Jowood which would have had a lot less bad press. Especially the gamers hate Jowood for their buggy products now and I doubt that they will be able to continue to ignore all the user feedback and push alpha versions as release versions for much longer. I'm especially interested what the Wings guys are doing now. I know that former Wings community manager and sound designed Marc Olbertz is working at Blizzard but that's about it. It's sad what happened there and that Austrian's only game publisher caused all that. <small><strong>Funky fact:</strong> The communication with the master server worked via jabber, the physics engine was ODE and the scripting language was Python. All open source technologies I never saw in a commercial game before :-)</small> <small><strong>Disclaimer:</strong> the information on this page should be accurate but it's hard to say for sure because there is few information about this topic actually available. If you are able to understand German you can find some information in this thread on the Söldner forums: <a href="http://www.secretwars.net/forum/showthread.php?t=41591">Söldner ein Abenteuer mit ungewissem Ausgang</a></small>SQAAAANTAAAABGJvZHlSUwAAAABMAAlFUwAAAANpbWdMAABNAANTAAAAA3NyY1MAAAAnaHR0cDov L3BvY29vLm9yZy9+bWl0c3VoaWtvL3Nzd18wMS5qcGVnUwAAAANhbHRTAAAAFUEgU8O2bGRuZXIg U2NyZWVuc2hvdFMAAAAFY2xhc3NTAAAACnRodW1icmlnaHRTAAAAAFMAAAA/QWJvdXQgZm91ciB5 ZWFycyBhZ28gSSBzdHVtYmxlZCBhYm91dCBhIHByb21pc2luZyBnYW1lIGNhbGxlZCAiRVMAAAAB YUwAAE0AAVMAAAAEaHJlZlMAAAAaaHR0cDovL3d3dy5zZWNyZXR3YXJzLm5ldC9TAAAAGFPDtmxk bmVyIC0tLSBTZWNyZXQgV2Fyc1MAAAIJIiBpbiBhIG1hZ2F6aW5lLiBJdCB3YXMgYW4gb25saW5l IHRhY3RpY2FsIHNob290ZXIgYW5kIGZlYXR1cmVkIGEgZnVsbHkgZGVzdHJveWFibGUgZW52aXJv bm1lbnQsIG1vcmUgdGhhbiBvbmUgaHVuZHJlZCB3ZWFwb25zIEkgdGhpbmssIG1hbnkgZGlmZmVy ZW50IHZlaGljbGVzLCBhaXJjcmFmdHMgYW5kIG11Y2ggbW9yZS4gSXQgd2FzIGh5cGVkIGJhY2sg dGhlbiBpbiB0aGUgR2VybWFuIGdhbWluZyBjb21tdW5pdHksIHByb2JhYmx5IGJlY2F1c2UgaXQg d2FzIGRldmVsb3BlZCBieSBhIEdlcm1hbiBzdHVkaW8gY2FsbGVkICJXaW5ncyIuIExvbmcgYmVm b3JlIHRoZSBnYW1lIHdhcyByZWxlYXNlZCB0aGUgZGV2ZWxvcGVycyB1cGRhdGVkIHRoZWlyIG9u bGluZSBkYWlyeSBhYm91dCByZWNlbnQgY2hhbmdlcyBpbiB0aGUgY29kZSwgYWJvdXQgd2hhdCB0 aGUgZ2FtZSB3aWxsIGZlYXR1cmUgYW5kIGEgbG90IG1vcmUuIFVuZm9ydHVuYXRlbHkgdGhleSBk ZWNpZGVkIHRvIHJlbGVhc2UgdGhlaXIgZ2FtZSBieSBFUwAAAAFhTAAATQABUwAAAARocmVmUwAA ABZodHRwOi8vd3d3Lmpvd29vZC5jb20vUwAAAAZKb3dvb2RTAAACGSwgYW4gQXVzdHJpYW4gcHVi bGlzaGVyLgoKV2h5IHdhcyB0aGF0IGJhZD8gQmFjayB0aGVuIEpvd29vZCBvbmNlIGFnYWluIGhh ZCBmaW5hbmNpYWwgcHJvYmxlbXMgYW5kIHRoZXkgdHJpZWQgdG8gc29sdmUgaXQgYnkgY29udmlu Y2luZyB0aGUgc2hhcmVkaG9sZGVycyB0aGF0IHRoZWlyIG5leHQgZ2FtZSB3aWxsIGJlIGEgbWFq b3Igc3VjY2Vzcy4gVGhleSBzZXQgYW4gdG90YWxseSB1bmFjaGlldmFibGUgcmVsZWFzZSBkYXRl IGFuZCB0aGUgZGV2ZWxvcGVyIHRlYW0gYXQgd2luZ3MgaGFkIHRvIGxpdmUgd2l0aCB0aGF0LiBJ dCB3ZW50IHRoYXQgZmFyIHRoYXQgdGhleSBoYWQgdG8gZGVzaWduIHRoZSBib3ggYXJlIHRoZW1z ZWx2ZXMgZXZlbiB0aG91Z2ggdGhlIGdhbWUgd2FzIHN0aWxsIGJ1Z2d5LiBUaGUgZ2FtZSB3YXMg cmVsZWFzZWQgYW5kIHdhcyBzdGlsbCBidWdneS4gSSB0aGluayBHYW1lU3RhciBldmVuIG9taXR0 ZWQgdGhlIHJhdGluZyBiZWNhdXNlIHRoZXkgd2FudGVkIHRvIHdhaXQgZm9yIHRoZSBmaXJzdCBw YXRjaC4KCkVTAAAAA2ltZ0wAAE0AA1MAAAADc3JjUwAAACdodHRwOi8vcG9jb28ub3JnL35taXRz dWhpa28vc3N3XzAyLmpwZWdTAAAAA2FsdFMAAAAVQSBTw7ZsZG5lciBTY3JlZW5zaG90UwAAAAVj bGFzc1MAAAAJdGh1bWJsZWZ0UwAAAABTAAAFS0hvd2V2ZXIgdGhlIGdhbWUgc29sZCBwcmV0dHkg d2VsbCB0aGUgZmlyc3QgdHdvIHdlZWtzIGRlc3BpdGUgdGhlIGJhZCBxdWFsaXR5IG9mIHRoZSBy ZWxlYXNlIHZlcnNpb24gYW5kIHRoZSBiYWQgcmV2aWV3cy4gSXQgZXZlbiBvdXRzb2xkIHRoZSBn cmVhdGVzdCBjb21wZXRpdG9yIGF0IHRoYXQgdGltZSAoSm9pbnQgT3BlcmF0aW9ucykuIEkgd2Fz IG9uZSBvZiB0aGUgZWFybHkgYWRvcHRlcnMgYW5kIEkgbG92ZWQgdG8gcGxheSBpdC4gT3duaW5n IGEgYmFkIElTRE4gY29ubmVjdGlvbiBhdCB0aGF0IHRpbWUgaXQgd2FzIHRlcnJpYmxlIGxhZ2dp bmcsIGVzcGVjaWFsbHkgYmVjYXVzZSB0aGVpciBuZXRjb2RlIHdhcyBhIGNhdGFzdHJvcGhlLiBT dGlsbCwgaXQgd2FzIGdyZWF0IGZ1biBhbmQgdGhlIGRlc3RydWN0aWJsZSBlbnZpcm9ubWVudCB3 YXMgZ3JlYXQuIE5vdCBvbmx5IHRoYXQsIHRoZSBnYW1lIHdhcyBzb21ld2hhdCByZXZvbHV0aW9u YXJ5LiBJdCB3YXMgdGhlIGZpcnN0IG9ubGluZSBnYW1lIEkgcGxheWVkIHdpdGggYW4gKGFsYmVp dCBiYWQgY29uZmlndXJlZCkgcGh5c2ljcyBlbmdpbmUsIGl0IHVzZWQgcHl0aG9uIGFzIHNjcmlw dGluZyBsYW5ndWFnZSwgaXQgaGFkIG9uZSBiaWcgbWFwIHRoYXQgd2FzIGdlbmVyYXRlZCBmcm9t IHNhdGVsbGl0ZSBpbWFnZXMgd2l0aCBkZXRhaWxlZCBhcmVhcyB3aGVyZSB0aGUgZmlnaHRzIHRv b2sgcGxhY2UuIFlvdSBjb3VsZCBidXkgeW91cnNlbGYgYSBqZXQgYW5kIGxlYXZlIHRoZSBtYXAg YW5kIHZpc2l0IGFsbCBvZmYgU2liZXJpYS4gTm90IGxpa2UgQmF0dGxlZmllbGQgVmlldG5hbSB3 aGVyZSB5b3UgaGl0IHRoZSBib3JkZXJzIG9mIHRoZSBtYXAgd2l0aCBhIGpldCBhZnRlciByb3Vn aGx5IDE1IHNlY29uZHMuIERhbW1pdCwgaXQgd291bGQgc3RpbGwgYmUgZnVuIGFuZCBJIGJldCBp dCB3b3VsZCBoYXZlIGJlZW4gYnVnLWxlc3MgYnkgbm93LgoKVGhlIGNvbW11bml0eSB0aGF0IGFw cGVhcmVkIGFyb3VuZCB0aGF0IGdhbWUgd2FzIGluY3JlZGlibGUuIEEgd2lraSBhcHBlYXJlZCwg cGVvcGxlIHRyaWVkIHRvIGhhY2sgYXJvdW5kIG9uIHRoZSBjb2RlIHRvIGdldCBleHRyYSBmZWF0 dXJlcyBpbnRvIHRoZSBnYW1lLCB1bm9mZmljaWFsIG1vZHMgYXBwZWFyZWQuIFRoZXJlIHdhcyBl dmVuIGEgcHJvamVjdCB0aGF0IHdhbnRlZCB0byBjcmVhdGUgYSBtb2QgZm9yIGEgbWVkaWV2YWwg c2V0dGluZy4gSGVsbCwgaXQgd2FzIGdyZWF0IGJhY2sgdGhlbi4gQnV0IGluc3RlYWQgb2YgZml4 aW5nIHRoZSBidWdzIEpvd29vZCBmb3JjZWQgdGhlIGRldmVsb3BlcnMgdG8gc3RhcnQgYW4gYWRk b24gcHJvamVjdC4uLgoKRVMAAAADaW1nTAAATQADUwAAAANzcmNTAAAAJ2h0dHA6Ly9wb2Nvby5v cmcvfm1pdHN1aGlrby9zc3dfMDMuanBlZ1MAAAADYWx0UwAAABVBIFPDtmxkbmVyIFNjcmVlbnNo b3RTAAAABWNsYXNzUwAAAAp0aHVtYnJpZ2h0UwAAAABTAAAFilNob3J0bHkgYWZ0ZXIgdGhlIGFk ZG9uIHdhcyBmaW5pc2hlZCB0aGUgY29tcGFueSBkZXZlbG9waW5nIHRoYXQgZ2FtZSB3YXMgbGlx dWlkYXRlZC4gVGhlIGRldmVsb3BlcnMgbG9zdCB0aGVpciBqb2IgYW5kIHRoZSBjb21tdW5pdHkg Y29udGludWVkIGRldmVsb3BpbmcgdGhlIGNsb3NlZCBjb2RlLiBUaGUgZ3JvdXAgYXJvdW5kICJw cm9qZWN0IHplcm8iIGNvbnRpbnVlZCBtYWludGFpbmluZyB0aGUgZ2FtZSB1bnRpbCB0aGF0IGdy b3VwIGJyb2tlIGFwYXJ0IGFuZCB0aGUgZ0Vhc3kgdGVhbSB0b29rIG92ZXIgdGhlIHdvcmsuIFRo ZSBnRWFzeSB0ZWFtIHdhcyBiYXNpY2FsbHkganVzdCB0aGUgcHJvamVjdCB6ZXJvIHRlYW0gd2l0 aG91dCB0aGUgZm91bmRlci4gVGhleSBkaWQgYW4gdHJlbWVuZG91cyBqb2IgYnV0IEpvd29vZCBv bmNlIGFnYWluIGRlc3Ryb3llZCBldmVyeXRoaW5nLiBUaGV5IHJlZnVzZWQgdG8gcGF5IHRoZWly IGJpbGxzLCB0aGVuIHRoZSBnRWFzeSB0ZWFtIHRvb2sgZG93biB0aGUgbWFzdGVyIHNlcnZlciBh bmQgSXZhbiBFcnRsb3YgYXBwZWFyZWQgb24gdGhlIHNjZW5lLiBIZSBtYW5hZ2VkIHRvIHJlc29s dmUgdGhlIHByb2JsZW1zIGJldHdlZW4gSm93b29kIGFuZCBnRWFzeSB0ZWFtIHRvIHNvbWUgZXh0 ZW5kIHRoYXQgdGhlIG1hc3RlciBzZXJ2ZXIgd2FzIHVwIGFuZCBydW5uaW5nIGFnYWluLgoKV2hv J3MgdGhhdCBJdmFuIEVydGxvdj8gVmVyeSBnb29kIHF1ZXN0aW9uIGluZGVlZCBhbmQgSSBwZXJz b25hbGx5IGRvbid0IGtub3cgdGhlIGZ1bGwgc3RvcnkgYnV0IGZyb20gd2hhdCBJJ3ZlIHJlYWQg b24gdGhlIGZvcnVtcyBoZSBpcyBjYWxsZWQgSm9oYW5uIEVydGwgYW5kIG93bnMgYSBjb21wYW55 IHRoYXQgc2VsbHMgZ3VlcnJpbGxhIG1hcmtldGluZyBhbmQgc2ltaWxhciBzZXJ2aWNlcy4gQW5k IGhlIHdvcmtlZCBmb3IgSm93b29kIGFuZCBhcHBhcmVudGx5IHN0aWxsIGRvZXMsIGF0IGxlYXN0 IGhlIGlzIGxpc3RlZCBhcyBjb21tdW5pdHkgbWFuYWdlciBpbiB0aGUgb2ZmaWNpYWwgZm9ydW1z LiBIZSBhbHNvIGJyb3VnaHQgdXAgdGhlIHRvcGljICJPcGVuIFNvdXJjaW5nIiB0aGUgY29kZSBh ZnRlciBpdCB3YXMgY2xlYXIgdGhhdCB0aGVyZSB3aWxsIGJlIG5vIFPDtmxkbmVyIDIuIEEgc2Vx dWVsIHdhcyBhY3R1YWxseSB1bmRlciBjb25zaWRlcmF0aW9uIGFuZCBnRWFzeSBzdGFydGVkIHdv cmtpbmcgb24gdGhhdCB0aWxsIHRoZSBkYXkgdGhleSB0b29rIGRvd24gdGhlIG1hc3RlciBzZXJ2 ZXIgYmVjYXVzZSB0aGVyZSB3YXMgbm8gcGF5bWVudCBieSBKb3dvb2QuIEJ1dCBzaW5jZSBzb21l IHRpbWUgdGhlcmUgd2FzIG5vIGZlZWRiYWNrIGFueSBtb3JlIGFuZCBhbiBvcGVuIHNvdXJjZSB2 ZXJzaW9uIGlzIHNvbWV3aGF0IHVubGlrZWx5LgoKRVMAAAADaW1nTAAATQADUwAAAANzcmNTAAAA J2h0dHA6Ly9wb2Nvby5vcmcvfm1pdHN1aGlrby9zc3dfMDQuanBlZ1MAAAADYWx0UwAAABVBIFPD tmxkbmVyIFNjcmVlbnNob3RTAAAABWNsYXNzUwAAAAl0aHVtYmxlZnRTAAAAAFMAAARqRnJhbmts eSBJIGRvbid0IGtub3cgaWYgSm93b29kIHBheWVkIG9yIGRpZG4ndC4gV2hhdCBKb3dvb2QgZGlk IHdhcyBkZXN0cm95aW5nIHRoZSBnYW1lIGJ5IGZvcmNpbmcgYW4gZWFybHkgcmVsZWFzZSwgZm9y Y2luZyBhbiBhZGRvbiB3aGVuIHRoZSBjb2RlIHdhcyBzdGlsbCB1bmZpbmlzaGVkLCBmaXJlZCB0 aGUgZGV2ZWxvcGVycy4gRXZlbiB3b3JzZTogdGhleSBhcmUgdGVsbGluZyB0aGVpciBzaGFyZWhv bGRlcnMgdGhhdCBldmVyeXRoaW5nIGlzIHdvcmtpbmcgcGVyZmVjdGx5IGFuZCB0aGF0IHRoZXkg YXJlIHJlbGVhc2luZyBkb3plbnMgb2YgbmV3IGdhbWVzLiBIZWxsLCB0aGV5IHJlbGVhc2VkIFNw ZWxsZm9yY2UgMSBhbmQgMiB3aGljaCBib3RoIGFyZSBhd2Vzb21lIGdhbWVzIChqdXN0IGhhcHBl biB0byBoYXZlIHRoZSB3b3JzdCBjb3B5IHByb3RlY3Rpb24gZXZlciBkZXNpZ25lZCksIHRoZSBH b3RoaWMgZ2FtZXMgKHRoZSAzcmQgcGFydCB3YXMgYnVnZ3kgbGlrZSBTw7ZsZG5lciBidXQgcHJv YmFibHkgYWxzbyBiZWNhdXNlIEpvd29vZCBmb3JjZWQgYW4gZWFybHkgcmVsZWFzZSkuIEpvd29v ZCBob3dldmVyIGNsYWltcyB0aGF0IHRoZXkgcGF5ZWQgYW5kIHRoYXQgZ0Vhc3kgd2FzIGx5aW5n LiBXaG8gaXMgcnVubmluZyB0aGUgcG9ydGFsIG5vdz8gQXBwYXJlbnRseSBJdmFuJ3MgY29tcGFu eS4KClNvIHdoeSBhbSBJIGJsb2dnaW5nIGFib3V0IGFsbCB0aGF0PyBNYWlubHkgYmVjYXVzZSBJ IHRoaW5rIHRoYXQgdG9waWMgaGFzbid0IGdhaW5lZCBhIGxvdCBvZiBhdHRyYWN0aW9uLiBJIHN0 b3BwZWQgcGxheWluZyB0aGF0IGdhbWUgYWZ0ZXIgV2luZ3Mgd2FzIGxpcXVpZGF0ZWQuIEZvciBv bmUgYmVjYXVzZSBJIHN3aXRjaGVkIHRvIHVidW50dSBhbmQgb24gdGhlIG90aGVyIGhhbmQgYmVj YXVzZSBteSBTw7ZsZG5lciBwbHVnaW4gKGFuIGluLWdhbWUgV2luYW1wIGNvbnRyb2xsZXIpIGRp c2FwcGVhcmVkIHdoZW4gdGhlIGZvcnVtIHdhcyB1cGRhdGVkIHRvIHJlZmxlY3QgdGhlIG5ldyBv d25lcnNoaXAuIEFsbCB0aGUgb2xkIHRvcGljcyB3aGVyZSBlaXRoZXIgZGVsZXRlZCBvciBtYWRl IHVucmVhZGFibGUgd2hlbiBXaW5ncyB3YXMgY2xvc2VkIGRvd24uCgpFUwAAAANpbWdMAABNAANT AAAAA3NyY1MAAAAnaHR0cDovL3BvY29vLm9yZy9+bWl0c3VoaWtvL3Nzd18wNS5qcGVnUwAAAANh bHRTAAAAFUEgU8O2bGRuZXIgU2NyZWVuc2hvdFMAAAAFY2xhc3NTAAAACnRodW1icmlnaHRTAAAA AFMAAAc1V2hhdCBub2JvZHkgcmVhbGx5IG5vdGljZXMgaXMgdGhhdCB0aGUgZ2FtZSBoYWQgYSB0 cmVtZW5kb3VzIEdlcm1hbiBjb21tdW5pdHkuIEhlbGwsIHNvbWUgb2YgdGhlbSBldmVuIHRvb2sg b3ZlciB0aGUgZGV2ZWxvcG1lbnQhIElmIEpvd29vZCB3b3VsZCBoYXZlIG5vdGljZWQgdGhhdCBl YXJsaWVyIHRoZXkgY291bGQgaGF2ZSBtYWRlIHRoYXQgZ2FtZSB0aGUgZnJlYWtpbmcgYmVzdCBv bmxpbmUgc2hvb3RlciBhdmFpbGFibGUgYXQgdGhhdCB0aW1lLiBCdXQgYmVjYXVzZSBvZiB0aGVp ciBzbWFsbCBob3Jpem9uIHRoZXkganVzdCB0aG91Z2h0IGFib3V0IHRoZWlyIG5leHQgcXVhcnRl ciBhbmQgZGVjaWRlZCB0byBkbyB3aGF0IHNoYXJlaG9sZGVycyB3YW50LCBub3Qgd2hhdCBwbGF5 ZXJzIHdhbnQuIEJ1dCBub3Qgb25seSBKb3dvb2QgaXMgdG8gYmxhbWUgYnV0IHRoZSByb290IG9m IGFsbCBldmlsIGluIHRoYXQgY2FzZS4KCktyYXdhbGwgc3VwcG9ydGVkIEpvd29vZCBpbiB0aGUg YmVnaW5uaW5nIHRvIGhvc3QgdGhlaXIgaW5pdGlhbCBpbmZyYXN0cnVjdHVyZSBuZWVkZWQgZm9y IHRoZSBnYW1lLiBVbmZvcnR1bmF0ZWx5IHRoZSBzZXJ2ZXIgc29mdHdhcmUgbmVlZGVkIERpcmVj dCBYIHRvIHJ1biBwcm9wZXJseSB3aGljaCBjYXVzZWQgYSBsb3Qgb2YgdHJvdWJsZS4gT25lIHRo ZSBvbmUgaGFuZCBpdCB3YXMgaGFyZCB0byBnZXQgbXVsdGlwbGUgc2VydmVycyBydW5uaW5nIG9u IG9uZSBtYWNoaW5lIGRvIHRvIHRoZSB3YXkgdGhlIHNlcnZlciB3YXMgZGVzaWduZWQsIG9uIHRo ZSBvdGhlciBoYW5kIHlvdSBuZWVkZWQgYSB3aW5kb3dzIHNlcnZlciB0byBob3N0IGdhbWVzLiBB bmQgYmVjYXVzZSB0aGUgaW5pdGlhbCBjb2RlIGJhc2Ugd2FzIHRoYXQgYnVnZ3kgYWxsIHRoZSBt YWdhemluZXMgZmxhbWVkIHRvIGdhbWUuIERlc3BpdGUgdGhlIGdvb2Qgc2FsZXMgZmlndXJlcyBp dCBtYWdhemluZXMgbmV2ZXIgd3JvdGUgYWJvdXQgdGhlIGdhbWUgYW5kIGZvcmNlZCBhbiBlYXJs eSBkZWFkIHdoaWNoIGhhcm1lZCB0aGUgY29tbXVuaXR5LiBBIHJlbGVhc2Ugc2l4IG1vbnRoIGxh dGVyLCBhIGxpbnV4IHNlcnZlciBmcm9tIHRoZSBiZWdpbm5pbmcsIG5vIGFkZG9uIGFuZCBnb29k IHByZXNzIGNvdmVyYWdlIHdvdWxkIGhhdmUgYXZvaWRlZCBhbGwgdGhlIHByb2JsZW1zIHRoaXMg Z2FtZSB3YXMgZmFjaW5nIGluIHRoZSBwYXN0LiBBbmQgaXQgd291bGQgaGF2ZSBzYXZlZCBXaW5n cywgdGhlIGdhbWUgdGhleSB3ZXJlIHdvcmtpbmcgb24gYmVzaWRlIFPDtmxkbmVyLCBhbmQgaW4g dGhlIGVuZCBvZiBjb3Vyc2UgSm93b29kIHdoaWNoIHdvdWxkIGhhdmUgaGFkIGEgbG90IGxlc3Mg YmFkIHByZXNzLgoKRXNwZWNpYWxseSB0aGUgZ2FtZXJzIGhhdGUgSm93b29kIGZvciB0aGVpciBi dWdneSBwcm9kdWN0cyBub3cgYW5kIEkgZG91YnQgdGhhdCB0aGV5IHdpbGwgYmUgYWJsZSB0byBj b250aW51ZSB0byBpZ25vcmUgYWxsIHRoZSB1c2VyIGZlZWRiYWNrIGFuZCBwdXNoIGFscGhhIHZl cnNpb25zIGFzIHJlbGVhc2UgdmVyc2lvbnMgZm9yIG11Y2ggbG9uZ2VyLgoKSSdtIGVzcGVjaWFs bHkgaW50ZXJlc3RlZCB3aGF0IHRoZSBXaW5ncyBndXlzIGFyZSBkb2luZyBub3cuIEkga25vdyB0 aGF0IGZvcm1lciBXaW5ncyBjb21tdW5pdHkgbWFuYWdlciBhbmQgc291bmQgZGVzaWduZWQgTWFy YyBPbGJlcnR6IGlzIHdvcmtpbmcgYXQgQmxpenphcmQgYnV0IHRoYXQncyBhYm91dCBpdC4gSXQn cyBzYWQgd2hhdCBoYXBwZW5lZCB0aGVyZSBhbmQgdGhhdCBBdXN0cmlhbidzIG9ubHkgZ2FtZSBw dWJsaXNoZXIgY2F1c2VkIGFsbCB0aGF0LgoKRVMAAAAFc21hbGxMAAFFUwAAAAZzdHJvbmdMAABN AABTAAAAC0Z1bmt5IGZhY3Q6UwAAAMcgVGhlIGNvbW11bmljYXRpb24gd2l0aCB0aGUgbWFzdGVy IHNlcnZlciB3b3JrZWQgdmlhIGphYmJlciwgdGhlIHBoeXNpY3MgZW5naW5lIHdhcyBPREUgYW5k IHRoZSBzY3JpcHRpbmcgbGFuZ3VhZ2Ugd2FzIFB5dGhvbi4gQWxsIG9wZW4gc291cmNlIHRlY2hu b2xvZ2llcyBJIG5ldmVyIHNhdyBpbiBhIGNvbW1lcmNpYWwgZ2FtZSBiZWZvcmUgOi0pTQAAUwAA AABTAAAAAgoKRVMAAAAFc21hbGxMAAJFUwAAAAZzdHJvbmdMAABNAABTAAAAC0Rpc2NsYWltZXI6 UwAAAP8gdGhlIGluZm9ybWF0aW9uIG9uIHRoaXMgcGFnZSBzaG91bGQgYmUgYWNjdXJhdGUgYnV0 IGl0J3MgaGFyZCB0byBzYXkgZm9yIHN1cmUgYmVjYXVzZSB0aGVyZSBpcyBmZXcgaW5mb3JtYXRp b24gYWJvdXQgdGhpcyB0b3BpYyBhY3R1YWxseSBhdmFpbGFibGUuIElmIHlvdSBhcmUgYWJsZSB0 byB1bmRlcnN0YW5kIEdlcm1hbiB5b3UgY2FuIGZpbmQgc29tZSBpbmZvcm1hdGlvbiBpbiB0aGlz IHRocmVhZCBvbiB0aGUgU8O2bGRuZXIgZm9ydW1zOiBFUwAAAAFhTAAATQABUwAAAARocmVmUwAA ADZodHRwOi8vd3d3LnNlY3JldHdhcnMubmV0L2ZvcnVtL3Nob3d0aHJlYWQucGhwP3Q9NDE1OTFT AAAALVPDtmxkbmVyIGVpbiBBYmVudGV1ZXIgbWl0IHVuZ2V3aXNzZW0gQXVzZ2FuZ1MAAAAATQAA UwAAAABTAAAAAFMAAAAGcGFyc2VyUwAAAARodG1sUwAAAAVpbnRyb1JTAAAAAEwAAA== Schranzkoppschranzkopp@gmx.nethttp://www.ssw-channel.de.vu2008-02-10T00:35:19Znono0Well written! And all true... I can tell you that Udett Schaffrath, Producer of söldner now works in Hamburg as the Communitymanager of Computerbild online. I'll ask him what happened to the other guys from Wings.Well written! And all true... I can tell you that Udett Schaffrath, Producer of söldner now works in Hamburg as the Communitymanager of Computerbild online. I'll ask him what happened to the other guys from Wings.SQAAAAJTAAAABGJvZHlSUwAAANhXZWxsIHdyaXR0ZW4hCgpBbmQgYWxsIHRydWUuLi4KSSBjYW4g dGVsbCB5b3UgdGhhdCBVZGV0dCBTY2hhZmZyYXRoLCBQcm9kdWNlciBvZiBzw7ZsZG5lciBub3cg d29ya3MgaW4gSGFtYnVyZyBhcyB0aGUgQ29tbXVuaXR5bWFuYWdlciBvZiBDb21wdXRlcmJpbGQg b25saW5lLgoKSSdsbCBhc2sgaGltIHdoYXQgaGFwcGVuZWQgdG8gdGhlIG90aGVyIGd1eXMgZnJv bSBXaW5ncy5MAABTAAAABnBhcnNlclMAAAAEaHRtbA== ryancrryan@rrdesign.cahttp://blog.rrdesign.ca2008-02-10T05:30:05Znono0I remember when I first saw some videos of this game and thought it looked great. I followed it for sometime waiting for the demo release and sure enough it was buggy. Then came all the bad reviews, and then it seemed to fade away. To bad it didn't turn into the came it could have been.I remember when I first saw some videos of this game and thought it looked great. I followed it for sometime waiting for the demo release and sure enough it was buggy. Then came all the bad reviews, and then it seemed to fade away. To bad it didn't turn into the came it could have been.SQAAAAJTAAAABGJvZHlSUwAAAR9JIHJlbWVtYmVyIHdoZW4gSSBmaXJzdCBzYXcgc29tZSB2aWRl b3Mgb2YgdGhpcyBnYW1lIGFuZCB0aG91Z2h0IGl0IGxvb2tlZCBncmVhdC4gSSBmb2xsb3dlZCBp dCBmb3Igc29tZXRpbWUgd2FpdGluZyBmb3IgdGhlIGRlbW8gcmVsZWFzZSBhbmQgc3VyZSBlbm91 Z2ggaXQgd2FzIGJ1Z2d5LiBUaGVuIGNhbWUgYWxsIHRoZSBiYWQgcmV2aWV3cywgYW5kIHRoZW4g aXQgc2VlbWVkIHRvIGZhZGUgYXdheS4gVG8gYmFkIGl0IGRpZG4ndCB0dXJuIGludG8gdGhlIGNh bWUgaXQgY291bGQgaGF2ZSBiZWVuLkwAAFMAAAAGcGFyc2VyUwAAAARodG1s mimimimi.vx@gmail.com2008-02-10T11:23:52Znono0ODE was in Bloodrayene 2 , Python in Civ4 and Eve Online :)ODE was in Bloodrayene 2 , Python in Civ4 and Eve Online :)SQAAAAJTAAAABGJvZHlSUwAAADtPREUgd2FzIGluIEJsb29kcmF5ZW5lIDIgLCBQeXRob24gaW4g Q2l2NCBhbmQgRXZlIE9ubGluZSA6KUwAAFMAAAAGcGFyc2VyUwAAAARodG1s Armin Ronacherarmin.ronacher@active-4.comhttp://lucumr.pocoo.org/2008-02-10T13:40:03Znono0BloodRayne 2 was released a year after Söldner, same for Civ4. EVE indeed was released a year earlier. But back then I didn't know about that one ^^BloodRayne 2 was released a year after Söldner, same for Civ4. EVE indeed was released a year earlier. But back then I didn't know about that one ^^SQAAAAJTAAAABGJvZHlSUwAAAJVCbG9vZFJheW5lIDIgd2FzIHJlbGVhc2VkIGEgeWVhciBhZnRl ciBTw7ZsZG5lciwgc2FtZSBmb3IgQ2l2NC4gRVZFIGluZGVlZCB3YXMgcmVsZWFzZWQgYSB5ZWFy IGVhcmxpZXIuIEJ1dCBiYWNrIHRoZW4gSSBkaWRuJ3Qga25vdyBhYm91dCB0aGF0IG9uZSBeXkwA AFMAAAAGcGFyc2VyUwAAAARodG1s Vadim P.vperetokin@gmail.com2008-02-10T15:03:29Znono0Ouch. Well, that's one publishing company to stay away from.. (and damnit, why does steam have to be windows-only?)Ouch. Well, that's one publishing company to stay away from.. (and damnit, why does steam have to be windows-only?)SQAAAAJTAAAABGJvZHlSUwAAAHRPdWNoLiBXZWxsLCB0aGF0J3Mgb25lIHB1Ymxpc2hpbmcgY29t cGFueSB0byBzdGF5IGF3YXkgZnJvbS4uCgooYW5kIGRhbW5pdCwgd2h5IGRvZXMgc3RlYW0gaGF2 ZSB0byBiZSB3aW5kb3dzLW9ubHk/KUwAAFMAAAAGcGFyc2VyUwAAAARodG1s allirogallirog@gmx.net2008-02-10T18:06:54Znono0Make this puuuuuuuuublic ;) and somebody translate the german forum post into english :)Make this puuuuuuuuublic ;) and somebody translate the german forum post into english :)SQAAAAJTAAAABGJvZHlSUwAAAFhNYWtlIHRoaXMgcHV1dXV1dXV1dWJsaWMgOykgYW5kIHNvbWVi b2R5IHRyYW5zbGF0ZSB0aGUgZ2VybWFuIGZvcnVtIHBvc3QgaW50byBlbmdsaXNoIDopTAAAUwAA AAZwYXJzZXJTAAAABGh0bWw= Useruser@example.com2008-02-10T20:37:30Znono0Nice post. I remember reading some previews of the game. It was exciting, even though my PC couldn't handle it. It's a shame that something with so much potential got messed up like that, but it happens all the time, it seems. Be sure to post again if you ever hear about the community getting restarted. Sounds and looks like a lot of fun.Nice post. I remember reading some previews of the game. It was exciting, even though my PC couldn't handle it. It's a shame that something with so much potential got messed up like that, but it happens all the time, it seems. Be sure to post again if you ever hear about the community getting restarted. Sounds and looks like a lot of fun.SQAAAAJTAAAABGJvZHlSUwAAAVlOaWNlIHBvc3QuICBJIHJlbWVtYmVyIHJlYWRpbmcgc29tZSBw cmV2aWV3cyBvZiB0aGUgZ2FtZS4gIEl0IHdhcyBleGNpdGluZywgZXZlbiB0aG91Z2ggbXkgUEMg Y291bGRuJ3QgaGFuZGxlIGl0LiAgSXQncyBhIHNoYW1lIHRoYXQgc29tZXRoaW5nIHdpdGggc28g bXVjaCBwb3RlbnRpYWwgZ290IG1lc3NlZCB1cCBsaWtlIHRoYXQsIGJ1dCBpdCBoYXBwZW5zIGFs bCB0aGUgdGltZSwgaXQgc2VlbXMuICBCZSBzdXJlIHRvIHBvc3QgYWdhaW4gaWYgeW91IGV2ZXIg aGVhciBhYm91dCB0aGUgY29tbXVuaXR5IGdldHRpbmcgcmVzdGFydGVkLiAgU291bmRzIGFuZCBs b29rcyBsaWtlIGEgbG90IG9mIGZ1bi5MAABTAAAABnBhcnNlclMAAAAEaHRtbA== prencherprencher@prencher.dk2008-02-12T02:03:58Znono0As I recall, BF2142 also uses python extensively (I believe BF2 does too). Lots of games do these days - even more use lua.As I recall, BF2142 also uses python extensively (I believe BF2 does too). Lots of games do these days - even more use lua.SQAAAAJTAAAABGJvZHlSUwAAAHtBcyBJIHJlY2FsbCwgQkYyMTQyIGFsc28gdXNlcyBweXRob24g ZXh0ZW5zaXZlbHkgKEkgYmVsaWV2ZSBCRjIgZG9lcyB0b28pLiBMb3RzIG9mIGdhbWVzIGRvIHRo ZXNlIGRheXMgLSBldmVuIG1vcmUgdXNlIGx1YS5MAABTAAAABnBhcnNlclMAAAAEaHRtbA== New Werkzeug Website / Docshttp://lucumr.pocoo.org/cogitations/2008/02/06/new-werkzeug-website-docs/2008-02-06T18:27:47Z2008-02-06T18:27:47ZArmin Ronachernew-werkzeug-website-docsyesyes2Disclaimer: Yes I know the colors are too bright. Everybody who saw that webpage told me that, so I will change that soon. Anyways. Because there is an upcoming 0.2 release I deployed the documentation for the 0.2 release already because most of the users are probably already working on the hg tip (at least that's what the situation looks like in #pocoo). <a href="http://werkzeug.pocoo.org/">The new website</a> and <a href="http://werkzeug.pocoo.org/documentation/">documentation</a>. Additionally if everything works well there will be a Werkzeug presentation on the <a href="http://www.linuxtage.at/">Grazer Linuxtage</a> April the 19th. The Werkzeug 0.2 release will be Feb 14th hopefully, until then I have to fight with Jabber, don't ask :-)Disclaimer: Yes I know the colors are too bright. Everybody who saw that webpage told me that, so I will change that soon. Anyways. Because there is an upcoming 0.2 release I deployed the documentation for the 0.2 release already because most of the users are probably already working on the hg tip (at least that's what the situation looks like in #pocoo). <a href="http://werkzeug.pocoo.org/">The new website</a> and <a href="http://werkzeug.pocoo.org/documentation/">documentation</a>. Additionally if everything works well there will be a Werkzeug presentation on the <a href="http://www.linuxtage.at/">Grazer Linuxtage</a> April the 19th. The Werkzeug 0.2 release will be Feb 14th hopefully, until then I have to fight with Jabber, don't ask :-)SQAAAANTAAAABGJvZHlSUwAAAWdEaXNjbGFpbWVyOiBZZXMgSSBrbm93IHRoZSBjb2xvcnMgYXJl IHRvbyBicmlnaHQuIEV2ZXJ5Ym9keSB3aG8gc2F3IHRoYXQgd2VicGFnZSB0b2xkIG1lIHRoYXQs IHNvIEkgd2lsbCBjaGFuZ2UgdGhhdCBzb29uLiBBbnl3YXlzLiBCZWNhdXNlIHRoZXJlIGlzIGFu IHVwY29taW5nIDAuMiByZWxlYXNlIEkgZGVwbG95ZWQgdGhlIGRvY3VtZW50YXRpb24gZm9yIHRo ZSAwLjIgcmVsZWFzZSBhbHJlYWR5IGJlY2F1c2UgbW9zdCBvZiB0aGUgdXNlcnMgYXJlIHByb2Jh Ymx5IGFscmVhZHkgd29ya2luZyBvbiB0aGUgaGcgdGlwIChhdCBsZWFzdCB0aGF0J3Mgd2hhdCB0 aGUgc2l0dWF0aW9uIGxvb2tzIGxpa2UgaW4gI3BvY29vKS4KCkwAA0VTAAAAAWFMAABNAAFTAAAA BGhyZWZTAAAAGmh0dHA6Ly93ZXJremV1Zy5wb2Nvby5vcmcvUwAAAA9UaGUgbmV3IHdlYnNpdGVT AAAABSBhbmQgRVMAAAABYUwAAE0AAVMAAAAEaHJlZlMAAAAoaHR0cDovL3dlcmt6ZXVnLnBvY29v Lm9yZy9kb2N1bWVudGF0aW9uL1MAAAANZG9jdW1lbnRhdGlvblMAAABWLgoKQWRkaXRpb25hbGx5 IGlmIGV2ZXJ5dGhpbmcgd29ya3Mgd2VsbCB0aGVyZSB3aWxsIGJlIGEgV2Vya3pldWcgcHJlc2Vu dGF0aW9uIG9uIHRoZSBFUwAAAAFhTAAATQABUwAAAARocmVmUwAAABhodHRwOi8vd3d3LmxpbnV4 dGFnZS5hdC9TAAAAEEdyYXplciBMaW51eHRhZ2VTAAAAeyBBcHJpbCB0aGUgMTl0aC4gVGhlIFdl cmt6ZXVnIDAuMiByZWxlYXNlIHdpbGwgYmUgRmViIDE0dGggaG9wZWZ1bGx5LCB1bnRpbCB0aGVu IEkgaGF2ZSB0byBmaWdodCB3aXRoIEphYmJlciwgZG9uJ3QgYXNrIDotKVMAAAAGcGFyc2VyUwAA AARodG1sUwAAAAVpbnRyb1JTAAAAAEwAAA== johnjohn.w@web.de2008-02-06T21:08:08Znono0Hey, the other one wasn't bad either. And the hammer isn't really the coolest photo I could imagine. Maybe go for a Tango like one? (or at least painted)Hey, the other one wasn't bad either. And the hammer isn't really the coolest photo I could imagine. Maybe go for a Tango like one? (or at least painted)SQAAAAJTAAAABGJvZHlSUwAAAJpIZXksIHRoZSBvdGhlciBvbmUgd2Fzbid0IGJhZCBlaXRoZXIu CgpBbmQgdGhlIGhhbW1lciBpc24ndCByZWFsbHkgdGhlIGNvb2xlc3QgcGhvdG8gSSBjb3VsZCBp bWFnaW5lLiBNYXliZSBnbyBmb3IgYSBUYW5nbyBsaWtlIG9uZT8gKG9yIGF0IGxlYXN0IHBhaW50 ZWQpTAAAUwAAAAZwYXJzZXJTAAAABGh0bWw= vicent rocasaptah@gmail.com2008-02-06T21:12:33Znono0hi, I prefer the last design :)hi, I prefer the last design :)SQAAAAJTAAAABGJvZHlSUwAAAB9oaSwKSSBwcmVmZXIgdGhlIGxhc3QgZGVzaWduIDopTAAAUwAA AAZwYXJzZXJTAAAABGh0bWw= Steveskryskalla@gmail.com2008-02-09T03:59:54Znono0I have to say I like the old design too :) This looks a lot like the TurboGears site (the blue header). That "look under the hood" link is really impressive though.I have to say I like the old design too :) This looks a lot like the TurboGears site (the blue header). That "look under the hood" link is really impressive though.SQAAAAJTAAAABGJvZHlSUwAAAKZJIGhhdmUgdG8gc2F5IEkgbGlrZSB0aGUgb2xkIGRlc2lnbiB0 b28gOikgIFRoaXMgbG9va3MgYSBsb3QgbGlrZSB0aGUgVHVyYm9HZWFycyBzaXRlICh0aGUgYmx1 ZSBoZWFkZXIpLgoKVGhhdCAibG9vayB1bmRlciB0aGUgaG9vZCIgbGluayBpcyByZWFsbHkgaW1w cmVzc2l2ZSB0aG91Z2guTAAAUwAAAAZwYXJzZXJTAAAABGh0bWw= Armin Ronacherarmin.ronacher@active-4.comhttp://lucumr.pocoo.org/2008-02-09T10:29:55Znono0Yes indeed, they look very similar. One more reason to make the header less flashy.Yes indeed, they look very similar. One more reason to make the header less flashy.SQAAAAJTAAAABGJvZHlSUwAAAFNZZXMgaW5kZWVkLCB0aGV5IGxvb2sgdmVyeSBzaW1pbGFyLiBP bmUgbW9yZSByZWFzb24gdG8gbWFrZSB0aGUgaGVhZGVyIGxlc3MgZmxhc2h5LkwAAFMAAAAGcGFy c2VyUwAAAARodG1s Until TextPress is ready…http://lucumr.pocoo.org/cogitations/2008/02/05/until-textpress-is-ready/2008-02-05T19:24:40Z2008-02-05T19:24:40ZArmin Ronacheruntil-textpress-is-readyyesyes2<pre>mitsuhiko@hammett:~$ cd lucumr/cogitations/ mitsuhiko@hammett:~/lucumr/cogitations$ rm xmlrpc.php mitsuhiko@hammett:~/lucumr/cogitations$ </pre><pre>mitsuhiko@hammett:~$ cd lucumr/cogitations/ mitsuhiko@hammett:~/lucumr/cogitations$ rm xmlrpc.php mitsuhiko@hammett:~/lucumr/cogitations$ </pre>SQAAAANTAAAABGJvZHlSUwAAAABMAAFFUwAAAANwcmVMAABNAABTAAAAi21pdHN1aGlrb0BoYW1t ZXR0On4kIGNkIGx1Y3Vtci9jb2dpdGF0aW9ucy8KbWl0c3VoaWtvQGhhbW1ldHQ6fi9sdWN1bXIv Y29naXRhdGlvbnMkIHJtIHhtbHJwYy5waHAgCm1pdHN1aGlrb0BoYW1tZXR0On4vbHVjdW1yL2Nv Z2l0YXRpb25zJCBTAAAAAFMAAAAGcGFyc2VyUwAAAARodG1sUwAAAAVpbnRyb1JTAAAAAEwAAA== BarCamp Senza Confini 2008, Day 1http://lucumr.pocoo.org/cogitations/2008/02/02/barcamp-senza-confini-2008-day-1/2008-02-02T20:32:54Z2008-02-02T20:32:54ZArmin Ronacherbarcamp-senza-confini-2008-day-1yesyes2And unfortunately also the only day for me because I can't be there tomorrow. Which is especially stupid because I'm very interested in the talk about broadband 2.0 by <a href="https://www.xing.com/profile/Alexander_List">Alexander List</a>. Well. It was my first barcamp so I presented a topic: mercurial. Good: There was at least one person in the audience that considers switching and I hope I whetted appetite to the others too, Bad: the talk was badly organized IMO, hope I will do better the next time. But now to the positive aspects of the day. I think the main reason why people go to barcamps are not the talks, but the possibility to meet people with similar interests and share experiences and knowledge. I meet a couple people there I didn't know before or only from IRC/Jabber/whatever and he have a couple of great discussions, especially about the currently problematic political situation here in Austria. And despite what I noticed in the past there are several groups operating here that try to fix the situation here. I'll hopefully blog a bit about it more soon :-)And unfortunately also the only day for me because I can't be there tomorrow. Which is especially stupid because I'm very interested in the talk about broadband 2.0 by <a href="https://www.xing.com/profile/Alexander_List">Alexander List</a>. Well. It was my first barcamp so I presented a topic: mercurial. Good: There was at least one person in the audience that considers switching and I hope I whetted appetite to the others too, Bad: the talk was badly organized IMO, hope I will do better the next time. But now to the positive aspects of the day. I think the main reason why people go to barcamps are not the talks, but the possibility to meet people with similar interests and share experiences and knowledge. I meet a couple people there I didn't know before or only from IRC/Jabber/whatever and he have a couple of great discussions, especially about the currently problematic political situation here in Austria. And despite what I noticed in the past there are several groups operating here that try to fix the situation here. I'll hopefully blog a bit about it more soon :-)SQAAAANTAAAABGJvZHlSUwAAAKhBbmQgdW5mb3J0dW5hdGVseSBhbHNvIHRoZSBvbmx5IGRheSBm b3IgbWUgYmVjYXVzZSBJIGNhbid0IGJlIHRoZXJlIHRvbW9ycm93LiBXaGljaCBpcyBlc3BlY2lh bGx5IHN0dXBpZCBiZWNhdXNlIEknbSB2ZXJ5IGludGVyZXN0ZWQgaW4gdGhlIHRhbGsgYWJvdXQg YnJvYWRiYW5kIDIuMCBieSBMAAFFUwAAAAFhTAAATQABUwAAAARocmVmUwAAACtodHRwczovL3d3 dy54aW5nLmNvbS9wcm9maWxlL0FsZXhhbmRlcl9MaXN0UwAAAA5BbGV4YW5kZXIgTGlzdFMAAANR LgoKV2VsbC4gSXQgd2FzIG15IGZpcnN0IGJhcmNhbXAgc28gSSBwcmVzZW50ZWQgYSB0b3BpYzog bWVyY3VyaWFsLiBHb29kOiBUaGVyZSB3YXMgYXQgbGVhc3Qgb25lIHBlcnNvbiBpbiB0aGUgYXVk aWVuY2UgdGhhdCBjb25zaWRlcnMgc3dpdGNoaW5nIGFuZCBJIGhvcGUgSSB3aGV0dGVkIGFwcGV0 aXRlIHRvIHRoZSBvdGhlcnMgdG9vLCBCYWQ6IHRoZSB0YWxrIHdhcyBiYWRseSBvcmdhbml6ZWQg SU1PLCBob3BlIEkgd2lsbCBkbyBiZXR0ZXIgdGhlIG5leHQgdGltZS4gQnV0IG5vdyB0byB0aGUg cG9zaXRpdmUgYXNwZWN0cyBvZiB0aGUgZGF5LgoKSSB0aGluayB0aGUgbWFpbiByZWFzb24gd2h5 IHBlb3BsZSBnbyB0byBiYXJjYW1wcyBhcmUgbm90IHRoZSB0YWxrcywgYnV0IHRoZSBwb3NzaWJp bGl0eSB0byBtZWV0IHBlb3BsZSB3aXRoIHNpbWlsYXIgaW50ZXJlc3RzIGFuZCBzaGFyZSBleHBl cmllbmNlcyBhbmQga25vd2xlZGdlLiBJIG1lZXQgYSBjb3VwbGUgcGVvcGxlIHRoZXJlIEkgZGlk bid0IGtub3cgYmVmb3JlIG9yIG9ubHkgZnJvbSBJUkMvSmFiYmVyL3doYXRldmVyIGFuZCBoZSBo YXZlIGEgY291cGxlIG9mIGdyZWF0IGRpc2N1c3Npb25zLCBlc3BlY2lhbGx5IGFib3V0IHRoZSBj dXJyZW50bHkgcHJvYmxlbWF0aWMgcG9saXRpY2FsIHNpdHVhdGlvbiBoZXJlIGluIEF1c3RyaWEu IEFuZCBkZXNwaXRlIHdoYXQgSSBub3RpY2VkIGluIHRoZSBwYXN0IHRoZXJlIGFyZSBzZXZlcmFs IGdyb3VwcyBvcGVyYXRpbmcgaGVyZSB0aGF0IHRyeSB0byBmaXggdGhlIHNpdHVhdGlvbiBoZXJl LgoKSSdsbCBob3BlZnVsbHkgYmxvZyBhIGJpdCBhYm91dCBpdCBtb3JlIHNvb24gOi0pUwAAAAZw YXJzZXJTAAAABGh0bWxTAAAABWludHJvUlMAAAAATAAA Manuzhaimail@manuzhai.nl2008-02-03T08:43:49Znono0It would be nice if you published your slides on the Mercurial wiki. There is a Presentations page just for this purpose.It would be nice if you published your slides on the Mercurial wiki. There is a Presentations page just for this purpose.SQAAAAJTAAAABGJvZHlSUwAAAHlJdCB3b3VsZCBiZSBuaWNlIGlmIHlvdSBwdWJsaXNoZWQgeW91 ciBzbGlkZXMgb24gdGhlIE1lcmN1cmlhbCB3aWtpLiBUaGVyZSBpcyBhIFByZXNlbnRhdGlvbnMg cGFnZSBqdXN0IGZvciB0aGlzIHB1cnBvc2UuTAAAUwAAAAZwYXJzZXJTAAAABGh0bWw= Mercurial for Subversion Usershttp://lucumr.pocoo.org/cogitations/2008/01/28/mercurial-for-subversion-users/2008-01-28T18:59:11Z2008-01-28T18:59:11ZArmin Ronachermercurial-for-subversion-usersyesyes2More and more projects are switching over to <a href="http://www.selenic.com/mercurial/">mercurial</a> or similar DVCS. Great as mercurial is, it's hard to get started if you are used to subversion because the concept behind Subversion (svn) and mercurial (hg) is fundamentally different. This article should help you understand how mercurial and similar systems work and how you can use it to contribute patches to the pocoo projects. If you compare Subversion to mercurial you won't find that many similarities beside the command arguments. Subversion works like FTP whereas mercurial is bittorrent. In Subversion the server is special: it keeps all the revision log and all the operations require a connection to this server. In mercurial I can take down the central repository if there is one an all developers will still be able to exchange changes. All the revision information is available to anyone and there is absolutely no difference between server and clients. This fundamental design decision means that there are dozens of separate branches of the code. hg makes it easy to merge and branch and it's developed exactly for that. In Subversion branching and merging is painful an often people just don't branch and don't commit there changes until the testsuite etc. passes again which of course results in huge changesets. But let's step right into it! The first thing in Subversion you do is either creating a repository on the server or checking it out on the client. In hg there is no difference between server and client so the process of creating a repository is available to everybody. Creating a repository is just as simple as typing "hg init name_of_the_repository". If that folder does not exist yet it will create an empty folder and initialize it as root of the repository, otherwise it will create the repository in the name of that folder. The process of checking out is a bit different from Subversion because it's effectively the same as creating a branch. Say you want to check out the current Pygments version to do some changes. The first thing you will do is looking for a way to access this repository. There are three very common ways to access it: filesystem, HTTP or SSH. Pygments is available as SSH and HTTP, but for non core developers only HTTP is available. Interestingly quite a few people have problems locating the checkout URL which is not very surprising because hgweb handles that. hgweb is the standard mercurial web interface which doesn't only provide a way to look at the changesets and tree but also handles patch exchange. In the case of Pygments this command should give you a fresh checkout in a few seconds into the new folder "pygments": <pre>hg clone http://dev.pocoo.org/hg/pygments-main pygments</pre> One thing you will notice is that it's incredible fast and even though the repository contains the whole history the checkout is pretty small. By the time I'm writing this blog post the pygments sourcecode including the unittests and example sourcecode without the revision history is 2.5MB. A complete mercurial checkout is only 5MB even though it includes 486 changesets. After you got your very own repository by cloning the pygments one you will notice that all the subversion-like commands ("hg ci", "hg add", "hg up", ...) work locally only. You check into your local version of the repository and hg up won't incorporate remote changes. One of the things that happen on hg clone is that mercurial will set the path to the repository you cloned from into the hgrc of the newly created repository. This file (".hg/hgrc") is used to store per-repository configuration like the path of remote repositories, the name used for checkins, plugins that are only enabled for this repository and more. Executing "hg pull" will automatically pull changes from this remote repository and put them into the current repository as second branch. To see what "hg pull" will pull from that remote repository you can execute "hg incoming" and it will print a list of changesets that are in the remote repository but not yet in the local one. After you have pulled you have to update the repository with "hg up" so that you can actually see the changes. If there were remote changes that require merging you have to "hg merge" them and "hg ci" the merge. Because this process is very common there are ways to simplify it. "hg pull && hg update" can be written as "hg pull -u". All the commands (pull, update, merge and checkin if required) can be handled in one go using "hg fe". This command however is part of a plugin which is disabled by default. If you want to use it you have to add the following lines into the repository hgrc or your personal one: <pre>[extensions] hgext.fetch=</pre> The other important difference to subversion is how you push your changes back to the server. In open source projects usually only a small number of developers has access to the main repository and contributors create patches using "diff" or "svn diff" and mail it to one of the persons with commit rights or attach it to a ticket in the project's tracker. If you are a person with push privileges you can do "hg push" and it will push the changesets which are not yet on the server (you can look at them using "hg outgoing"). If you don't have push access you can create a bundle of changes and attach that to a ticket rather than a patch. A bundle stores multiple changesets in one file and it also preserves the correct author information and timestamps. Another way is mailing the changes to a different developer using the patchbomb extension (I won't cover that here, just google it up). Or you can let other people pull from your repository. Therefore you either have to configure your apache to server a hgweb instance or you just call "hg serve" and it will spawn a server on localhost:8000 everybody can pull from. Once the developer has decided to put your changes into the central repository and pushed them, your changes will appear there unaltered and with the same revision hashes. What will be different is the local number the changeset is given. If the revision was called deadbeef:42 locally it could be called deadbeef:52 on the server because different changesets were applied first. All the commands that interact with remote repositories ("hg pull", "hg push", "hg fe", ...) also take a different path than the default path from the hgrc as argument. This allows you to pull changes from repositories shared over the web. A cool example what mercurial allows you to do is our last ubuntuusers webteam meetup. There we used my notebook to store the central repository and everybody pushed the changes every once in a while to it. Additionally some people exchanged patches to not yet working features among each other so that the code on the central repo was seldom broken. When I left everybody had all the changes locally because they pulled and I could remove my notebook and everybody continued working on their way home. When we met again on IRC I copied my repo on the server and everybody pushed their local changes to it.More and more projects are switching over to <a href="http://www.selenic.com/mercurial/">mercurial</a> or similar DVCS. Great as mercurial is, it's hard to get started if you are used to subversion because the concept behind Subversion (svn) and mercurial (hg) is fundamentally different. This article should help you understand how mercurial and similar systems work and how you can use it to contribute patches to the pocoo projects. If you compare Subversion to mercurial you won't find that many similarities beside the command arguments. Subversion works like FTP whereas mercurial is bittorrent. In Subversion the server is special: it keeps all the revision log and all the operations require a connection to this server. In mercurial I can take down the central repository if there is one an all developers will still be able to exchange changes. All the revision information is available to anyone and there is absolutely no difference between server and clients. This fundamental design decision means that there are dozens of separate branches of the code. hg makes it easy to merge and branch and it's developed exactly for that. In Subversion branching and merging is painful an often people just don't branch and don't commit there changes until the testsuite etc. passes again which of course results in huge changesets. But let's step right into it! The first thing in Subversion you do is either creating a repository on the server or checking it out on the client. In hg there is no difference between server and client so the process of creating a repository is available to everybody. Creating a repository is just as simple as typing "hg init name_of_the_repository". If that folder does not exist yet it will create an empty folder and initialize it as root of the repository, otherwise it will create the repository in the name of that folder. The process of checking out is a bit different from Subversion because it's effectively the same as creating a branch. Say you want to check out the current Pygments version to do some changes. The first thing you will do is looking for a way to access this repository. There are three very common ways to access it: filesystem, HTTP or SSH. Pygments is available as SSH and HTTP, but for non core developers only HTTP is available. Interestingly quite a few people have problems locating the checkout URL which is not very surprising because hgweb handles that. hgweb is the standard mercurial web interface which doesn't only provide a way to look at the changesets and tree but also handles patch exchange. In the case of Pygments this command should give you a fresh checkout in a few seconds into the new folder "pygments": <pre>hg clone http://dev.pocoo.org/hg/pygments-main pygments</pre> One thing you will notice is that it's incredible fast and even though the repository contains the whole history the checkout is pretty small. By the time I'm writing this blog post the pygments sourcecode including the unittests and example sourcecode without the revision history is 2.5MB. A complete mercurial checkout is only 5MB even though it includes 486 changesets. After you got your very own repository by cloning the pygments one you will notice that all the subversion-like commands ("hg ci", "hg add", "hg up", ...) work locally only. You check into your local version of the repository and hg up won't incorporate remote changes. One of the things that happen on hg clone is that mercurial will set the path to the repository you cloned from into the hgrc of the newly created repository. This file (".hg/hgrc") is used to store per-repository configuration like the path of remote repositories, the name used for checkins, plugins that are only enabled for this repository and more. Executing "hg pull" will automatically pull changes from this remote repository and put them into the current repository as second branch. To see what "hg pull" will pull from that remote repository you can execute "hg incoming" and it will print a list of changesets that are in the remote repository but not yet in the local one. After you have pulled you have to update the repository with "hg up" so that you can actually see the changes. If there were remote changes that require merging you have to "hg merge" them and "hg ci" the merge. Because this process is very common there are ways to simplify it. "hg pull &amp;&amp; hg update" can be written as "hg pull -u". All the commands (pull, update, merge and checkin if required) can be handled in one go using "hg fe". This command however is part of a plugin which is disabled by default. If you want to use it you have to add the following lines into the repository hgrc or your personal one: <pre>[extensions] hgext.fetch=</pre> The other important difference to subversion is how you push your changes back to the server. In open source projects usually only a small number of developers has access to the main repository and contributors create patches using "diff" or "svn diff" and mail it to one of the persons with commit rights or attach it to a ticket in the project's tracker. If you are a person with push privileges you can do "hg push" and it will push the changesets which are not yet on the server (you can look at them using "hg outgoing"). If you don't have push access you can create a bundle of changes and attach that to a ticket rather than a patch. A bundle stores multiple changesets in one file and it also preserves the correct author information and timestamps. Another way is mailing the changes to a different developer using the patchbomb extension (I won't cover that here, just google it up). Or you can let other people pull from your repository. Therefore you either have to configure your apache to server a hgweb instance or you just call "hg serve" and it will spawn a server on localhost:8000 everybody can pull from. Once the developer has decided to put your changes into the central repository and pushed them, your changes will appear there unaltered and with the same revision hashes. What will be different is the local number the changeset is given. If the revision was called deadbeef:42 locally it could be called deadbeef:52 on the server because different changesets were applied first. All the commands that interact with remote repositories ("hg pull", "hg push", "hg fe", ...) also take a different path than the default path from the hgrc as argument. This allows you to pull changes from repositories shared over the web. A cool example what mercurial allows you to do is our last ubuntuusers webteam meetup. There we used my notebook to store the central repository and everybody pushed the changes every once in a while to it. Additionally some people exchanged patches to not yet working features among each other so that the code on the central repo was seldom broken. When I left everybody had all the changes locally because they pulled and I could remove my notebook and everybody continued working on their way home. When we met again on IRC I copied my repo on the server and everybody pushed their local changes to it.SQAAAANTAAAABGJvZHlSUwAAAC1Nb3JlIGFuZCBtb3JlIHByb2plY3RzIGFyZSBzd2l0Y2hpbmcg b3ZlciB0byBMAANFUwAAAAFhTAAATQABUwAAAARocmVmUwAAACFodHRwOi8vd3d3LnNlbGVuaWMu Y29tL21lcmN1cmlhbC9TAAAACW1lcmN1cmlhbFMAAAonIG9yIHNpbWlsYXIgRFZDUy4gR3JlYXQg YXMgbWVyY3VyaWFsIGlzLCBpdCdzIGhhcmQgdG8gZ2V0IHN0YXJ0ZWQgaWYgeW91IGFyZSB1c2Vk IHRvIHN1YnZlcnNpb24gYmVjYXVzZSB0aGUgY29uY2VwdCBiZWhpbmQgU3VidmVyc2lvbiAoc3Zu KSBhbmQgbWVyY3VyaWFsIChoZykgaXMgZnVuZGFtZW50YWxseSBkaWZmZXJlbnQuIFRoaXMgYXJ0 aWNsZSBzaG91bGQgaGVscCB5b3UgdW5kZXJzdGFuZCBob3cgbWVyY3VyaWFsIGFuZCBzaW1pbGFy IHN5c3RlbXMgd29yayBhbmQgaG93IHlvdSBjYW4gdXNlIGl0IHRvIGNvbnRyaWJ1dGUgcGF0Y2hl cyB0byB0aGUgcG9jb28gcHJvamVjdHMuCgpJZiB5b3UgY29tcGFyZSBTdWJ2ZXJzaW9uIHRvIG1l cmN1cmlhbCB5b3Ugd29uJ3QgZmluZCB0aGF0IG1hbnkgc2ltaWxhcml0aWVzIGJlc2lkZSB0aGUg Y29tbWFuZCBhcmd1bWVudHMuIFN1YnZlcnNpb24gd29ya3MgbGlrZSBGVFAgd2hlcmVhcyBtZXJj dXJpYWwgaXMgYml0dG9ycmVudC4gSW4gU3VidmVyc2lvbiB0aGUgc2VydmVyIGlzIHNwZWNpYWw6 IGl0IGtlZXBzIGFsbCB0aGUgcmV2aXNpb24gbG9nIGFuZCBhbGwgdGhlIG9wZXJhdGlvbnMgcmVx dWlyZSBhIGNvbm5lY3Rpb24gdG8gdGhpcyBzZXJ2ZXIuIEluIG1lcmN1cmlhbCBJIGNhbiB0YWtl IGRvd24gdGhlIGNlbnRyYWwgcmVwb3NpdG9yeSBpZiB0aGVyZSBpcyBvbmUgYW4gYWxsIGRldmVs b3BlcnMgd2lsbCBzdGlsbCBiZSBhYmxlIHRvIGV4Y2hhbmdlIGNoYW5nZXMuIEFsbCB0aGUgcmV2 aXNpb24gaW5mb3JtYXRpb24gaXMgYXZhaWxhYmxlIHRvIGFueW9uZSBhbmQgdGhlcmUgaXMgYWJz b2x1dGVseSBubyBkaWZmZXJlbmNlIGJldHdlZW4gc2VydmVyIGFuZCBjbGllbnRzLgoKVGhpcyBm dW5kYW1lbnRhbCBkZXNpZ24gZGVjaXNpb24gbWVhbnMgdGhhdCB0aGVyZSBhcmUgZG96ZW5zIG9m IHNlcGFyYXRlIGJyYW5jaGVzIG9mIHRoZSBjb2RlLiBoZyBtYWtlcyBpdCBlYXN5IHRvIG1lcmdl IGFuZCBicmFuY2ggYW5kIGl0J3MgZGV2ZWxvcGVkIGV4YWN0bHkgZm9yIHRoYXQuIEluIFN1YnZl cnNpb24gYnJhbmNoaW5nIGFuZCBtZXJnaW5nIGlzIHBhaW5mdWwgYW4gb2Z0ZW4gcGVvcGxlIGp1 c3QgZG9uJ3QgYnJhbmNoIGFuZCBkb24ndCBjb21taXQgdGhlcmUgY2hhbmdlcyB1bnRpbCB0aGUg dGVzdHN1aXRlIGV0Yy4gcGFzc2VzIGFnYWluIHdoaWNoIG9mIGNvdXJzZSByZXN1bHRzIGluIGh1 Z2UgY2hhbmdlc2V0cy4gQnV0IGxldCdzIHN0ZXAgcmlnaHQgaW50byBpdCEKClRoZSBmaXJzdCB0 aGluZyBpbiBTdWJ2ZXJzaW9uIHlvdSBkbyBpcyBlaXRoZXIgY3JlYXRpbmcgYSByZXBvc2l0b3J5 IG9uIHRoZSBzZXJ2ZXIgb3IgY2hlY2tpbmcgaXQgb3V0IG9uIHRoZSBjbGllbnQuIEluIGhnIHRo ZXJlIGlzIG5vIGRpZmZlcmVuY2UgYmV0d2VlbiBzZXJ2ZXIgYW5kIGNsaWVudCBzbyB0aGUgcHJv Y2VzcyBvZiBjcmVhdGluZyBhIHJlcG9zaXRvcnkgaXMgYXZhaWxhYmxlIHRvIGV2ZXJ5Ym9keS4g Q3JlYXRpbmcgYSByZXBvc2l0b3J5IGlzIGp1c3QgYXMgc2ltcGxlIGFzIHR5cGluZyAiaGcgaW5p dCBuYW1lX29mX3RoZV9yZXBvc2l0b3J5Ii4gSWYgdGhhdCBmb2xkZXIgZG9lcyBub3QgZXhpc3Qg eWV0IGl0IHdpbGwgY3JlYXRlIGFuIGVtcHR5IGZvbGRlciBhbmQgaW5pdGlhbGl6ZSBpdCBhcyBy b290IG9mIHRoZSByZXBvc2l0b3J5LCBvdGhlcndpc2UgaXQgd2lsbCBjcmVhdGUgdGhlIHJlcG9z aXRvcnkgaW4gdGhlIG5hbWUgb2YgdGhhdCBmb2xkZXIuCgpUaGUgcHJvY2VzcyBvZiBjaGVja2lu ZyBvdXQgaXMgYSBiaXQgZGlmZmVyZW50IGZyb20gU3VidmVyc2lvbiBiZWNhdXNlIGl0J3MgZWZm ZWN0aXZlbHkgdGhlIHNhbWUgYXMgY3JlYXRpbmcgYSBicmFuY2guIFNheSB5b3Ugd2FudCB0byBj aGVjayBvdXQgdGhlIGN1cnJlbnQgUHlnbWVudHMgdmVyc2lvbiB0byBkbyBzb21lIGNoYW5nZXMu IFRoZSBmaXJzdCB0aGluZyB5b3Ugd2lsbCBkbyBpcyBsb29raW5nIGZvciBhIHdheSB0byBhY2Nl c3MgdGhpcyByZXBvc2l0b3J5LiBUaGVyZSBhcmUgdGhyZWUgdmVyeSBjb21tb24gd2F5cyB0byBh Y2Nlc3MgaXQ6IGZpbGVzeXN0ZW0sIEhUVFAgb3IgU1NILiBQeWdtZW50cyBpcyBhdmFpbGFibGUg YXMgU1NIIGFuZCBIVFRQLCBidXQgZm9yIG5vbiBjb3JlIGRldmVsb3BlcnMgb25seSBIVFRQIGlz IGF2YWlsYWJsZS4gSW50ZXJlc3RpbmdseSBxdWl0ZSBhIGZldyBwZW9wbGUgaGF2ZSBwcm9ibGVt cyBsb2NhdGluZyB0aGUgY2hlY2tvdXQgVVJMIHdoaWNoIGlzIG5vdCB2ZXJ5IHN1cnByaXNpbmcg YmVjYXVzZSBoZ3dlYiBoYW5kbGVzIHRoYXQuIGhnd2ViIGlzIHRoZSBzdGFuZGFyZCBtZXJjdXJp YWwgd2ViIGludGVyZmFjZSB3aGljaCBkb2Vzbid0IG9ubHkgcHJvdmlkZSBhIHdheSB0byBsb29r IGF0IHRoZSBjaGFuZ2VzZXRzIGFuZCB0cmVlIGJ1dCBhbHNvIGhhbmRsZXMgcGF0Y2ggZXhjaGFu Z2UuIEluIHRoZSBjYXNlIG9mIFB5Z21lbnRzIHRoaXMgY29tbWFuZCBzaG91bGQgZ2l2ZSB5b3Ug YSBmcmVzaCBjaGVja291dCBpbiBhIGZldyBzZWNvbmRzIGludG8gdGhlIG5ldyBmb2xkZXIgInB5 Z21lbnRzIjoKCkVTAAAAA3ByZUwAAE0AAFMAAAA3aGcgY2xvbmUgaHR0cDovL2Rldi5wb2Nvby5v cmcvaGcvcHlnbWVudHMtbWFpbiBweWdtZW50c1MAAAedCgpPbmUgdGhpbmcgeW91IHdpbGwgbm90 aWNlIGlzIHRoYXQgaXQncyBpbmNyZWRpYmxlIGZhc3QgYW5kIGV2ZW4gdGhvdWdoIHRoZSByZXBv c2l0b3J5IGNvbnRhaW5zIHRoZSB3aG9sZSBoaXN0b3J5IHRoZSBjaGVja291dCBpcyBwcmV0dHkg c21hbGwuIEJ5IHRoZSB0aW1lIEknbSB3cml0aW5nIHRoaXMgYmxvZyBwb3N0IHRoZSBweWdtZW50 cyBzb3VyY2Vjb2RlIGluY2x1ZGluZyB0aGUgdW5pdHRlc3RzIGFuZCBleGFtcGxlIHNvdXJjZWNv ZGUgd2l0aG91dCB0aGUgcmV2aXNpb24gaGlzdG9yeSBpcyAyLjVNQi4gQSBjb21wbGV0ZSBtZXJj dXJpYWwgY2hlY2tvdXQgaXMgb25seSA1TUIgZXZlbiB0aG91Z2ggaXQgaW5jbHVkZXMgNDg2IGNo YW5nZXNldHMuCgpBZnRlciB5b3UgZ290IHlvdXIgdmVyeSBvd24gcmVwb3NpdG9yeSBieSBjbG9u aW5nIHRoZSBweWdtZW50cyBvbmUgeW91IHdpbGwgbm90aWNlIHRoYXQgYWxsIHRoZSBzdWJ2ZXJz aW9uLWxpa2UgY29tbWFuZHMgKCJoZyBjaSIsICJoZyBhZGQiLCAiaGcgdXAiLCAuLi4pIHdvcmsg bG9jYWxseSBvbmx5LiBZb3UgY2hlY2sgaW50byB5b3VyIGxvY2FsIHZlcnNpb24gb2YgdGhlIHJl cG9zaXRvcnkgYW5kIGhnIHVwIHdvbid0IGluY29ycG9yYXRlIHJlbW90ZSBjaGFuZ2VzLiBPbmUg b2YgdGhlIHRoaW5ncyB0aGF0IGhhcHBlbiBvbiBoZyBjbG9uZSBpcyB0aGF0IG1lcmN1cmlhbCB3 aWxsIHNldCB0aGUgcGF0aCB0byB0aGUgcmVwb3NpdG9yeSB5b3UgY2xvbmVkIGZyb20gaW50byB0 aGUgaGdyYyBvZiB0aGUgbmV3bHkgY3JlYXRlZCByZXBvc2l0b3J5LiBUaGlzIGZpbGUgKCIuaGcv aGdyYyIpIGlzIHVzZWQgdG8gc3RvcmUgcGVyLXJlcG9zaXRvcnkgY29uZmlndXJhdGlvbiBsaWtl IHRoZSBwYXRoIG9mIHJlbW90ZSByZXBvc2l0b3JpZXMsIHRoZSBuYW1lIHVzZWQgZm9yIGNoZWNr aW5zLCBwbHVnaW5zIHRoYXQgYXJlIG9ubHkgZW5hYmxlZCBmb3IgdGhpcyByZXBvc2l0b3J5IGFu ZCBtb3JlLiBFeGVjdXRpbmcgImhnIHB1bGwiIHdpbGwgYXV0b21hdGljYWxseSBwdWxsIGNoYW5n ZXMgZnJvbSB0aGlzIHJlbW90ZSByZXBvc2l0b3J5IGFuZCBwdXQgdGhlbSBpbnRvIHRoZSBjdXJy ZW50IHJlcG9zaXRvcnkgYXMgc2Vjb25kIGJyYW5jaC4gVG8gc2VlIHdoYXQgImhnIHB1bGwiIHdp bGwgcHVsbCBmcm9tIHRoYXQgcmVtb3RlIHJlcG9zaXRvcnkgeW91IGNhbiBleGVjdXRlICJoZyBp bmNvbWluZyIgYW5kIGl0IHdpbGwgcHJpbnQgYSBsaXN0IG9mIGNoYW5nZXNldHMgdGhhdCBhcmUg aW4gdGhlIHJlbW90ZSByZXBvc2l0b3J5IGJ1dCBub3QgeWV0IGluIHRoZSBsb2NhbCBvbmUuIEFm dGVyIHlvdSBoYXZlIHB1bGxlZCB5b3UgaGF2ZSB0byB1cGRhdGUgdGhlIHJlcG9zaXRvcnkgd2l0 aCAiaGcgdXAiIHNvIHRoYXQgeW91IGNhbiBhY3R1YWxseSBzZWUgdGhlIGNoYW5nZXMuIElmIHRo ZXJlIHdlcmUgcmVtb3RlIGNoYW5nZXMgdGhhdCByZXF1aXJlIG1lcmdpbmcgeW91IGhhdmUgdG8g ImhnIG1lcmdlIiB0aGVtIGFuZCAiaGcgY2kiIHRoZSBtZXJnZS4KCkJlY2F1c2UgdGhpcyBwcm9j ZXNzIGlzIHZlcnkgY29tbW9uIHRoZXJlIGFyZSB3YXlzIHRvIHNpbXBsaWZ5IGl0LiAiaGcgcHVs bCAmJiBoZyB1cGRhdGUiIGNhbiBiZSB3cml0dGVuIGFzICJoZyBwdWxsIC11Ii4gQWxsIHRoZSBj b21tYW5kcyAocHVsbCwgdXBkYXRlLCBtZXJnZSBhbmQgY2hlY2tpbiBpZiByZXF1aXJlZCkgY2Fu IGJlIGhhbmRsZWQgaW4gb25lIGdvIHVzaW5nICJoZyBmZSIuIFRoaXMgY29tbWFuZCBob3dldmVy IGlzIHBhcnQgb2YgYSBwbHVnaW4gd2hpY2ggaXMgZGlzYWJsZWQgYnkgZGVmYXVsdC4gIElmIHlv dSB3YW50IHRvIHVzZSBpdCB5b3UgaGF2ZSB0byBhZGQgdGhlIGZvbGxvd2luZyBsaW5lcyBpbnRv IHRoZSByZXBvc2l0b3J5IGhncmMgb3IgeW91ciBwZXJzb25hbCBvbmU6CgpFUwAAAANwcmVMAABN AABTAAAAGVtleHRlbnNpb25zXQpoZ2V4dC5mZXRjaD1TAAAJNAoKVGhlIG90aGVyIGltcG9ydGFu dCBkaWZmZXJlbmNlIHRvIHN1YnZlcnNpb24gaXMgaG93IHlvdSBwdXNoIHlvdXIgY2hhbmdlcyBi YWNrIHRvIHRoZSBzZXJ2ZXIuIEluIG9wZW4gc291cmNlIHByb2plY3RzIHVzdWFsbHkgb25seSBh IHNtYWxsIG51bWJlciBvZiBkZXZlbG9wZXJzIGhhcyBhY2Nlc3MgdG8gdGhlIG1haW4gcmVwb3Np dG9yeSBhbmQgY29udHJpYnV0b3JzIGNyZWF0ZSBwYXRjaGVzIHVzaW5nICJkaWZmIiBvciAic3Zu IGRpZmYiIGFuZCBtYWlsIGl0IHRvIG9uZSBvZiB0aGUgcGVyc29ucyB3aXRoIGNvbW1pdCByaWdo dHMgb3IgYXR0YWNoIGl0IHRvIGEgdGlja2V0IGluIHRoZSBwcm9qZWN0J3MgdHJhY2tlci4gSWYg eW91IGFyZSBhIHBlcnNvbiB3aXRoIHB1c2ggcHJpdmlsZWdlcyB5b3UgY2FuIGRvICJoZyBwdXNo IiBhbmQgaXQgd2lsbCBwdXNoIHRoZSBjaGFuZ2VzZXRzIHdoaWNoIGFyZSBub3QgeWV0IG9uIHRo ZSBzZXJ2ZXIgKHlvdSBjYW4gbG9vayBhdCB0aGVtIHVzaW5nICJoZyBvdXRnb2luZyIpLiBJZiB5 b3UgZG9uJ3QgaGF2ZSBwdXNoIGFjY2VzcyB5b3UgY2FuIGNyZWF0ZSBhIGJ1bmRsZSBvZiBjaGFu Z2VzIGFuZCBhdHRhY2ggdGhhdCB0byBhIHRpY2tldCByYXRoZXIgdGhhbiBhIHBhdGNoLiBBIGJ1 bmRsZSBzdG9yZXMgbXVsdGlwbGUgY2hhbmdlc2V0cyBpbiBvbmUgZmlsZSBhbmQgaXQgYWxzbyBw cmVzZXJ2ZXMgdGhlIGNvcnJlY3QgYXV0aG9yIGluZm9ybWF0aW9uIGFuZCB0aW1lc3RhbXBzLiBB bm90aGVyIHdheSBpcyBtYWlsaW5nIHRoZSBjaGFuZ2VzIHRvIGEgZGlmZmVyZW50IGRldmVsb3Bl ciB1c2luZyB0aGUgcGF0Y2hib21iIGV4dGVuc2lvbiAoSSB3b24ndCBjb3ZlciB0aGF0IGhlcmUs IGp1c3QgZ29vZ2xlIGl0IHVwKS4gT3IgeW91IGNhbiBsZXQgb3RoZXIgcGVvcGxlIHB1bGwgZnJv bSB5b3VyIHJlcG9zaXRvcnkuIFRoZXJlZm9yZSB5b3UgZWl0aGVyIGhhdmUgdG8gY29uZmlndXJl IHlvdXIgYXBhY2hlIHRvIHNlcnZlciBhIGhnd2ViIGluc3RhbmNlIG9yIHlvdSBqdXN0IGNhbGwg ImhnIHNlcnZlIiBhbmQgaXQgd2lsbCBzcGF3biBhIHNlcnZlciBvbiBsb2NhbGhvc3Q6ODAwMCBl dmVyeWJvZHkgY2FuIHB1bGwgZnJvbS4KCk9uY2UgdGhlIGRldmVsb3BlciBoYXMgZGVjaWRlZCB0 byBwdXQgeW91ciBjaGFuZ2VzIGludG8gdGhlIGNlbnRyYWwgcmVwb3NpdG9yeSBhbmQgcHVzaGVk IHRoZW0sIHlvdXIgY2hhbmdlcyB3aWxsIGFwcGVhciB0aGVyZSB1bmFsdGVyZWQgYW5kIHdpdGgg dGhlIHNhbWUgcmV2aXNpb24gaGFzaGVzLiBXaGF0IHdpbGwgYmUgZGlmZmVyZW50IGlzIHRoZSBs b2NhbCBudW1iZXIgdGhlIGNoYW5nZXNldCBpcyBnaXZlbi4gSWYgdGhlIHJldmlzaW9uIHdhcyBj YWxsZWQgZGVhZGJlZWY6NDIgbG9jYWxseSBpdCBjb3VsZCBiZSBjYWxsZWQgZGVhZGJlZWY6NTIg b24gdGhlIHNlcnZlciBiZWNhdXNlIGRpZmZlcmVudCBjaGFuZ2VzZXRzIHdlcmUgYXBwbGllZCBm aXJzdC4KCkFsbCB0aGUgY29tbWFuZHMgdGhhdCBpbnRlcmFjdCB3aXRoIHJlbW90ZSByZXBvc2l0 b3JpZXMgKCJoZyBwdWxsIiwgImhnIHB1c2giLCAiaGcgZmUiLCAuLi4pIGFsc28gdGFrZSBhIGRp ZmZlcmVudCBwYXRoIHRoYW4gdGhlIGRlZmF1bHQgcGF0aCBmcm9tIHRoZSBoZ3JjIGFzIGFyZ3Vt ZW50LiBUaGlzIGFsbG93cyB5b3UgdG8gcHVsbCBjaGFuZ2VzIGZyb20gcmVwb3NpdG9yaWVzIHNo YXJlZCBvdmVyIHRoZSB3ZWIuCgpBIGNvb2wgZXhhbXBsZSB3aGF0IG1lcmN1cmlhbCBhbGxvd3Mg eW91IHRvIGRvIGlzIG91ciBsYXN0IHVidW50dXVzZXJzIHdlYnRlYW0gbWVldHVwLiBUaGVyZSB3 ZSB1c2VkIG15IG5vdGVib29rIHRvIHN0b3JlIHRoZSBjZW50cmFsIHJlcG9zaXRvcnkgYW5kIGV2 ZXJ5Ym9keSBwdXNoZWQgdGhlIGNoYW5nZXMgZXZlcnkgb25jZSBpbiBhIHdoaWxlIHRvIGl0LiBB ZGRpdGlvbmFsbHkgc29tZSBwZW9wbGUgZXhjaGFuZ2VkIHBhdGNoZXMgdG8gbm90IHlldCB3b3Jr aW5nIGZlYXR1cmVzIGFtb25nIGVhY2ggb3RoZXIgc28gdGhhdCB0aGUgY29kZSBvbiB0aGUgY2Vu dHJhbCByZXBvIHdhcyBzZWxkb20gYnJva2VuLiBXaGVuIEkgbGVmdCBldmVyeWJvZHkgaGFkIGFs bCB0aGUgY2hhbmdlcyBsb2NhbGx5IGJlY2F1c2UgdGhleSBwdWxsZWQgYW5kIEkgY291bGQgcmVt b3ZlIG15IG5vdGVib29rIGFuZCBldmVyeWJvZHkgY29udGludWVkIHdvcmtpbmcgb24gdGhlaXIg d2F5IGhvbWUuIFdoZW4gd2UgbWV0IGFnYWluIG9uIElSQyBJIGNvcGllZCBteSByZXBvIG9uIHRo ZSBzZXJ2ZXIgYW5kIGV2ZXJ5Ym9keSBwdXNoZWQgdGhlaXIgbG9jYWwgY2hhbmdlcyB0byBpdC5T AAAABnBhcnNlclMAAAAEaHRtbFMAAAAFaW50cm9SUwAAAABMAAA= Horst Gutmannzerok@zerokspot.comhttp://zerokspot.com2008-01-28T20:20:49Znono0Very nice primer :-) It would really be nice to see more projects using DVCS and if it's just to make it easier for outsiders to contribute whole changesets instead of just patches which they won't get the full credits. Btw.: Are you coming the the BarCamp in Klagenfurt this weekend? Would be a really nice presentation :-)Very nice primer :-) It would really be nice to see more projects using DVCS and if it's just to make it easier for outsiders to contribute whole changesets instead of just patches which they won't get the full credits. Btw.: Are you coming the the BarCamp in Klagenfurt this weekend? Would be a really nice presentation :-)SQAAAAJTAAAABGJvZHlSUwAAAUVWZXJ5IG5pY2UgcHJpbWVyIDotKSBJdCB3b3VsZCByZWFsbHkg YmUgbmljZSB0byBzZWUgbW9yZSBwcm9qZWN0cyB1c2luZyBEVkNTIGFuZCBpZiBpdCdzIGp1c3Qg dG8gbWFrZSBpdCBlYXNpZXIgZm9yIG91dHNpZGVycyB0byBjb250cmlidXRlIHdob2xlIGNoYW5n ZXNldHMgaW5zdGVhZCBvZiBqdXN0IHBhdGNoZXMgd2hpY2ggdGhleSB3b24ndCBnZXQgdGhlIGZ1 bGwgY3JlZGl0cy4KCkJ0dy46IEFyZSB5b3UgY29taW5nIHRoZSB0aGUgQmFyQ2FtcCBpbiBLbGFn ZW5mdXJ0IHRoaXMgd2Vla2VuZD8gV291bGQgYmUgYSByZWFsbHkgbmljZSBwcmVzZW50YXRpb24g Oi0pTAAAUwAAAAZwYXJzZXJTAAAABGh0bWw= Christoph Hackchristoph@tux21b.orghttp://www.tux21b.org/2008-01-28T20:34:56Znono0Yeah, I am very impressed by mercurial too. Additionally to the main Ubuntuusers repository I have set up another on my server and now I can develop on different hosts, without altering the main one, but everybody can push if needed. And on our meeting (which was also really awesome *g*) there where up to 10 different branches at the same time, and we continued editing the same files simultaneously and I only had to fix a conflict once. And even then, manually merging was much nicer than in subversion, because there weren't 3 different files and mercurial asks directly while merging the the branches. Furthermore the speed of the VCS transactions where also unfamiliarly fast, so lets stick with mercurial. Regards ChristophYeah, I am very impressed by mercurial too. Additionally to the main Ubuntuusers repository I have set up another on my server and now I can develop on different hosts, without altering the main one, but everybody can push if needed. And on our meeting (which was also really awesome *g*) there where up to 10 different branches at the same time, and we continued editing the same files simultaneously and I only had to fix a conflict once. And even then, manually merging was much nicer than in subversion, because there weren't 3 different files and mercurial asks directly while merging the the branches. Furthermore the speed of the VCS transactions where also unfamiliarly fast, so lets stick with mercurial. Regards ChristophSQAAAAJTAAAABGJvZHlSUwAAAt5ZZWFoLCBJIGFtIHZlcnkgaW1wcmVzc2VkIGJ5IG1lcmN1cmlh bCB0b28uIEFkZGl0aW9uYWxseSB0byB0aGUgbWFpbiBVYnVudHV1c2VycyByZXBvc2l0b3J5IEkg aGF2ZSBzZXQgdXAgYW5vdGhlciBvbiBteSBzZXJ2ZXIgYW5kIG5vdyBJIGNhbiBkZXZlbG9wIG9u IGRpZmZlcmVudCBob3N0cywgd2l0aG91dCBhbHRlcmluZyB0aGUgbWFpbiBvbmUsIGJ1dCBldmVy eWJvZHkgY2FuIHB1c2ggaWYgbmVlZGVkLgoKQW5kIG9uIG91ciBtZWV0aW5nICh3aGljaCB3YXMg YWxzbyByZWFsbHkgYXdlc29tZSAqZyopIHRoZXJlIHdoZXJlIHVwIHRvIDEwIGRpZmZlcmVudCBi cmFuY2hlcyBhdCB0aGUgc2FtZSB0aW1lLCBhbmQgd2UgY29udGludWVkIGVkaXRpbmcgdGhlIHNh bWUgZmlsZXMgc2ltdWx0YW5lb3VzbHkgYW5kIEkgb25seSBoYWQgdG8gZml4IGEgY29uZmxpY3Qg b25jZS4gQW5kIGV2ZW4gdGhlbiwgbWFudWFsbHkgbWVyZ2luZyB3YXMgbXVjaCBuaWNlciB0aGFu IGluIHN1YnZlcnNpb24sIGJlY2F1c2UgdGhlcmUgd2VyZW4ndCAzIGRpZmZlcmVudCBmaWxlcyBh bmQgbWVyY3VyaWFsIGFza3MgZGlyZWN0bHkgd2hpbGUgbWVyZ2luZyB0aGUgdGhlIGJyYW5jaGVz LgoKRnVydGhlcm1vcmUgdGhlIHNwZWVkIG9mIHRoZSBWQ1MgdHJhbnNhY3Rpb25zIHdoZXJlIGFs c28gdW5mYW1pbGlhcmx5IGZhc3QsIHNvIGxldHMgc3RpY2sgd2l0aCBtZXJjdXJpYWwuCgpSZWdh cmRzCkNocmlzdG9waEwAAFMAAAAGcGFyc2VyUwAAAARodG1s Ericeric.nilsson@slaskpost.se2008-01-28T20:43:08Znono0Just one question, i think you did expect it.. :) Why not git? like the hacker you are how could you not be convinced by torvalds google talk (youtube it)!Just one question, i think you did expect it.. :) Why not git? like the hacker you are how could you not be convinced by torvalds google talk (youtube it)!SQAAAAJTAAAABGJvZHlSUwAAAJtKdXN0IG9uZSBxdWVzdGlvbiwgaSB0aGluayB5b3UgZGlkIGV4 cGVjdCBpdC4uIDopIFdoeSBub3QgZ2l0PyBsaWtlIHRoZSBoYWNrZXIgeW91IGFyZSBob3cgY291 bGQgeW91IG5vdCBiZSBjb252aW5jZWQgYnkgdG9ydmFsZHMgZ29vZ2xlIHRhbGsgKHlvdXR1YmUg aXQpIUwAAFMAAAAGcGFyc2VyUwAAAARodG1s Armin Ronacherarmin.ronacher@active-4.comhttp://lucumr.pocoo.org/2008-01-28T20:51:41Znono0@Horst Gutmann: Yes, I will be there. I would love to talk about DVCS systems, however there is already a talk about that topic on the proposal list. @Eric: Both git and mercurial are very nice systems. The reason why I'm currently more interested in mercurial is the fact that it runs on all three systems I use (linux, os x, windows) without many hacks, and that it's written in Python :-)@Horst Gutmann: Yes, I will be there. I would love to talk about DVCS systems, however there is already a talk about that topic on the proposal list. @Eric: Both git and mercurial are very nice systems. The reason why I'm currently more interested in mercurial is the fact that it runs on all three systems I use (linux, os x, windows) without many hacks, and that it's written in Python :-)SQAAAAJTAAAABGJvZHlSUwAAAYhASG9yc3QgR3V0bWFubjogWWVzLCBJIHdpbGwgYmUgdGhlcmUu IEkgd291bGQgbG92ZSB0byB0YWxrIGFib3V0IERWQ1Mgc3lzdGVtcywgaG93ZXZlciB0aGVyZSBp cyBhbHJlYWR5IGEgdGFsayBhYm91dCB0aGF0IHRvcGljIG9uIHRoZSBwcm9wb3NhbCBsaXN0LgoK QEVyaWM6IEJvdGggZ2l0IGFuZCBtZXJjdXJpYWwgYXJlIHZlcnkgbmljZSBzeXN0ZW1zLiBUaGUg cmVhc29uIHdoeSBJJ20gY3VycmVudGx5IG1vcmUgaW50ZXJlc3RlZCBpbiBtZXJjdXJpYWwgaXMg dGhlIGZhY3QgdGhhdCBpdCBydW5zIG9uIGFsbCB0aHJlZSBzeXN0ZW1zIEkgdXNlIChsaW51eCwg b3MgeCwgd2luZG93cykgd2l0aG91dCBtYW55IGhhY2tzLCBhbmQgdGhhdCBpdCdzIHdyaXR0ZW4g aW4gUHl0aG9uIDotKUwAAFMAAAAGcGFyc2VyUwAAAARodG1s Eric Florenzanofloguy@gmail.comhttp://www.eflorenzano.com/2008-01-28T21:30:07Znono0@Armin's Comment 4: In that case, did you check out Bazaar? I've tried both, and neither one really seemed much better than the other, but Bazaar is supposedly better at complex merges.@Armin's Comment 4: In that case, did you check out Bazaar? I've tried both, and neither one really seemed much better than the other, but Bazaar is supposedly better at complex merges.SQAAAAJTAAAABGJvZHlSUwAAALpAQXJtaW4ncyBDb21tZW50IDQ6IEluIHRoYXQgY2FzZSwgZGlk IHlvdSBjaGVjayBvdXQgQmF6YWFyPyAgSSd2ZSB0cmllZCBib3RoLCBhbmQgbmVpdGhlciBvbmUg cmVhbGx5IHNlZW1lZCBtdWNoIGJldHRlciB0aGFuIHRoZSBvdGhlciwgYnV0IEJhemFhciBpcyBz dXBwb3NlZGx5IGJldHRlciBhdCBjb21wbGV4IG1lcmdlcy5MAABTAAAABnBhcnNlclMAAAAEaHRt bA== Armin Ronacherarmin.ronacher@active-4.comhttp://lucumr.pocoo.org/2008-01-28T21:43:07Znono0Well, there are many DVCS, I selected mercurial ;-) Feel free to use bzr, git, darcs or whatever, they are all nice systems and have their own advantages and disadvantages. The reasons why I personally use mercurial are speed, the good community and support, the trac integration, the helpful channel and the good windows/os x support beside linux.Well, there are many DVCS, I selected mercurial ;-) Feel free to use bzr, git, darcs or whatever, they are all nice systems and have their own advantages and disadvantages. The reasons why I personally use mercurial are speed, the good community and support, the trac integration, the helpful channel and the good windows/os x support beside linux.SQAAAAJTAAAABGJvZHlSUwAAAVxXZWxsLCB0aGVyZSBhcmUgbWFueSBEVkNTLCBJIHNlbGVjdGVk IG1lcmN1cmlhbCA7LSkgRmVlbCBmcmVlIHRvIHVzZSBienIsIGdpdCwgZGFyY3Mgb3Igd2hhdGV2 ZXIsIHRoZXkgYXJlIGFsbCBuaWNlIHN5c3RlbXMgYW5kIGhhdmUgdGhlaXIgb3duIGFkdmFudGFn ZXMgYW5kIGRpc2FkdmFudGFnZXMuIFRoZSByZWFzb25zIHdoeSBJIHBlcnNvbmFsbHkgdXNlIG1l cmN1cmlhbCBhcmUgc3BlZWQsIHRoZSBnb29kIGNvbW11bml0eSBhbmQgc3VwcG9ydCwgdGhlIHRy YWMgaW50ZWdyYXRpb24sIHRoZSBoZWxwZnVsIGNoYW5uZWwgYW5kIHRoZSBnb29kIHdpbmRvd3Mv b3MgeCBzdXBwb3J0IGJlc2lkZSBsaW51eC5MAABTAAAABnBhcnNlclMAAAAEaHRtbA== Horst Gutmannzerok@zerokspot.comhttp://zerokspot.com2008-01-28T21:47:46Znono0@Armin: That's mine and I just killed that ;-) So the slot should be free again :-) If you're interested we could also convert this in some kind of discussion to find out what other people are using to perhaps find some best practices. @Eric: I've tried using bzr every once in a while but ever time switched back to hg simply because of the far better performance. The only downside hg currently has for me is a replication "bug" that makes mercurial store a new copy of a file whenever it is renamed which might or might not be relevant depending on the project: http://www.selenic.com/mercurial/bts/issue883@Armin: That's mine and I just killed that ;-) So the slot should be free again :-) If you're interested we could also convert this in some kind of discussion to find out what other people are using to perhaps find some best practices. @Eric: I've tried using bzr every once in a while but ever time switched back to hg simply because of the far better performance. The only downside hg currently has for me is a replication "bug" that makes mercurial store a new copy of a file whenever it is renamed which might or might not be relevant depending on the project: http://www.selenic.com/mercurial/bts/issue883SQAAAAJTAAAABGJvZHlSUwAAAmNAQXJtaW46IFRoYXQncyBtaW5lIGFuZCBJIGp1c3Qga2lsbGVk IHRoYXQgOy0pIFNvIHRoZSBzbG90IHNob3VsZCBiZSBmcmVlIGFnYWluIDotKSBJZiB5b3UncmUg aW50ZXJlc3RlZCB3ZSBjb3VsZCBhbHNvIGNvbnZlcnQgdGhpcyBpbiBzb21lIGtpbmQgb2YgZGlz Y3Vzc2lvbiB0byBmaW5kIG91dCB3aGF0IG90aGVyIHBlb3BsZSBhcmUgdXNpbmcgdG8gcGVyaGFw cyBmaW5kIHNvbWUgYmVzdCBwcmFjdGljZXMuCgpARXJpYzogSSd2ZSB0cmllZCB1c2luZyBienIg ZXZlcnkgb25jZSBpbiBhIHdoaWxlIGJ1dCBldmVyIHRpbWUgc3dpdGNoZWQgYmFjayB0byBoZyBz aW1wbHkgYmVjYXVzZSBvZiB0aGUgZmFyIGJldHRlciBwZXJmb3JtYW5jZS4gVGhlIG9ubHkgZG93 bnNpZGUgaGcgY3VycmVudGx5IGhhcyBmb3IgbWUgaXMgYSByZXBsaWNhdGlvbiAiYnVnIiB0aGF0 IG1ha2VzIG1lcmN1cmlhbCBzdG9yZSBhIG5ldyBjb3B5IG9mIGEgZmlsZSB3aGVuZXZlciBpdCBp cyByZW5hbWVkIHdoaWNoIG1pZ2h0IG9yIG1pZ2h0IG5vdCBiZSByZWxldmFudCBkZXBlbmRpbmcg b24gdGhlIHByb2plY3Q6IGh0dHA6Ly93d3cuc2VsZW5pYy5jb20vbWVyY3VyaWFsL2J0cy9pc3N1 ZTg4M0wAAFMAAAAGcGFyc2VyUwAAAARodG1s Armin Ronacherarmin.ronacher@active-4.comhttp://lucumr.pocoo.org/2008-01-28T22:01:07Znono0@Horst: Who do I have to talk to if I want to occupy that slot? And which is it? :-)@Horst: Who do I have to talk to if I want to occupy that slot? And which is it? :-)SQAAAAJTAAAABGJvZHlSUwAAAFRASG9yc3Q6IFdobyBkbyBJIGhhdmUgdG8gdGFsayB0byBpZiBJ IHdhbnQgdG8gb2NjdXB5IHRoYXQgc2xvdD8gQW5kIHdoaWNoIGlzIGl0PyA6LSlMAABTAAAABnBh cnNlclMAAAAEaHRtbA== Horst Gutmannzerok@zerokspot.comhttp://zerokspot.com2008-01-29T06:59:15Znono0No one. Just add your proposal to the proposal list and take a slot in the schedule if you want. I guess the whole "who gets what timeslot" will be decided sometime on Saturday before the first presentation ;-)No one. Just add your proposal to the proposal list and take a slot in the schedule if you want. I guess the whole "who gets what timeslot" will be decided sometime on Saturday before the first presentation ;-)SQAAAAJTAAAABGJvZHlSUwAAANJObyBvbmUuIEp1c3QgYWRkIHlvdXIgcHJvcG9zYWwgdG8gdGhl IHByb3Bvc2FsIGxpc3QgYW5kIHRha2UgYSBzbG90IGluIHRoZSBzY2hlZHVsZSBpZiB5b3Ugd2Fu dC4gSSBndWVzcyB0aGUgd2hvbGUgIndobyBnZXRzIHdoYXQgdGltZXNsb3QiIHdpbGwgYmUgZGVj aWRlZCBzb21ldGltZSBvbiBTYXR1cmRheSBiZWZvcmUgdGhlIGZpcnN0IHByZXNlbnRhdGlvbiA7 LSlMAABTAAAABnBhcnNlclMAAAAEaHRtbA== Stunosp@mplea.se2008-01-29T11:55:21Znono0I don't know why people forget linking these days. The whole blog post contains not one single link. I had to google mercurial. Sigh.I don't know why people forget linking these days. The whole blog post contains not one single link. I had to google mercurial. Sigh.SQAAAAJTAAAABGJvZHlSUwAAAIVJIGRvbid0IGtub3cgd2h5IHBlb3BsZSBmb3JnZXQgbGlua2lu ZyB0aGVzZSBkYXlzLiBUaGUgd2hvbGUgYmxvZyBwb3N0IGNvbnRhaW5zIG5vdCBvbmUgc2luZ2xl IGxpbmsuIEkgaGFkIHRvIGdvb2dsZSBtZXJjdXJpYWwuIFNpZ2guTAAAUwAAAAZwYXJzZXJTAAAA BGh0bWw= Armin Ronacherarmin.ronacher@active-4.comhttp://lucumr.pocoo.org/2008-01-29T13:56:28Znono0@10: added the Link, sorry for that ;-)@10: added the Link, sorry for that ;-)SQAAAAJTAAAABGJvZHlSUwAAACdAMTA6IGFkZGVkIHRoZSBMaW5rLCBzb3JyeSBmb3IgdGhhdCA7 LSlMAABTAAAABnBhcnNlclMAAAAEaHRtbA== Ray Gardnerraygard@gmail.com2008-01-30T22:19:55Znono0I looked briefly at Hg a few weeks ago for a project I'm working on. For my project, it's important to maintain the timestamps on files as they are edited. It seemed to me that when I cloned, files got all new timestamps. Is there a switch or config option for Hg to make it preserve timestamps of files, so that when they're checked out they have the same time as when they were checked in (modulo the resolution that Python keeps file times at)? Am I missing something?I looked briefly at Hg a few weeks ago for a project I'm working on. For my project, it's important to maintain the timestamps on files as they are edited. It seemed to me that when I cloned, files got all new timestamps. Is there a switch or config option for Hg to make it preserve timestamps of files, so that when they're checked out they have the same time as when they were checked in (modulo the resolution that Python keeps file times at)? Am I missing something?SQAAAAJTAAAABGJvZHlSUwAAAddJIGxvb2tlZCBicmllZmx5IGF0IEhnIGEgZmV3IHdlZWtzIGFn byBmb3IgYSBwcm9qZWN0IEknbSB3b3JraW5nIG9uLiBGb3IgbXkgcHJvamVjdCwgaXQncyBpbXBv cnRhbnQgdG8gbWFpbnRhaW4gdGhlIHRpbWVzdGFtcHMgb24gZmlsZXMgYXMgdGhleSBhcmUgZWRp dGVkLiBJdCBzZWVtZWQgdG8gbWUgdGhhdCB3aGVuIEkgY2xvbmVkLCBmaWxlcyBnb3QgYWxsIG5l dyB0aW1lc3RhbXBzLiBJcyB0aGVyZSBhIHN3aXRjaCBvciBjb25maWcgb3B0aW9uIGZvciBIZyB0 byBtYWtlIGl0IHByZXNlcnZlIHRpbWVzdGFtcHMgb2YgZmlsZXMsIHNvIHRoYXQgd2hlbiB0aGV5 J3JlIGNoZWNrZWQgb3V0IHRoZXkgaGF2ZSB0aGUgc2FtZSB0aW1lIGFzIHdoZW4gdGhleSB3ZXJl IGNoZWNrZWQgaW4gKG1vZHVsbyB0aGUgcmVzb2x1dGlvbiB0aGF0IFB5dGhvbiBrZWVwcyBmaWxl IHRpbWVzIGF0KT8gQW0gSSBtaXNzaW5nIHNvbWV0aGluZz9MAABTAAAABnBhcnNlclMAAAAEaHRt bA== Armin Ronacherarmin.ronacher@active-4.comhttp://lucumr.pocoo.org/2008-01-30T22:56:12Znono0Na, mercurial doesn't track the timestamps of the files. I don't know if there is any distributed system that allows that.Na, mercurial doesn't track the timestamps of the files. I don't know if there is any distributed system that allows that.SQAAAAJTAAAABGJvZHlSUwAAAHpOYSwgbWVyY3VyaWFsIGRvZXNuJ3QgdHJhY2sgdGhlIHRpbWVz dGFtcHMgb2YgdGhlIGZpbGVzLiBJIGRvbid0IGtub3cgaWYgdGhlcmUgaXMgYW55IGRpc3RyaWJ1 dGVkIHN5c3RlbSB0aGF0IGFsbG93cyB0aGF0LkwAAFMAAAAGcGFyc2VyUwAAAARodG1s Armin Ronacherarmin.ronacher@active-4.comhttp://lucumr.pocoo.org/2008-01-30T23:00:03Znono0Okay, I was wrong I think. Here is a FAQ entry about that issue: http://www.selenic.com/mercurial/wiki/index.cgi/FAQOkay, I was wrong I think. Here is a FAQ entry about that issue: http://www.selenic.com/mercurial/wiki/index.cgi/FAQSQAAAAJTAAAABGJvZHlSUwAAAHRPa2F5LCBJIHdhcyB3cm9uZyBJIHRoaW5rLiBIZXJlIGlzIGEg RkFRIGVudHJ5IGFib3V0IHRoYXQgaXNzdWU6IGh0dHA6Ly93d3cuc2VsZW5pYy5jb20vbWVyY3Vy aWFsL3dpa2kvaW5kZXguY2dpL0ZBUUwAAFMAAAAGcGFyc2VyUwAAAARodG1s ubuntuusers Webteam Meetinghttp://lucumr.pocoo.org/cogitations/2008/01/28/ubuntuusers-webteam-meeting/2008-01-28T15:26:03Z2008-01-28T15:26:03ZArmin Ronacherubuntuusers-webteam-meetingyesyes2The last four days I attended <a href="http://www.ubuntuusers.de/">our</a> first offline-webteam meeting and it was fun ;-) We spend a few days hacking on various parts of the ubuntuusers software and had a great time. While it's pointless to talk about what we did because hacking on broken code is not that much fun as such (unless you can laugh about PHP bugs and stuff like that) I think we can present some of the changes with the upcoming hardy release. Don't expect too much but that shows that we are doing something even if you think development on the German portal software is stalled. That's certainly not the case. But we are once again looking for web designers. The sourcecode is multilingual and the development takes place in both German and English for potential future translations to other languages than German, so you can participate even if you are not speaking German :-) If you are interested in participating and if you have advanced XHTML1/HTML4/CSS2 skills, we want you for ubuntuusers webteam! If you are interested mail me at mitsuhiko you know what comes next ubuntu dot com.The last four days I attended <a href="http://www.ubuntuusers.de/">our</a> first offline-webteam meeting and it was fun ;-) We spend a few days hacking on various parts of the ubuntuusers software and had a great time. While it's pointless to talk about what we did because hacking on broken code is not that much fun as such (unless you can laugh about PHP bugs and stuff like that) I think we can present some of the changes with the upcoming hardy release. Don't expect too much but that shows that we are doing something even if you think development on the German portal software is stalled. That's certainly not the case. But we are once again looking for web designers. The sourcecode is multilingual and the development takes place in both German and English for potential future translations to other languages than German, so you can participate even if you are not speaking German :-) If you are interested in participating and if you have advanced XHTML1/HTML4/CSS2 skills, we want you for ubuntuusers webteam! If you are interested mail me at mitsuhiko you know what comes next ubuntu dot com.SQAAAANTAAAABGJvZHlSUwAAAB5UaGUgbGFzdCBmb3VyIGRheXMgSSBhdHRlbmRlZCBMAAFFUwAA AAFhTAAATQABUwAAAARocmVmUwAAABpodHRwOi8vd3d3LnVidW50dXVzZXJzLmRlL1MAAAADb3Vy UwAABAsgZmlyc3Qgb2ZmbGluZS13ZWJ0ZWFtIG1lZXRpbmcgYW5kIGl0IHdhcyBmdW4gOy0pIFdl IHNwZW5kIGEgZmV3IGRheXMgaGFja2luZyBvbiB2YXJpb3VzIHBhcnRzIG9mIHRoZSB1YnVudHV1 c2VycyBzb2Z0d2FyZSBhbmQgaGFkIGEgZ3JlYXQgdGltZS4gV2hpbGUgaXQncyBwb2ludGxlc3Mg dG8gdGFsayBhYm91dCB3aGF0IHdlIGRpZCBiZWNhdXNlIGhhY2tpbmcgb24gYnJva2VuIGNvZGUg aXMgbm90IHRoYXQgbXVjaCBmdW4gYXMgc3VjaCAodW5sZXNzIHlvdSBjYW4gbGF1Z2ggYWJvdXQg UEhQIGJ1Z3MgYW5kIHN0dWZmIGxpa2UgdGhhdCkgSSB0aGluayB3ZSBjYW4gcHJlc2VudCBzb21l IG9mIHRoZSBjaGFuZ2VzIHdpdGggdGhlIHVwY29taW5nIGhhcmR5IHJlbGVhc2UuCgpEb24ndCBl eHBlY3QgdG9vIG11Y2ggYnV0IHRoYXQgc2hvd3MgdGhhdCB3ZSBhcmUgZG9pbmcgc29tZXRoaW5n IGV2ZW4gaWYgeW91IHRoaW5rIGRldmVsb3BtZW50IG9uIHRoZSBHZXJtYW4gcG9ydGFsIHNvZnR3 YXJlIGlzIHN0YWxsZWQuIFRoYXQncyBjZXJ0YWlubHkgbm90IHRoZSBjYXNlLgoKQnV0IHdlIGFy ZSBvbmNlIGFnYWluIGxvb2tpbmcgZm9yIHdlYiBkZXNpZ25lcnMuIFRoZSBzb3VyY2Vjb2RlIGlz IG11bHRpbGluZ3VhbCBhbmQgdGhlIGRldmVsb3BtZW50IHRha2VzIHBsYWNlIGluIGJvdGggR2Vy bWFuIGFuZCBFbmdsaXNoIGZvciBwb3RlbnRpYWwgZnV0dXJlIHRyYW5zbGF0aW9ucyB0byBvdGhl ciBsYW5ndWFnZXMgdGhhbiBHZXJtYW4sIHNvIHlvdSBjYW4gcGFydGljaXBhdGUgZXZlbiBpZiB5 b3UgYXJlIG5vdCBzcGVha2luZyBHZXJtYW4gOi0pIElmIHlvdSBhcmUgaW50ZXJlc3RlZCBpbiBw YXJ0aWNpcGF0aW5nIGFuZCBpZiB5b3UgaGF2ZSBhZHZhbmNlZCBYSFRNTDEvSFRNTDQvQ1NTMiBz a2lsbHMsIHdlIHdhbnQgeW91IGZvciB1YnVudHV1c2VycyB3ZWJ0ZWFtIQoKSWYgeW91IGFyZSBp bnRlcmVzdGVkIG1haWwgbWUgYXQgbWl0c3VoaWtvIHlvdSBrbm93IHdoYXQgY29tZXMgbmV4dCB1 YnVudHUgZG90IGNvbS5TAAAABnBhcnNlclMAAAAEaHRtbFMAAAAFaW50cm9SUwAAAABMAAA= No…http://lucumr.pocoo.org/cogitations/2008/01/23/no/2008-01-23T22:31:07Z2008-01-23T22:31:07ZArmin Ronachernoyesyes2<a href="http://diveintomark.org/archives/2008/01/23/microsoft-koan">I</a> <a href="http://blogs.msdn.com/ie/archive/2008/01/21/compatibility-and-ie8.aspx">will</a> <a href="http://annevankesteren.nl/2008/01/ie-lock-in">not</a> <a href="http://weblogs.mozillazine.org/roc/archives/2008/01/post_2.html">blog</a> <a href="http://weblogs.mozillazine.org/roc/archives/2008/01/slipping_the_ba.html">about</a> <a href="http://webkit.org/blog/155/versioning-compatibility-and-standards/">it</a>, <a href="http://dean.edwards.name/weblog/2008/01/quotes/">because</a> <a href="http://www.b-list.org/weblog/2008/jan/23/legacy/">it</a> <a href="http://ajaxian.com/archives/ie8-compatibility-with-x-ua-compatible">just</a> <a href="http://alistapart.com/articles/beyonddoctype">sucks</a>.<a href="http://diveintomark.org/archives/2008/01/23/microsoft-koan">I</a> <a href="http://blogs.msdn.com/ie/archive/2008/01/21/compatibility-and-ie8.aspx">will</a> <a href="http://annevankesteren.nl/2008/01/ie-lock-in">not</a> <a href="http://weblogs.mozillazine.org/roc/archives/2008/01/post_2.html">blog</a> <a href="http://weblogs.mozillazine.org/roc/archives/2008/01/slipping_the_ba.html">about</a> <a href="http://webkit.org/blog/155/versioning-compatibility-and-standards/">it</a>, <a href="http://dean.edwards.name/weblog/2008/01/quotes/">because</a> <a href="http://www.b-list.org/weblog/2008/jan/23/legacy/">it</a> <a href="http://ajaxian.com/archives/ie8-compatibility-with-x-ua-compatible">just</a> <a href="http://alistapart.com/articles/beyonddoctype">sucks</a>.SQAAAANTAAAABGJvZHlSUwAAAABMAApFUwAAAAFhTAAATQABUwAAAARocmVmUwAAADpodHRwOi8v ZGl2ZWludG9tYXJrLm9yZy9hcmNoaXZlcy8yMDA4LzAxLzIzL21pY3Jvc29mdC1rb2FuUwAAAAFJ UwAAAAEgRVMAAAABYUwAAE0AAVMAAAAEaHJlZlMAAABGaHR0cDovL2Jsb2dzLm1zZG4uY29tL2ll L2FyY2hpdmUvMjAwOC8wMS8yMS9jb21wYXRpYmlsaXR5LWFuZC1pZTguYXNweFMAAAAEd2lsbFMA AAABIEVTAAAAAWFMAABNAAFTAAAABGhyZWZTAAAALGh0dHA6Ly9hbm5ldmFua2VzdGVyZW4ubmwv MjAwOC8wMS9pZS1sb2NrLWluUwAAAANub3RTAAAAASBFUwAAAAFhTAAATQABUwAAAARocmVmUwAA AD9odHRwOi8vd2VibG9ncy5tb3ppbGxhemluZS5vcmcvcm9jL2FyY2hpdmVzLzIwMDgvMDEvcG9z dF8yLmh0bWxTAAAABGJsb2dTAAAAASBFUwAAAAFhTAAATQABUwAAAARocmVmUwAAAEhodHRwOi8v d2VibG9ncy5tb3ppbGxhemluZS5vcmcvcm9jL2FyY2hpdmVzLzIwMDgvMDEvc2xpcHBpbmdfdGhl X2JhLmh0bWxTAAAABWFib3V0UwAAAAEgRVMAAAABYUwAAE0AAVMAAAAEaHJlZlMAAABCaHR0cDov L3dlYmtpdC5vcmcvYmxvZy8xNTUvdmVyc2lvbmluZy1jb21wYXRpYmlsaXR5LWFuZC1zdGFuZGFy ZHMvUwAAAAJpdFMAAAACLCBFUwAAAAFhTAAATQABUwAAAARocmVmUwAAAC9odHRwOi8vZGVhbi5l ZHdhcmRzLm5hbWUvd2VibG9nLzIwMDgvMDEvcXVvdGVzL1MAAAAHYmVjYXVzZVMAAAABIEVTAAAA AWFMAABNAAFTAAAABGhyZWZTAAAAMGh0dHA6Ly93d3cuYi1saXN0Lm9yZy93ZWJsb2cvMjAwOC9q YW4vMjMvbGVnYWN5L1MAAAACaXRTAAAAASBFUwAAAAFhTAAATQABUwAAAARocmVmUwAAAEJodHRw Oi8vYWpheGlhbi5jb20vYXJjaGl2ZXMvaWU4LWNvbXBhdGliaWxpdHktd2l0aC14LXVhLWNvbXBh dGlibGVTAAAABGp1c3RTAAAAASBFUwAAAAFhTAAATQABUwAAAARocmVmUwAAACxodHRwOi8vYWxp c3RhcGFydC5jb20vYXJ0aWNsZXMvYmV5b25kZG9jdHlwZVMAAAAFc3Vja3NTAAAAAS5TAAAABnBh cnNlclMAAAAEaHRtbFMAAAAFaW50cm9SUwAAAABMAAA= Python Code Introspectionhttp://lucumr.pocoo.org/cogitations/2008/01/21/python-code-introspection/2008-01-21T21:00:09Z2008-01-21T21:00:09ZArmin Ronacherpython-code-introspectionyesyes2<a href="http://pyside.blogspot.com/2008/01/what-do-you-look-for-in-documentation.html">Georg blogged about sphinx</a> recently and now we can all rejoice because sphinx can now be used with custom documentation (non c-python documentation) too. Unfortunately hand written documentation alone is hard to maintain. For Werkzeug 0.2 I want to switch to a combination of hand written documentation and source documentation generated from python sourcecode, powered by sphinx of course. The main problem is getting the information out of the sourcecode. Unlike compiled languages in Python a lot is dynamic and much of the functionality is only available at runtime. Unlike PHP objects can be modified later on, and unlike Ruby there are attributes and methods on classes so it's hard to hide private/protected stuff on a class. epydoc came up with some conventions (especially for rst users) but introspection is still too hard in python and will lead to unexpected results. A pretty common idom in python is to implement a class in one file and import it to somewhere else, where it will become importable from. One of the best example was Python's "re" module. Until 2.5 that module was a stub and the actual functions were imported from the "sre" module. This becomes difficult if not impossible to get right for automatically generated modules. Pydoc for example requires __all__ to be defined in that module, otherwise it will hide those objects like it hides every other import. Another example which is pain in the ass to get right by automatic introspection are function decorators and descriptors. Descriptors also break in pydoc half of the time and nobody seems to know when exactly it breaks. Function decorators are impossible to get right because even if you try to traverse the closure variables of all the wrapped functions up to the original function the result could be terrible wrong because one function in the middle is indeed variadic. Because it's that hard to get right I don't want to lose time on solving something that's unsolvable anyways. My current idea to make the documentation process a little less annoying I think about adding directives to sphinx that pull information from python objects into rst files in a semiautomatic way. Say you have a pretty complex module that implements a couple of functions and classes and who knows what. Additionally to the documentation from the docstrings you also want to group the objects by topics and add hand written documentation for every group. In the python code you document all your functions with nice rst docstrings with the epydoc conventions. Additionally you add group markers: <!-- PYGMENTS_CACHE><div class="highlight"><pre><span class="k">def</span> <span class="nf">escape</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">quote</span><span class="o">=</span><span class="bp">False</span><span class="p">):</span> <span class="sd">&quot;&quot;&quot;This function escapes strings for HTML documents.</span> <span class="sd"> :param s: the string to escape</span> <span class="sd"> :param quote: set to `True` to escape the quote character too.</span> <span class="sd"> :return: escaped string</span> <span class="sd"> :group: html-helpers</span> <span class="sd"> &quot;&quot;&quot;</span><span class="s">&quot;</span> </pre></div> <PYGMENTS_CACHE --><!-- PYGMENTS_RAW(python)> def escape(s, quote=False): """This function escapes strings for HTML documents. :param s: the string to escape :param quote: set to `True` to escape the quote character too. :return: escaped string :group: html-helpers """"<PYGMENTS_RAW --> You can do that with every function and object. To dump the documentation for a group to an rst document you would then use a little directive: <!-- PYGMENTS_CACHE><div class="highlight"><pre><span class="gh">HTML Helpers</span> <span class="gh">============</span> These functions and classes help you process HTML. <span class="p">..</span> <span class="ow">autodoc</span><span class="p">::</span> <span class="k">group html-helpers [werkzeug.utils]</span> </pre></div> <PYGMENTS_CACHE --><!-- PYGMENTS_RAW(rst)> HTML Helpers ============ These functions and classes help you process HTML. .. autodoc:: group html-helpers [werkzeug.utils]<PYGMENTS_RAW --> This will dump all the objects flagged with that group in alphabetical order to the rst document. But of course this breaks for complex use cases you should be able to step back. Imagine you have a pretty complex object and you want to hide some of the methods / attributes, mark missing variables or make a member a descriptor rather than a method if the automatic discovery failed: <!-- PYGMENTS_CACHE><div class="highlight"><pre><span class="gh">Request</span> <span class="gh">=======</span> summary for the request object goes here. <span class="p">..</span> <span class="ow">autodoc</span><span class="p">::</span> <span class="k">object werkzeug.wrappers.Request</span> no_docstring: yes extra_members: <span class="m">-</span> <span class="nv">`_get_file_stream`</span> </pre></div> <PYGMENTS_CACHE --><!-- PYGMENTS_RAW(rst)> Request ======= summary for the request object goes here. .. autodoc:: object werkzeug.wrappers.Request no_docstring: yes extra_members: - `_get_file_stream`<PYGMENTS_RAW --> But how exactly that should work, I don't have a good idea yet. But I want to find it quickly because right now I'm pretty unhappy because writing docs both in the sourcecode and in hand written documentation sucks ass. <strong>Update:</strong> Fixed Georg's name :-)<a href="http://pyside.blogspot.com/2008/01/what-do-you-look-for-in-documentation.html">Georg blogged about sphinx</a> recently and now we can all rejoice because sphinx can now be used with custom documentation (non c-python documentation) too. Unfortunately hand written documentation alone is hard to maintain. For Werkzeug 0.2 I want to switch to a combination of hand written documentation and source documentation generated from python sourcecode, powered by sphinx of course. The main problem is getting the information out of the sourcecode. Unlike compiled languages in Python a lot is dynamic and much of the functionality is only available at runtime. Unlike PHP objects can be modified later on, and unlike Ruby there are attributes and methods on classes so it's hard to hide private/protected stuff on a class. epydoc came up with some conventions (especially for rst users) but introspection is still too hard in python and will lead to unexpected results. A pretty common idom in python is to implement a class in one file and import it to somewhere else, where it will become importable from. One of the best example was Python's "re" module. Until 2.5 that module was a stub and the actual functions were imported from the "sre" module. This becomes difficult if not impossible to get right for automatically generated modules. Pydoc for example requires __all__ to be defined in that module, otherwise it will hide those objects like it hides every other import. Another example which is pain in the ass to get right by automatic introspection are function decorators and descriptors. Descriptors also break in pydoc half of the time and nobody seems to know when exactly it breaks. Function decorators are impossible to get right because even if you try to traverse the closure variables of all the wrapped functions up to the original function the result could be terrible wrong because one function in the middle is indeed variadic. Because it's that hard to get right I don't want to lose time on solving something that's unsolvable anyways. My current idea to make the documentation process a little less annoying I think about adding directives to sphinx that pull information from python objects into rst files in a semiautomatic way. Say you have a pretty complex module that implements a couple of functions and classes and who knows what. Additionally to the documentation from the docstrings you also want to group the objects by topics and add hand written documentation for every group. In the python code you document all your functions with nice rst docstrings with the epydoc conventions. Additionally you add group markers: You can do that with every function and object. To dump the documentation for a group to an rst document you would then use a little directive: This will dump all the objects flagged with that group in alphabetical order to the rst document. But of course this breaks for complex use cases you should be able to step back. Imagine you have a pretty complex object and you want to hide some of the methods / attributes, mark missing variables or make a member a descriptor rather than a method if the automatic discovery failed: But how exactly that should work, I don't have a good idea yet. But I want to find it quickly because right now I'm pretty unhappy because writing docs both in the sourcecode and in hand written documentation sucks ass. <strong>Update:</strong> Fixed Georg's name :-)SQAAAANTAAAABGJvZHlSUwAAAABMAAJFUwAAAAFhTAAATQABUwAAAARocmVmUwAAAE1odHRwOi8v cHlzaWRlLmJsb2dzcG90LmNvbS8yMDA4LzAxL3doYXQtZG8teW91LWxvb2stZm9yLWluLWRvY3Vt ZW50YXRpb24uaHRtbFMAAAAaR2VvcmcgYmxvZ2dlZCBhYm91dCBzcGhpbnhTAAAM6iByZWNlbnRs eSBhbmQgbm93IHdlIGNhbiBhbGwgcmVqb2ljZSBiZWNhdXNlIHNwaGlueCBjYW4gbm93IGJlIHVz ZWQgd2l0aCBjdXN0b20gZG9jdW1lbnRhdGlvbiAobm9uIGMtcHl0aG9uIGRvY3VtZW50YXRpb24p IHRvby4gVW5mb3J0dW5hdGVseSBoYW5kIHdyaXR0ZW4gZG9jdW1lbnRhdGlvbiBhbG9uZSBpcyBo YXJkIHRvIG1haW50YWluLgoKRm9yIFdlcmt6ZXVnIDAuMiBJIHdhbnQgdG8gc3dpdGNoIHRvIGEg Y29tYmluYXRpb24gb2YgaGFuZCB3cml0dGVuIGRvY3VtZW50YXRpb24gYW5kIHNvdXJjZSBkb2N1 bWVudGF0aW9uIGdlbmVyYXRlZCBmcm9tIHB5dGhvbiBzb3VyY2Vjb2RlLCBwb3dlcmVkIGJ5IHNw aGlueCBvZiBjb3Vyc2UuIFRoZSBtYWluIHByb2JsZW0gaXMgZ2V0dGluZyB0aGUgaW5mb3JtYXRp b24gb3V0IG9mIHRoZSBzb3VyY2Vjb2RlLiBVbmxpa2UgY29tcGlsZWQgbGFuZ3VhZ2VzIGluIFB5 dGhvbiBhIGxvdCBpcyBkeW5hbWljIGFuZCBtdWNoIG9mIHRoZSBmdW5jdGlvbmFsaXR5IGlzIG9u bHkgYXZhaWxhYmxlIGF0IHJ1bnRpbWUuIFVubGlrZSBQSFAgb2JqZWN0cyBjYW4gYmUgbW9kaWZp ZWQgbGF0ZXIgb24sIGFuZCB1bmxpa2UgUnVieSB0aGVyZSBhcmUgYXR0cmlidXRlcyBhbmQgbWV0 aG9kcyBvbiBjbGFzc2VzIHNvIGl0J3MgaGFyZCB0byBoaWRlIHByaXZhdGUvcHJvdGVjdGVkIHN0 dWZmIG9uIGEgY2xhc3MuIGVweWRvYyBjYW1lIHVwIHdpdGggc29tZSBjb252ZW50aW9ucyAoZXNw ZWNpYWxseSBmb3IgcnN0IHVzZXJzKSBidXQgaW50cm9zcGVjdGlvbiBpcyBzdGlsbCB0b28gaGFy ZCBpbiBweXRob24gYW5kIHdpbGwgbGVhZCB0byB1bmV4cGVjdGVkIHJlc3VsdHMuCgpBIHByZXR0 eSBjb21tb24gaWRvbSBpbiBweXRob24gaXMgdG8gaW1wbGVtZW50IGEgY2xhc3MgaW4gb25lIGZp bGUgYW5kIGltcG9ydCBpdCB0byBzb21ld2hlcmUgZWxzZSwgd2hlcmUgaXQgd2lsbCBiZWNvbWUg aW1wb3J0YWJsZSBmcm9tLiBPbmUgb2YgdGhlIGJlc3QgZXhhbXBsZSB3YXMgUHl0aG9uJ3MgInJl IiBtb2R1bGUuIFVudGlsIDIuNSB0aGF0IG1vZHVsZSB3YXMgYSBzdHViIGFuZCB0aGUgYWN0dWFs IGZ1bmN0aW9ucyB3ZXJlIGltcG9ydGVkIGZyb20gdGhlICJzcmUiIG1vZHVsZS4gVGhpcyBiZWNv bWVzIGRpZmZpY3VsdCBpZiBub3QgaW1wb3NzaWJsZSB0byBnZXQgcmlnaHQgZm9yIGF1dG9tYXRp Y2FsbHkgZ2VuZXJhdGVkIG1vZHVsZXMuIFB5ZG9jIGZvciBleGFtcGxlIHJlcXVpcmVzIF9fYWxs X18gdG8gYmUgZGVmaW5lZCBpbiB0aGF0IG1vZHVsZSwgb3RoZXJ3aXNlIGl0IHdpbGwgaGlkZSB0 aG9zZSBvYmplY3RzIGxpa2UgaXQgaGlkZXMgZXZlcnkgb3RoZXIgaW1wb3J0LgoKQW5vdGhlciBl eGFtcGxlIHdoaWNoIGlzIHBhaW4gaW4gdGhlIGFzcyB0byBnZXQgcmlnaHQgYnkgYXV0b21hdGlj IGludHJvc3BlY3Rpb24gYXJlIGZ1bmN0aW9uIGRlY29yYXRvcnMgYW5kIGRlc2NyaXB0b3JzLiBE ZXNjcmlwdG9ycyBhbHNvIGJyZWFrIGluIHB5ZG9jIGhhbGYgb2YgdGhlIHRpbWUgYW5kIG5vYm9k eSBzZWVtcyB0byBrbm93IHdoZW4gZXhhY3RseSBpdCBicmVha3MuIEZ1bmN0aW9uIGRlY29yYXRv cnMgYXJlIGltcG9zc2libGUgdG8gZ2V0IHJpZ2h0IGJlY2F1c2UgZXZlbiBpZiB5b3UgdHJ5IHRv IHRyYXZlcnNlIHRoZSBjbG9zdXJlIHZhcmlhYmxlcyBvZiBhbGwgdGhlIHdyYXBwZWQgZnVuY3Rp b25zIHVwIHRvIHRoZSBvcmlnaW5hbCBmdW5jdGlvbiB0aGUgcmVzdWx0IGNvdWxkIGJlIHRlcnJp YmxlIHdyb25nIGJlY2F1c2Ugb25lIGZ1bmN0aW9uIGluIHRoZSBtaWRkbGUgaXMgaW5kZWVkIHZh cmlhZGljLgoKQmVjYXVzZSBpdCdzIHRoYXQgaGFyZCB0byBnZXQgcmlnaHQgSSBkb24ndCB3YW50 IHRvIGxvc2UgdGltZSBvbiBzb2x2aW5nIHNvbWV0aGluZyB0aGF0J3MgdW5zb2x2YWJsZSBhbnl3 YXlzLiBNeSBjdXJyZW50IGlkZWEgdG8gbWFrZSB0aGUgZG9jdW1lbnRhdGlvbiBwcm9jZXNzIGEg bGl0dGxlIGxlc3MgYW5ub3lpbmcgSSB0aGluayBhYm91dCBhZGRpbmcgZGlyZWN0aXZlcyB0byBz cGhpbnggdGhhdCBwdWxsIGluZm9ybWF0aW9uIGZyb20gcHl0aG9uIG9iamVjdHMgaW50byByc3Qg ZmlsZXMgaW4gYSBzZW1pYXV0b21hdGljIHdheS4KClNheSB5b3UgaGF2ZSBhIHByZXR0eSBjb21w bGV4IG1vZHVsZSB0aGF0IGltcGxlbWVudHMgYSBjb3VwbGUgb2YgZnVuY3Rpb25zIGFuZCBjbGFz c2VzIGFuZCB3aG8ga25vd3Mgd2hhdC4gQWRkaXRpb25hbGx5IHRvIHRoZSBkb2N1bWVudGF0aW9u IGZyb20gdGhlIGRvY3N0cmluZ3MgeW91IGFsc28gd2FudCB0byBncm91cCB0aGUgb2JqZWN0cyBi eSB0b3BpY3MgYW5kIGFkZCBoYW5kIHdyaXR0ZW4gZG9jdW1lbnRhdGlvbiBmb3IgZXZlcnkgZ3Jv dXAuCgpJbiB0aGUgcHl0aG9uIGNvZGUgeW91IGRvY3VtZW50IGFsbCB5b3VyIGZ1bmN0aW9ucyB3 aXRoIG5pY2UgcnN0IGRvY3N0cmluZ3Mgd2l0aCB0aGUgZXB5ZG9jIGNvbnZlbnRpb25zLiBBZGRp dGlvbmFsbHkgeW91IGFkZCBncm91cCBtYXJrZXJzOgoKCgpZb3UgY2FuIGRvIHRoYXQgd2l0aCBl dmVyeSBmdW5jdGlvbiBhbmQgb2JqZWN0LiBUbyBkdW1wIHRoZSBkb2N1bWVudGF0aW9uIGZvciBh IGdyb3VwIHRvIGFuIHJzdCBkb2N1bWVudCB5b3Ugd291bGQgdGhlbiB1c2UgYSBsaXR0bGUgZGly ZWN0aXZlOgoKCgpUaGlzIHdpbGwgZHVtcCBhbGwgdGhlIG9iamVjdHMgZmxhZ2dlZCB3aXRoIHRo YXQgZ3JvdXAgaW4gYWxwaGFiZXRpY2FsIG9yZGVyIHRvIHRoZSByc3QgZG9jdW1lbnQuIEJ1dCBv ZiBjb3Vyc2UgdGhpcyBicmVha3MgZm9yIGNvbXBsZXggdXNlIGNhc2VzIHlvdSBzaG91bGQgYmUg YWJsZSB0byBzdGVwIGJhY2suIEltYWdpbmUgeW91IGhhdmUgYSBwcmV0dHkgY29tcGxleCBvYmpl Y3QgYW5kIHlvdSB3YW50IHRvIGhpZGUgc29tZSBvZiB0aGUgbWV0aG9kcyAvIGF0dHJpYnV0ZXMs IG1hcmsgbWlzc2luZyB2YXJpYWJsZXMgb3IgbWFrZSBhIG1lbWJlciBhIGRlc2NyaXB0b3IgcmF0 aGVyIHRoYW4gYSBtZXRob2QgaWYgdGhlIGF1dG9tYXRpYyBkaXNjb3ZlcnkgZmFpbGVkOgoKCgpC dXQgaG93IGV4YWN0bHkgdGhhdCBzaG91bGQgd29yaywgSSBkb24ndCBoYXZlIGEgZ29vZCBpZGVh IHlldC4gQnV0IEkgd2FudCB0byBmaW5kIGl0IHF1aWNrbHkgYmVjYXVzZSByaWdodCBub3cgSSdt IHByZXR0eSB1bmhhcHB5IGJlY2F1c2Ugd3JpdGluZyBkb2NzIGJvdGggaW4gdGhlIHNvdXJjZWNv ZGUgYW5kIGluIGhhbmQgd3JpdHRlbiBkb2N1bWVudGF0aW9uIHN1Y2tzIGFzcy4KCkVTAAAABnN0 cm9uZ0wAAE0AAFMAAAAHVXBkYXRlOlMAAAAXIEZpeGVkIEdlb3JnJ3MgbmFtZSA6LSlTAAAABnBh cnNlclMAAAAEaHRtbFMAAAAFaW50cm9SUwAAAABMAAA= Georggeorg@python.org2008-01-21T22:06:30Znono0This proposal is certainly a good one. The exact syntax might be different (e.g. using directive options for "no_docstring" etc.). I hope it is easily implementable as a Sphinx extension. The combination of hand-written docs and docstrings where they make sense is something that ensures up-to-date documentation that is nice to read, not fragmented like many API docs.This proposal is certainly a good one. The exact syntax might be different (e.g. using directive options for "no_docstring" etc.). I hope it is easily implementable as a Sphinx extension. The combination of hand-written docs and docstrings where they make sense is something that ensures up-to-date documentation that is nice to read, not fragmented like many API docs.SQAAAAJTAAAABGJvZHlSUwAAAXJUaGlzIHByb3Bvc2FsIGlzIGNlcnRhaW5seSBhIGdvb2Qgb25l LiBUaGUgZXhhY3Qgc3ludGF4IG1pZ2h0IGJlIGRpZmZlcmVudCAoZS5nLiB1c2luZyBkaXJlY3Rp dmUgb3B0aW9ucyBmb3IgIm5vX2RvY3N0cmluZyIgZXRjLikuIEkgaG9wZSBpdCBpcyBlYXNpbHkg aW1wbGVtZW50YWJsZSBhcyBhIFNwaGlueCBleHRlbnNpb24uCgpUaGUgY29tYmluYXRpb24gb2Yg aGFuZC13cml0dGVuIGRvY3MgYW5kIGRvY3N0cmluZ3Mgd2hlcmUgdGhleSBtYWtlIHNlbnNlIGlz IHNvbWV0aGluZyB0aGF0IGVuc3VyZXMgdXAtdG8tZGF0ZSBkb2N1bWVudGF0aW9uIHRoYXQgaXMg bmljZSB0byByZWFkLCBub3QgZnJhZ21lbnRlZCBsaWtlIG1hbnkgQVBJIGRvY3MuTAAAUwAAAAZw YXJzZXJTAAAABGh0bWw= Error Reporting in WSGI Applicationshttp://lucumr.pocoo.org/cogitations/2008/01/18/error-reporting-in-wsgi-applications/2008-01-18T14:15:22Z2008-01-18T14:15:22ZArmin Ronachererror-reporting-in-wsgi-applicationsyesyes2Thanks to an google alert on "pygments" I stumbled accross gluon/web2py, some sort of "enterprise ready framework". It's definitively not a framework I would use myself for countless reasons but there is one thing on the feature list which I found interesting. Apparently gluon files tickets for tracebacks in the database. While it's a terrible idea to put that data into the very same database all your application data goes (what happens if the DB is down?) it's a different approach to Django which sends mails on errors. Two days ago someone mentioned the paste WSGI middleware which sends emails on tracebacks, similar to the way Django does that. I'm not a fan of error reporting middlewares because I think that should go into the application. On an server error (caused by lost database connections, programmer errors etc.) you should not present the user a black-and-white error page or display an inline traceback like most PHP applications do. We can do better! First of all there is a module in the standard library everybody seems to forget about. It's called "logging" and does exactly that --- it logs errors. I don't know why so many people miss it or just don't use it, but it's really one of the good things in the python standard library. Why is it so good? It's extensible and configurable. The idea is that the application gets itself a logger and logs into that logger (debug messages, information messages, warnings, errors or tracebacks). Independently from the logging there are logger handlers which do something with the logged messages. For example you can tell the logger to log everything except of debug output into a rotated file and mail all errors to some mail addresses. In the Werkzeug wiki there is a <a href="http://dev.pocoo.org/projects/werkzeug/wiki/ErrorHandlingInProduction">wiki page about error handling</a> in WSGI applications using the logger module. Total amount of code needed for a simple WSGI application with logging is about ten lines or so. And it's flexible enough to integrate in every WSGI application setup, no need to solve that in a middleware where you don't have access to your application's config or whatever. And the best thing about it is that you can configure the way errors are handled. Like I mentioned before gluon creates entries in the database for logged errors. I wrote a small logger handler that does the same but for an external trac. Whenever an application error occours the logger checks if there is already a ticket for that error, if not it creates one. For every new occurrence of that bug it will create a comment in that ticket. If you want to try it out yourself, I added the code to the <a href="http://dev.pocoo.org/hg/sandbox/raw-file/tip/trachandler.py">sandbox repository</a>. <strong>Update:</strong> I also created a <a href="http://trac-hacks.org/wiki/PythonTracLogHandlerIntegration">trac hack</a> for it.Thanks to an google alert on "pygments" I stumbled accross gluon/web2py, some sort of "enterprise ready framework". It's definitively not a framework I would use myself for countless reasons but there is one thing on the feature list which I found interesting. Apparently gluon files tickets for tracebacks in the database. While it's a terrible idea to put that data into the very same database all your application data goes (what happens if the DB is down?) it's a different approach to Django which sends mails on errors. Two days ago someone mentioned the paste WSGI middleware which sends emails on tracebacks, similar to the way Django does that. I'm not a fan of error reporting middlewares because I think that should go into the application. On an server error (caused by lost database connections, programmer errors etc.) you should not present the user a black-and-white error page or display an inline traceback like most PHP applications do. We can do better! First of all there is a module in the standard library everybody seems to forget about. It's called "logging" and does exactly that --- it logs errors. I don't know why so many people miss it or just don't use it, but it's really one of the good things in the python standard library. Why is it so good? It's extensible and configurable. The idea is that the application gets itself a logger and logs into that logger (debug messages, information messages, warnings, errors or tracebacks). Independently from the logging there are logger handlers which do something with the logged messages. For example you can tell the logger to log everything except of debug output into a rotated file and mail all errors to some mail addresses. In the Werkzeug wiki there is a <a href="http://dev.pocoo.org/projects/werkzeug/wiki/ErrorHandlingInProduction">wiki page about error handling</a> in WSGI applications using the logger module. Total amount of code needed for a simple WSGI application with logging is about ten lines or so. And it's flexible enough to integrate in every WSGI application setup, no need to solve that in a middleware where you don't have access to your application's config or whatever. And the best thing about it is that you can configure the way errors are handled. Like I mentioned before gluon creates entries in the database for logged errors. I wrote a small logger handler that does the same but for an external trac. Whenever an application error occours the logger checks if there is already a ticket for that error, if not it creates one. For every new occurrence of that bug it will create a comment in that ticket. If you want to try it out yourself, I added the code to the <a href="http://dev.pocoo.org/hg/sandbox/raw-file/tip/trachandler.py">sandbox repository</a>. <strong>Update:</strong> I also created a <a href="http://trac-hacks.org/wiki/PythonTracLogHandlerIntegration">trac hack</a> for it.SQAAAANTAAAABGJvZHlSUwAABttUaGFua3MgdG8gYW4gZ29vZ2xlIGFsZXJ0IG9uICJweWdtZW50 cyIgSSBzdHVtYmxlZCBhY2Nyb3NzIGdsdW9uL3dlYjJweSwgc29tZSBzb3J0IG9mICJlbnRlcnBy aXNlIHJlYWR5IGZyYW1ld29yayIuICAgSXQncyBkZWZpbml0aXZlbHkgbm90IGEgZnJhbWV3b3Jr IEkgd291bGQgdXNlIG15c2VsZiBmb3IgY291bnRsZXNzIHJlYXNvbnMgYnV0IHRoZXJlIGlzIG9u ZSB0aGluZyBvbiB0aGUgZmVhdHVyZSBsaXN0IHdoaWNoIEkgZm91bmQgaW50ZXJlc3RpbmcuICBB cHBhcmVudGx5IGdsdW9uIGZpbGVzIHRpY2tldHMgZm9yIHRyYWNlYmFja3MgaW4gdGhlIGRhdGFi YXNlLiAgV2hpbGUgaXQncyBhIHRlcnJpYmxlIGlkZWEgdG8gcHV0IHRoYXQgZGF0YSBpbnRvIHRo ZSB2ZXJ5IHNhbWUgZGF0YWJhc2UgYWxsIHlvdXIgYXBwbGljYXRpb24gZGF0YSBnb2VzICh3aGF0 IGhhcHBlbnMgaWYgdGhlIERCIGlzIGRvd24/KSBpdCdzIGEgZGlmZmVyZW50IGFwcHJvYWNoIHRv IERqYW5nbyB3aGljaCBzZW5kcyBtYWlscyBvbiBlcnJvcnMuCgpUd28gZGF5cyBhZ28gc29tZW9u ZSBtZW50aW9uZWQgdGhlIHBhc3RlIFdTR0kgbWlkZGxld2FyZSB3aGljaCBzZW5kcyBlbWFpbHMg b24gdHJhY2ViYWNrcywgc2ltaWxhciB0byB0aGUgd2F5IERqYW5nbyBkb2VzIHRoYXQuICBJJ20g bm90IGEgZmFuIG9mIGVycm9yIHJlcG9ydGluZyBtaWRkbGV3YXJlcyBiZWNhdXNlIEkgdGhpbmsg dGhhdCBzaG91bGQgZ28gaW50byB0aGUgYXBwbGljYXRpb24uICBPbiBhbiBzZXJ2ZXIgZXJyb3Ig KGNhdXNlZCBieSBsb3N0IGRhdGFiYXNlIGNvbm5lY3Rpb25zLCBwcm9ncmFtbWVyIGVycm9ycyBl dGMuKSB5b3Ugc2hvdWxkIG5vdCBwcmVzZW50IHRoZSB1c2VyIGEgYmxhY2stYW5kLXdoaXRlIGVy cm9yIHBhZ2Ugb3IgZGlzcGxheSBhbiBpbmxpbmUgdHJhY2ViYWNrIGxpa2UgbW9zdCBQSFAgYXBw bGljYXRpb25zIGRvLiAgV2UgY2FuIGRvIGJldHRlciEKCkZpcnN0IG9mIGFsbCB0aGVyZSBpcyBh IG1vZHVsZSBpbiB0aGUgc3RhbmRhcmQgbGlicmFyeSBldmVyeWJvZHkgc2VlbXMgdG8gZm9yZ2V0 IGFib3V0LiAgSXQncyBjYWxsZWQgImxvZ2dpbmciIGFuZCBkb2VzIGV4YWN0bHkgdGhhdCAtLS0g aXQgbG9ncyBlcnJvcnMuIEkgZG9uJ3Qga25vdyB3aHkgc28gbWFueSBwZW9wbGUgbWlzcyBpdCBv ciBqdXN0IGRvbid0IHVzZSBpdCwgYnV0IGl0J3MgcmVhbGx5IG9uZSBvZiB0aGUgZ29vZCB0aGlu Z3MgaW4gdGhlIHB5dGhvbiBzdGFuZGFyZCBsaWJyYXJ5LgoKV2h5IGlzIGl0IHNvIGdvb2Q/ICBJ dCdzIGV4dGVuc2libGUgYW5kIGNvbmZpZ3VyYWJsZS4gIFRoZSBpZGVhIGlzIHRoYXQgdGhlIGFw cGxpY2F0aW9uIGdldHMgaXRzZWxmIGEgbG9nZ2VyIGFuZCBsb2dzIGludG8gdGhhdCBsb2dnZXIg KGRlYnVnIG1lc3NhZ2VzLCBpbmZvcm1hdGlvbiBtZXNzYWdlcywgd2FybmluZ3MsIGVycm9ycyBv ciB0cmFjZWJhY2tzKS4gIEluZGVwZW5kZW50bHkgZnJvbSB0aGUgbG9nZ2luZyB0aGVyZSBhcmUg bG9nZ2VyIGhhbmRsZXJzIHdoaWNoIGRvIHNvbWV0aGluZyB3aXRoIHRoZSBsb2dnZWQgbWVzc2Fn ZXMuICBGb3IgZXhhbXBsZSB5b3UgY2FuIHRlbGwgdGhlIGxvZ2dlciB0byBsb2cgZXZlcnl0aGlu ZyBleGNlcHQgb2YgZGVidWcgb3V0cHV0IGludG8gYSByb3RhdGVkIGZpbGUgYW5kIG1haWwgYWxs IGVycm9ycyB0byBzb21lIG1haWwgYWRkcmVzc2VzLgoKSW4gdGhlIFdlcmt6ZXVnIHdpa2kgdGhl cmUgaXMgYSBMAARFUwAAAAFhTAAATQABUwAAAARocmVmUwAAAEVodHRwOi8vZGV2LnBvY29vLm9y Zy9wcm9qZWN0cy93ZXJremV1Zy93aWtpL0Vycm9ySGFuZGxpbmdJblByb2R1Y3Rpb25TAAAAHndp a2kgcGFnZSBhYm91dCBlcnJvciBoYW5kbGluZ1MAAANAIGluIFdTR0kgYXBwbGljYXRpb25zIHVz aW5nIHRoZSBsb2dnZXIgbW9kdWxlLiAgVG90YWwgYW1vdW50IG9mIGNvZGUgbmVlZGVkIGZvciBh IHNpbXBsZSBXU0dJIGFwcGxpY2F0aW9uIHdpdGggbG9nZ2luZyBpcyBhYm91dCB0ZW4gbGluZXMg b3Igc28uICBBbmQgaXQncyBmbGV4aWJsZSBlbm91Z2ggdG8gaW50ZWdyYXRlIGluIGV2ZXJ5IFdT R0kgYXBwbGljYXRpb24gc2V0dXAsIG5vIG5lZWQgdG8gc29sdmUgdGhhdCBpbiBhIG1pZGRsZXdh cmUgd2hlcmUgeW91IGRvbid0IGhhdmUgYWNjZXNzIHRvIHlvdXIgYXBwbGljYXRpb24ncyBjb25m aWcgb3Igd2hhdGV2ZXIuCgpBbmQgdGhlIGJlc3QgdGhpbmcgYWJvdXQgaXQgaXMgdGhhdCB5b3Ug Y2FuIGNvbmZpZ3VyZSB0aGUgd2F5IGVycm9ycyBhcmUgaGFuZGxlZC4gIExpa2UgSSBtZW50aW9u ZWQgYmVmb3JlIGdsdW9uIGNyZWF0ZXMgZW50cmllcyBpbiB0aGUgZGF0YWJhc2UgZm9yIGxvZ2dl ZCBlcnJvcnMuICBJIHdyb3RlIGEgc21hbGwgbG9nZ2VyIGhhbmRsZXIgdGhhdCBkb2VzIHRoZSBz YW1lIGJ1dCBmb3IgYW4gZXh0ZXJuYWwgdHJhYy4gIFdoZW5ldmVyIGFuIGFwcGxpY2F0aW9uIGVy cm9yIG9jY291cnMgdGhlIGxvZ2dlciBjaGVja3MgaWYgdGhlcmUgaXMgYWxyZWFkeSBhIHRpY2tl dCBmb3IgdGhhdCBlcnJvciwgaWYgbm90IGl0IGNyZWF0ZXMgb25lLiAgRm9yIGV2ZXJ5IG5ldyBv Y2N1cnJlbmNlIG9mIHRoYXQgYnVnIGl0IHdpbGwgY3JlYXRlIGEgY29tbWVudCBpbiB0aGF0IHRp Y2tldC4KCklmIHlvdSB3YW50IHRvIHRyeSBpdCBvdXQgeW91cnNlbGYsIEkgYWRkZWQgdGhlIGNv ZGUgdG8gdGhlIEVTAAAAAWFMAABNAAFTAAAABGhyZWZTAAAAO2h0dHA6Ly9kZXYucG9jb28ub3Jn L2hnL3NhbmRib3gvcmF3LWZpbGUvdGlwL3RyYWNoYW5kbGVyLnB5UwAAABJzYW5kYm94IHJlcG9z aXRvcnlTAAAAAy4KCkVTAAAABnN0cm9uZ0wAAE0AAFMAAAAHVXBkYXRlOlMAAAASIEkgYWxzbyBj cmVhdGVkIGEgRVMAAAABYUwAAE0AAVMAAAAEaHJlZlMAAAA6aHR0cDovL3RyYWMtaGFja3Mub3Jn L3dpa2kvUHl0aG9uVHJhY0xvZ0hhbmRsZXJJbnRlZ3JhdGlvblMAAAAJdHJhYyBoYWNrUwAAAAgg Zm9yIGl0LlMAAAAGcGFyc2VyUwAAAARodG1sUwAAAAVpbnRyb1JTAAAAAEwAAA== Robert Brewerfumanchu@aminus.orghttp://www.aminus.org/blogs/index.php/fumanchu2008-01-18T23:02:14Znono0&gt; I don’t know why so many people miss it or just don’t use it... &gt; Why is it so good? It’s extensible and configurable. That's also why it's so bad: it's so extensible and configurable that's it's far too slow for high-performance websites. So please, when you make the latest and greatest web framework, go ahead and add support for the logging module, go ahead and make it the default, but make it easily overridable at the same time.&gt; I don’t know why so many people miss it or just don’t use it... &gt; Why is it so good? It’s extensible and configurable. That's also why it's so bad: it's so extensible and configurable that's it's far too slow for high-performance websites. So please, when you make the latest and greatest web framework, go ahead and add support for the logging module, go ahead and make it the default, but make it easily overridable at the same time.SQAAAAJTAAAABGJvZHlSUwAAAbw+IEkgZG9u4oCZdCBrbm93IHdoeSBzbyBtYW55IHBlb3BsZSBt aXNzIGl0IG9yIGp1c3QgZG9u4oCZdCB1c2UgaXQuLi4KPiBXaHkgaXMgaXQgc28gZ29vZD8gSXTi gJlzIGV4dGVuc2libGUgYW5kIGNvbmZpZ3VyYWJsZS4KClRoYXQncyBhbHNvIHdoeSBpdCdzIHNv IGJhZDogaXQncyBzbyBleHRlbnNpYmxlIGFuZCBjb25maWd1cmFibGUgdGhhdCdzIGl0J3MgZmFy IHRvbyBzbG93IGZvciBoaWdoLXBlcmZvcm1hbmNlIHdlYnNpdGVzLiBTbyBwbGVhc2UsIHdoZW4g eW91IG1ha2UgdGhlIGxhdGVzdCBhbmQgZ3JlYXRlc3Qgd2ViIGZyYW1ld29yaywgZ28gYWhlYWQg YW5kIGFkZCBzdXBwb3J0IGZvciB0aGUgbG9nZ2luZyBtb2R1bGUsIGdvIGFoZWFkIGFuZCBtYWtl IGl0IHRoZSBkZWZhdWx0LCBidXQgbWFrZSBpdCBlYXNpbHkgb3ZlcnJpZGFibGUgYXQgdGhlIHNh bWUgdGltZS5MAABTAAAABnBhcnNlclMAAAAEaHRtbA== Armin Ronacherarmin.ronacher@active-4.comhttp://lucumr.pocoo.org/2008-01-19T00:38:36Znono0That's very true. But in a production environment the calls to the actual logger can be reduced to the cases where you actually log an error or exception. For example you can create methods for log / info / warn or whatever and if __debug__ is False you replace them with a no-op lambda. My point with that post was mostly to not reinvent exception reporting when the stdlib can do that. And that one logger.exception call in the very last except of your WSGI application won't harm the performance of the application at all.That's very true. But in a production environment the calls to the actual logger can be reduced to the cases where you actually log an error or exception. For example you can create methods for log / info / warn or whatever and if __debug__ is False you replace them with a no-op lambda. My point with that post was mostly to not reinvent exception reporting when the stdlib can do that. And that one logger.exception call in the very last except of your WSGI application won't harm the performance of the application at all.SQAAAAJTAAAABGJvZHlSUwAAAg5UaGF0J3MgdmVyeSB0cnVlLiBCdXQgaW4gYSBwcm9kdWN0aW9u IGVudmlyb25tZW50IHRoZSBjYWxscyB0byB0aGUgYWN0dWFsIGxvZ2dlciBjYW4gYmUgcmVkdWNl ZCB0byB0aGUgY2FzZXMgd2hlcmUgeW91IGFjdHVhbGx5IGxvZyBhbiBlcnJvciBvciBleGNlcHRp b24uIEZvciBleGFtcGxlIHlvdSBjYW4gY3JlYXRlIG1ldGhvZHMgZm9yIGxvZyAvIGluZm8gLyB3 YXJuIG9yIHdoYXRldmVyIGFuZCBpZiBfX2RlYnVnX18gaXMgRmFsc2UgeW91IHJlcGxhY2UgdGhl bSB3aXRoIGEgbm8tb3AgbGFtYmRhLgoKTXkgcG9pbnQgd2l0aCB0aGF0IHBvc3Qgd2FzIG1vc3Rs eSB0byBub3QgcmVpbnZlbnQgZXhjZXB0aW9uIHJlcG9ydGluZyB3aGVuIHRoZSBzdGRsaWIgY2Fu IGRvIHRoYXQuIEFuZCB0aGF0IG9uZSBsb2dnZXIuZXhjZXB0aW9uIGNhbGwgaW4gdGhlIHZlcnkg bGFzdCBleGNlcHQgb2YgeW91ciBXU0dJIGFwcGxpY2F0aW9uIHdvbid0IGhhcm0gdGhlIHBlcmZv cm1hbmNlIG9mIHRoZSBhcHBsaWNhdGlvbiBhdCBhbGwuTAAAUwAAAAZwYXJzZXJTAAAABGh0bWw= Georggeorg@python.org2008-01-19T09:41:16Znono0BTW, the documentation for logging has recently been enhanced by a tutorial section, thanks to a GHOP student, see <a href="http://docs.python.org/dev/library/logging" rel="nofollow">http://docs.python.org/dev/library/logging</a>.BTW, the documentation for logging has recently been enhanced by a tutorial section, thanks to a GHOP student, see <a href="http://docs.python.org/dev/library/logging" rel="nofollow">http://docs.python.org/dev/library/logging</a>.SQAAAAJTAAAABGJvZHlSUwAAAHNCVFcsIHRoZSBkb2N1bWVudGF0aW9uIGZvciBsb2dnaW5nIGhh cyByZWNlbnRseSBiZWVuIGVuaGFuY2VkIGJ5IGEgdHV0b3JpYWwgc2VjdGlvbiwgdGhhbmtzIHRv IGEgR0hPUCBzdHVkZW50LCBzZWUgTAABRVMAAAABYUwAAE0AAlMAAAAEaHJlZlMAAAAqaHR0cDov L2RvY3MucHl0aG9uLm9yZy9kZXYvbGlicmFyeS9sb2dnaW5nUwAAAANyZWxTAAAACG5vZm9sbG93 UwAAACpodHRwOi8vZG9jcy5weXRob24ub3JnL2Rldi9saWJyYXJ5L2xvZ2dpbmdTAAAAAS5TAAAA BnBhcnNlclMAAAAEaHRtbA== Massimomdipierro@cs.depaul.eduhttp://www.web2py.com2008-01-20T06:46:52Znono0I would like to make two corrections: 1) You say that web2py "files tickets for tracebacks in the database". No. web2py files tickets for any error that occurs and that is not explicitly catched by the application, including db tracebacks. 2) You also say "it’s a terrible idea to put that data into the very same database all your application data goes (what happens if the DB is down?" I agree and web2py in fact does not do that. web2py tickets are stored in files and they can be accessed even if the db is down. Every app has its own seperate ticketing system provided by web2py. You also say that you would not use web2py for countless reasons. It would be helpful if you were to list those reasons. Perhaps some of them are consequence of misinformation and I could try convince you that, in fact, you should use web2py. ;-) One common misconception is to assume limitations because of the GPL license. If you read the web2py license carefully, as long as you do not copy web2py code into your web2py app web2py makes no claims on your app and you can even distribute it in closed form (something that web2py builds for you) and charge for it.I would like to make two corrections: 1) You say that web2py "files tickets for tracebacks in the database". No. web2py files tickets for any error that occurs and that is not explicitly catched by the application, including db tracebacks. 2) You also say "it’s a terrible idea to put that data into the very same database all your application data goes (what happens if the DB is down?" I agree and web2py in fact does not do that. web2py tickets are stored in files and they can be accessed even if the db is down. Every app has its own seperate ticketing system provided by web2py. You also say that you would not use web2py for countless reasons. It would be helpful if you were to list those reasons. Perhaps some of them are consequence of misinformation and I could try convince you that, in fact, you should use web2py. ;-) One common misconception is to assume limitations because of the GPL license. If you read the web2py license carefully, as long as you do not copy web2py code into your web2py app web2py makes no claims on your app and you can even distribute it in closed form (something that web2py builds for you) and charge for it.SQAAAAJTAAAABGJvZHlSUwAABIJJIHdvdWxkIGxpa2UgdG8gbWFrZSB0d28gY29ycmVjdGlvbnM6 IDEpIFlvdSBzYXkgdGhhdCB3ZWIycHkgImZpbGVzIHRpY2tldHMgZm9yIHRyYWNlYmFja3MgaW4g dGhlIGRhdGFiYXNlIi4gTm8uIHdlYjJweSBmaWxlcyB0aWNrZXRzIGZvciBhbnkgZXJyb3IgdGhh dCBvY2N1cnMgYW5kIHRoYXQgaXMgbm90IGV4cGxpY2l0bHkgY2F0Y2hlZCBieSB0aGUgYXBwbGlj YXRpb24sIGluY2x1ZGluZyBkYiB0cmFjZWJhY2tzLiAyKSBZb3UgYWxzbyBzYXkgIml04oCZcyBh IHRlcnJpYmxlIGlkZWEgdG8gcHV0IHRoYXQgZGF0YSBpbnRvIHRoZSB2ZXJ5IHNhbWUgZGF0YWJh c2UgYWxsIHlvdXIgYXBwbGljYXRpb24gZGF0YSBnb2VzICh3aGF0IGhhcHBlbnMgaWYgdGhlIERC IGlzIGRvd24/IiBJIGFncmVlIGFuZCB3ZWIycHkgaW4gZmFjdCBkb2VzIG5vdCBkbyB0aGF0LiB3 ZWIycHkgdGlja2V0cyBhcmUgc3RvcmVkIGluIGZpbGVzIGFuZCB0aGV5IGNhbiBiZSBhY2Nlc3Nl ZCBldmVuIGlmIHRoZSBkYiBpcyBkb3duLiBFdmVyeSBhcHAgaGFzIGl0cyBvd24gc2VwZXJhdGUg dGlja2V0aW5nIHN5c3RlbSBwcm92aWRlZCBieSB3ZWIycHkuCgpZb3UgYWxzbyBzYXkgdGhhdCB5 b3Ugd291bGQgbm90IHVzZSB3ZWIycHkgZm9yIGNvdW50bGVzcyByZWFzb25zLiBJdCB3b3VsZCBi ZSBoZWxwZnVsIGlmIHlvdSB3ZXJlIHRvIGxpc3QgdGhvc2UgcmVhc29ucy4gUGVyaGFwcyBzb21l IG9mIHRoZW0gYXJlIGNvbnNlcXVlbmNlIG9mIG1pc2luZm9ybWF0aW9uIGFuZCBJIGNvdWxkIHRy eSBjb252aW5jZSB5b3UgdGhhdCwgaW4gZmFjdCwgeW91IHNob3VsZCB1c2Ugd2ViMnB5LiA7LSkK Ck9uZSBjb21tb24gbWlzY29uY2VwdGlvbiBpcyB0byBhc3N1bWUgbGltaXRhdGlvbnMgYmVjYXVz ZSBvZiB0aGUgR1BMIGxpY2Vuc2UuIElmIHlvdSByZWFkIHRoZSB3ZWIycHkgbGljZW5zZSBjYXJl ZnVsbHksIGFzIGxvbmcgYXMgeW91IGRvIG5vdCBjb3B5IHdlYjJweSBjb2RlIGludG8geW91ciB3 ZWIycHkgYXBwIHdlYjJweSBtYWtlcyBubyBjbGFpbXMgb24geW91ciBhcHAgYW5kIHlvdSBjYW4g ZXZlbiBkaXN0cmlidXRlIGl0IGluIGNsb3NlZCBmb3JtIChzb21ldGhpbmcgdGhhdCB3ZWIycHkg YnVpbGRzIGZvciB5b3UpIGFuZCBjaGFyZ2UgZm9yIGl0LkwAAFMAAAAGcGFyc2VyUwAAAARodG1s Massimomdipierro@cs.depaul.eduhttp://www.web2py.com2008-01-20T07:09:18Znono0... another misconception about web2py is that you have to use the web interface for development and for database administration. You can but you are not forced to.... another misconception about web2py is that you have to use the web interface for development and for database administration. You can but you are not forced to.SQAAAAJTAAAABGJvZHlSUwAAAKQuLi4gYW5vdGhlciBtaXNjb25jZXB0aW9uIGFib3V0IHdlYjJw eSBpcyB0aGF0IHlvdSBoYXZlIHRvIHVzZSB0aGUgd2ViIGludGVyZmFjZSBmb3IgZGV2ZWxvcG1l bnQgYW5kIGZvciBkYXRhYmFzZSBhZG1pbmlzdHJhdGlvbi4gWW91IGNhbiBidXQgeW91IGFyZSBu b3QgZm9yY2VkIHRvLkwAAFMAAAAGcGFyc2VyUwAAAARodG1s Armin Ronacherarmin.ronacher@active-4.comhttp://lucumr.pocoo.org/2008-01-21T19:22:11Znono0In general I'm not a framework lover, even though I'm happy Django user. Mainly because I have a couple of use cases I can solve with Django and because the Django developers do a very good job at keeping the source clean, readable and maintained. When I looked at the web2py sources I stopped looking at it pretty soon when I found out that it's bypassing the python import system for controllers and models, that it comes in a nonstandard distribution I can't deploy on a server that easy and that it's reinventing the wheel everywhere. For custom applications I don't want to miss SQLAlchemy any more or all those template engines available for Python. So no, for things I have to bootstrap fast and quickly I would chose Django because of the community and the number of developers, and for custom applications I go with Werkzeug, especially because I can fix it when it breaks ;-)In general I'm not a framework lover, even though I'm happy Django user. Mainly because I have a couple of use cases I can solve with Django and because the Django developers do a very good job at keeping the source clean, readable and maintained. When I looked at the web2py sources I stopped looking at it pretty soon when I found out that it's bypassing the python import system for controllers and models, that it comes in a nonstandard distribution I can't deploy on a server that easy and that it's reinventing the wheel everywhere. For custom applications I don't want to miss SQLAlchemy any more or all those template engines available for Python. So no, for things I have to bootstrap fast and quickly I would chose Django because of the community and the number of developers, and for custom applications I go with Werkzeug, especially because I can fix it when it breaks ;-)SQAAAAJTAAAABGJvZHlSUwAAA3dJbiBnZW5lcmFsIEknbSBub3QgYSBmcmFtZXdvcmsgbG92ZXIs IGV2ZW4gdGhvdWdoIEknbSBoYXBweSBEamFuZ28gdXNlci4gTWFpbmx5IGJlY2F1c2UgSSBoYXZl IGEgY291cGxlIG9mIHVzZSBjYXNlcyBJIGNhbiBzb2x2ZSB3aXRoIERqYW5nbyBhbmQgYmVjYXVz ZSB0aGUgRGphbmdvIGRldmVsb3BlcnMgZG8gYSB2ZXJ5IGdvb2Qgam9iIGF0IGtlZXBpbmcgdGhl IHNvdXJjZSBjbGVhbiwgcmVhZGFibGUgYW5kIG1haW50YWluZWQuCgpXaGVuIEkgbG9va2VkIGF0 IHRoZSB3ZWIycHkgc291cmNlcyBJIHN0b3BwZWQgbG9va2luZyBhdCBpdCBwcmV0dHkgc29vbiB3 aGVuIEkgZm91bmQgb3V0IHRoYXQgaXQncyBieXBhc3NpbmcgdGhlIHB5dGhvbiBpbXBvcnQgc3lz dGVtIGZvciBjb250cm9sbGVycyBhbmQgbW9kZWxzLCB0aGF0IGl0IGNvbWVzIGluIGEgbm9uc3Rh bmRhcmQgZGlzdHJpYnV0aW9uIEkgY2FuJ3QgZGVwbG95IG9uIGEgc2VydmVyIHRoYXQgZWFzeSBh bmQgdGhhdCBpdCdzIHJlaW52ZW50aW5nIHRoZSB3aGVlbCBldmVyeXdoZXJlLgoKRm9yIGN1c3Rv bSBhcHBsaWNhdGlvbnMgSSBkb24ndCB3YW50IHRvIG1pc3MgU1FMQWxjaGVteSBhbnkgbW9yZSBv ciBhbGwgdGhvc2UgdGVtcGxhdGUgZW5naW5lcyBhdmFpbGFibGUgZm9yIFB5dGhvbi4gU28gbm8s IGZvciB0aGluZ3MgSSBoYXZlIHRvIGJvb3RzdHJhcCBmYXN0IGFuZCBxdWlja2x5IEkgd291bGQg Y2hvc2UgRGphbmdvIGJlY2F1c2Ugb2YgdGhlIGNvbW11bml0eSBhbmQgdGhlIG51bWJlciBvZiBk ZXZlbG9wZXJzLCBhbmQgZm9yIGN1c3RvbSBhcHBsaWNhdGlvbnMgSSBnbyB3aXRoIFdlcmt6ZXVn LCBlc3BlY2lhbGx5IGJlY2F1c2UgSSBjYW4gZml4IGl0IHdoZW4gaXQgYnJlYWtzIDstKUwAAFMA AAAGcGFyc2VyUwAAAARodG1s Massimomdipierro@cs.depaul.eduhttp://www.web2py.com2008-01-25T15:25:16Znono0If you download the web2py source code instead of the windows/mac executables, you can deploy it as any other python framework. In fact web2py is wsgi compliant, packages the paste httserver (same as pylons) if you want to use mod_proxy, and a wsgi handler like Django if you prefer mod_wsgi. You can install any python module using easy_install and import it from models/view/controllers as you would in Django or Pylons. web2py allows you to bytecode-compile your controllers/views so that 1) no parsing of templates is done in production mode, and 2) you can distribute your apps in semi-closed source; this is why it bypasses the normal import for its own controllers. A small prize to pay for a much faster framework.If you download the web2py source code instead of the windows/mac executables, you can deploy it as any other python framework. In fact web2py is wsgi compliant, packages the paste httserver (same as pylons) if you want to use mod_proxy, and a wsgi handler like Django if you prefer mod_wsgi. You can install any python module using easy_install and import it from models/view/controllers as you would in Django or Pylons. web2py allows you to bytecode-compile your controllers/views so that 1) no parsing of templates is done in production mode, and 2) you can distribute your apps in semi-closed source; this is why it bypasses the normal import for its own controllers. A small prize to pay for a much faster framework.SQAAAAJTAAAABGJvZHlSUwAAAtJJZiB5b3UgZG93bmxvYWQgdGhlIHdlYjJweSBzb3VyY2UgY29k ZSBpbnN0ZWFkIG9mIHRoZSB3aW5kb3dzL21hYyBleGVjdXRhYmxlcywgeW91IGNhbiBkZXBsb3kg aXQgYXMgYW55IG90aGVyIHB5dGhvbiBmcmFtZXdvcmsuIEluIGZhY3Qgd2ViMnB5IGlzIHdzZ2kg Y29tcGxpYW50LCBwYWNrYWdlcyB0aGUgcGFzdGUgaHR0c2VydmVyIChzYW1lIGFzIHB5bG9ucykg aWYgeW91IHdhbnQgdG8gdXNlIG1vZF9wcm94eSwgYW5kIGEgd3NnaSBoYW5kbGVyIGxpa2UgRGph bmdvIGlmIHlvdSBwcmVmZXIgbW9kX3dzZ2kuIFlvdSBjYW4gaW5zdGFsbCBhbnkgcHl0aG9uIG1v ZHVsZSB1c2luZyBlYXN5X2luc3RhbGwgYW5kIGltcG9ydCBpdCBmcm9tIG1vZGVscy92aWV3L2Nv bnRyb2xsZXJzIGFzIHlvdSB3b3VsZCBpbiBEamFuZ28gb3IgUHlsb25zLiB3ZWIycHkgYWxsb3dz IHlvdSB0byBieXRlY29kZS1jb21waWxlIHlvdXIgY29udHJvbGxlcnMvdmlld3Mgc28gdGhhdCAx KSBubyBwYXJzaW5nIG9mIHRlbXBsYXRlcyBpcyBkb25lIGluIHByb2R1Y3Rpb24gbW9kZSwgYW5k IDIpIHlvdSBjYW4gZGlzdHJpYnV0ZSB5b3VyIGFwcHMgaW4gc2VtaS1jbG9zZWQgc291cmNlOyB0 aGlzIGlzIHdoeSBpdCBieXBhc3NlcyB0aGUgbm9ybWFsIGltcG9ydCBmb3IgaXRzIG93biBjb250 cm9sbGVycy4gQSBzbWFsbCBwcml6ZSB0byBwYXkgZm9yIGEgbXVjaCBmYXN0ZXIgZnJhbWV3b3Jr LkwAAFMAAAAGcGFyc2VyUwAAAARodG1s New Stuff in Werkzeug (and the WSGI World)http://lucumr.pocoo.org/cogitations/2008/01/16/new-stuff-in-werkzeug-and-the-wsgi-world/2008-01-16T17:29:22Z2008-01-16T17:29:22ZArmin Ronachernew-stuff-in-werkzeug-and-the-wsgi-worldyesyes2Unfortunately I'm very busy lately so there are few updates on Werkzeug and all the other libraries I personally contributed (and there are even some patches in my Mail queue I have to apply after reviewing) but that doesn't mean that there is no progress :-) There is actually quite a lot of new stuff between the 0.1 release and now. Werkzeug tries to implement stupid stuff you reimplement in every second application in a way that you can use it with minor modifications in your application. Because many of those features only come up if you have implemented them often in your own applications they didn't make it into 0.1. Thanks to all the early adopters we now have cool new stuff that was implemented because there was need for it. For example Werkzeug now has RFC-compliant Etag and Cache-Control parsing. You can also generate etags automatically for responses and make them conditional for some requests. The utility module was extended with many new stuff that fix limitations in the standard library or implement long missed functions like finding modules in a package (very useful if you want to automatically register controllers), importing modules by a string (useful if your URL map endpoints are (partial) import paths), generating URLs like trac does by calling an Href object, functions to fix URLs similar to the way Firefox fixes them, dumping and parsing HTTP dates, loading and dumping cookies with a simple function call (and support for http only) and probably a lot more before the actual 0.2 release. Another cool thing is (unrelated to Werkzeug) that more and more cool modules come up that make web development a charm. While babel is available for quite a while I haven't really used it until last weak and it's really great. Together with Werkzeug's routing system and the ability to do multiple inheritance in SQLAlchemy there are so cool ways to do web development of internationalized applications. <small>I know the last sentence doesn't make sense without the context, so I guess I have to blog about that. <small>sooo freaking cool.</small></small> Form handling in Python is still a bit strange if you are not using django's newforms (I know that there is formencode but somehow it isn't what I'm looking for) but there is now <a href="http://pypi.python.org/pypi/WTForms/">WTForms</a> which looks promising. With some more small changes it could become a very cool form handling system (for example I'm missing some default validators at the moment and I'm not completely sure how to pass choices to a select box in a per form instance basis). WTForms was derived from an application that is already in production so it solves already many problems nicely. It's a library I want to watch closely the next weeks. And I think that approach should become the way Werkzeug is developed in the future. Implement features a release earlier and mark them as "under consideration" if they are not yet used in production applications. If you adopt them early you can give feedback and we can improve it to the next Werkzeug release and streamline the API. What's to do until the next Werkzeug release? Georg is currently working on making the sphinx documentation builder independent from the CPython documentation so that other projects can use it too. I then want to semi-automatically build an API documentation for Werkzeug and combine them with hand written rst pages for the Werkzeug 0.2 documentation. I got some feedback for the Werkzeug docs and looks like they are a bit too chaotic and misleading. Especially getting started with Werkzeug is still too complicated so I hope we can address this with a new documentation that combines automatically generated documentation with tutorials. The documentation tool could probably be useful for other projects too, I guess <a href="http://pyside.blogspot.com/">Georg</a> will drop some lines in his blog once it's ready. Updates regarding Jinja will be up shortly, there is currently a branch developed by Lakin Wecker to speed up Jinja template evaluation. And if you already know what GHRML/XAML will gonna be: I will try to get that running this weekend. That's it for the moment ;-)Unfortunately I'm very busy lately so there are few updates on Werkzeug and all the other libraries I personally contributed (and there are even some patches in my Mail queue I have to apply after reviewing) but that doesn't mean that there is no progress :-) There is actually quite a lot of new stuff between the 0.1 release and now. Werkzeug tries to implement stupid stuff you reimplement in every second application in a way that you can use it with minor modifications in your application. Because many of those features only come up if you have implemented them often in your own applications they didn't make it into 0.1. Thanks to all the early adopters we now have cool new stuff that was implemented because there was need for it. For example Werkzeug now has RFC-compliant Etag and Cache-Control parsing. You can also generate etags automatically for responses and make them conditional for some requests. The utility module was extended with many new stuff that fix limitations in the standard library or implement long missed functions like finding modules in a package (very useful if you want to automatically register controllers), importing modules by a string (useful if your URL map endpoints are (partial) import paths), generating URLs like trac does by calling an Href object, functions to fix URLs similar to the way Firefox fixes them, dumping and parsing HTTP dates, loading and dumping cookies with a simple function call (and support for http only) and probably a lot more before the actual 0.2 release. Another cool thing is (unrelated to Werkzeug) that more and more cool modules come up that make web development a charm. While babel is available for quite a while I haven't really used it until last weak and it's really great. Together with Werkzeug's routing system and the ability to do multiple inheritance in SQLAlchemy there are so cool ways to do web development of internationalized applications. <small>I know the last sentence doesn't make sense without the context, so I guess I have to blog about that. <small>sooo freaking cool.</small></small> Form handling in Python is still a bit strange if you are not using django's newforms (I know that there is formencode but somehow it isn't what I'm looking for) but there is now <a href="http://pypi.python.org/pypi/WTForms/">WTForms</a> which looks promising. With some more small changes it could become a very cool form handling system (for example I'm missing some default validators at the moment and I'm not completely sure how to pass choices to a select box in a per form instance basis). WTForms was derived from an application that is already in production so it solves already many problems nicely. It's a library I want to watch closely the next weeks. And I think that approach should become the way Werkzeug is developed in the future. Implement features a release earlier and mark them as "under consideration" if they are not yet used in production applications. If you adopt them early you can give feedback and we can improve it to the next Werkzeug release and streamline the API. What's to do until the next Werkzeug release? Georg is currently working on making the sphinx documentation builder independent from the CPython documentation so that other projects can use it too. I then want to semi-automatically build an API documentation for Werkzeug and combine them with hand written rst pages for the Werkzeug 0.2 documentation. I got some feedback for the Werkzeug docs and looks like they are a bit too chaotic and misleading. Especially getting started with Werkzeug is still too complicated so I hope we can address this with a new documentation that combines automatically generated documentation with tutorials. The documentation tool could probably be useful for other projects too, I guess <a href="http://pyside.blogspot.com/">Georg</a> will drop some lines in his blog once it's ready. Updates regarding Jinja will be up shortly, there is currently a branch developed by Lakin Wecker to speed up Jinja template evaluation. And if you already know what GHRML/XAML will gonna be: I will try to get that running this weekend. That's it for the moment ;-)SQAAAANTAAAABGJvZHlSUwAAB5RVbmZvcnR1bmF0ZWx5IEknbSB2ZXJ5IGJ1c3kgbGF0ZWx5IHNv IHRoZXJlIGFyZSBmZXcgdXBkYXRlcyBvbiBXZXJremV1ZyBhbmQgYWxsIHRoZSBvdGhlciBsaWJy YXJpZXMgSSBwZXJzb25hbGx5IGNvbnRyaWJ1dGVkIChhbmQgdGhlcmUgYXJlIGV2ZW4gc29tZSBw YXRjaGVzIGluIG15IE1haWwgcXVldWUgSSBoYXZlIHRvIGFwcGx5IGFmdGVyIHJldmlld2luZykg YnV0IHRoYXQgZG9lc24ndCBtZWFuIHRoYXQgdGhlcmUgaXMgbm8gcHJvZ3Jlc3MgOi0pCgpUaGVy ZSBpcyBhY3R1YWxseSBxdWl0ZSBhIGxvdCBvZiBuZXcgc3R1ZmYgYmV0d2VlbiB0aGUgMC4xIHJl bGVhc2UgYW5kIG5vdy4gV2Vya3pldWcgdHJpZXMgdG8gaW1wbGVtZW50IHN0dXBpZCBzdHVmZiB5 b3UgcmVpbXBsZW1lbnQgaW4gZXZlcnkgc2Vjb25kIGFwcGxpY2F0aW9uIGluIGEgd2F5IHRoYXQg eW91IGNhbiB1c2UgaXQgd2l0aCBtaW5vciBtb2RpZmljYXRpb25zIGluIHlvdXIgYXBwbGljYXRp b24uIEJlY2F1c2UgbWFueSBvZiB0aG9zZSBmZWF0dXJlcyBvbmx5IGNvbWUgdXAgaWYgeW91IGhh dmUgaW1wbGVtZW50ZWQgdGhlbSBvZnRlbiBpbiB5b3VyIG93biBhcHBsaWNhdGlvbnMgdGhleSBk aWRuJ3QgbWFrZSBpdCBpbnRvIDAuMS4gVGhhbmtzIHRvIGFsbCB0aGUgZWFybHkgYWRvcHRlcnMg d2Ugbm93IGhhdmUgY29vbCBuZXcgc3R1ZmYgdGhhdCB3YXMgaW1wbGVtZW50ZWQgYmVjYXVzZSB0 aGVyZSB3YXMgbmVlZCBmb3IgaXQuCgpGb3IgZXhhbXBsZSBXZXJremV1ZyBub3cgaGFzIFJGQy1j b21wbGlhbnQgRXRhZyBhbmQgQ2FjaGUtQ29udHJvbCBwYXJzaW5nLiBZb3UgY2FuIGFsc28gZ2Vu ZXJhdGUgZXRhZ3MgYXV0b21hdGljYWxseSBmb3IgcmVzcG9uc2VzIGFuZCBtYWtlIHRoZW0gY29u ZGl0aW9uYWwgZm9yIHNvbWUgcmVxdWVzdHMuIFRoZSB1dGlsaXR5IG1vZHVsZSB3YXMgZXh0ZW5k ZWQgd2l0aCBtYW55IG5ldyBzdHVmZiB0aGF0IGZpeCBsaW1pdGF0aW9ucyBpbiB0aGUgc3RhbmRh cmQgbGlicmFyeSBvciBpbXBsZW1lbnQgbG9uZyBtaXNzZWQgZnVuY3Rpb25zIGxpa2UgZmluZGlu ZyBtb2R1bGVzIGluIGEgcGFja2FnZSAodmVyeSB1c2VmdWwgaWYgeW91IHdhbnQgdG8gYXV0b21h dGljYWxseSByZWdpc3RlciBjb250cm9sbGVycyksIGltcG9ydGluZyBtb2R1bGVzIGJ5IGEgc3Ry aW5nICh1c2VmdWwgaWYgeW91ciBVUkwgbWFwIGVuZHBvaW50cyBhcmUgKHBhcnRpYWwpIGltcG9y dCBwYXRocyksIGdlbmVyYXRpbmcgVVJMcyBsaWtlIHRyYWMgZG9lcyBieSBjYWxsaW5nIGFuIEhy ZWYgb2JqZWN0LCBmdW5jdGlvbnMgdG8gZml4IFVSTHMgc2ltaWxhciB0byB0aGUgd2F5IEZpcmVm b3ggZml4ZXMgdGhlbSwgZHVtcGluZyBhbmQgcGFyc2luZyBIVFRQIGRhdGVzLCBsb2FkaW5nIGFu ZCBkdW1waW5nIGNvb2tpZXMgd2l0aCBhIHNpbXBsZSBmdW5jdGlvbiBjYWxsIChhbmQgc3VwcG9y dCBmb3IgaHR0cCBvbmx5KSBhbmQgcHJvYmFibHkgYSBsb3QgbW9yZSBiZWZvcmUgdGhlIGFjdHVh bCAwLjIgcmVsZWFzZS4KCkFub3RoZXIgY29vbCB0aGluZyBpcyAodW5yZWxhdGVkIHRvIFdlcmt6 ZXVnKSB0aGF0IG1vcmUgYW5kIG1vcmUgY29vbCBtb2R1bGVzIGNvbWUgdXAgdGhhdCBtYWtlIHdl YiBkZXZlbG9wbWVudCBhIGNoYXJtLiBXaGlsZSBiYWJlbCBpcyBhdmFpbGFibGUgZm9yIHF1aXRl IGEgd2hpbGUgSSBoYXZlbid0IHJlYWxseSB1c2VkIGl0IHVudGlsIGxhc3Qgd2VhayBhbmQgaXQn cyByZWFsbHkgZ3JlYXQuIFRvZ2V0aGVyIHdpdGggV2Vya3pldWcncyByb3V0aW5nIHN5c3RlbSBh bmQgdGhlIGFiaWxpdHkgdG8gZG8gbXVsdGlwbGUgaW5oZXJpdGFuY2UgaW4gU1FMQWxjaGVteSB0 aGVyZSBhcmUgc28gY29vbCB3YXlzIHRvIGRvIHdlYiBkZXZlbG9wbWVudCBvZiBpbnRlcm5hdGlv bmFsaXplZCBhcHBsaWNhdGlvbnMuIEwAA0VTAAAABXNtYWxsTAABRVMAAAAFc21hbGxMAABNAABT AAAAE3Nvb28gZnJlYWtpbmcgY29vbC5TAAAAAE0AAFMAAABnSSBrbm93IHRoZSBsYXN0IHNlbnRl bmNlIGRvZXNuJ3QgbWFrZSBzZW5zZSB3aXRob3V0IHRoZSBjb250ZXh0LCBzbyBJIGd1ZXNzIEkg aGF2ZSB0byBibG9nIGFib3V0IHRoYXQuIFMAAAC1CgpGb3JtIGhhbmRsaW5nIGluIFB5dGhvbiBp cyBzdGlsbCBhIGJpdCBzdHJhbmdlIGlmIHlvdSBhcmUgbm90IHVzaW5nIGRqYW5nbydzIG5ld2Zv cm1zIChJIGtub3cgdGhhdCB0aGVyZSBpcyBmb3JtZW5jb2RlIGJ1dCBzb21laG93IGl0IGlzbid0 IHdoYXQgSSdtIGxvb2tpbmcgZm9yKSBidXQgdGhlcmUgaXMgbm93IEVTAAAAAWFMAABNAAFTAAAA BGhyZWZTAAAAJGh0dHA6Ly9weXBpLnB5dGhvbi5vcmcvcHlwaS9XVEZvcm1zL1MAAAAHV1RGb3Jt c1MAAAXQIHdoaWNoIGxvb2tzIHByb21pc2luZy4gV2l0aCBzb21lIG1vcmUgc21hbGwgY2hhbmdl cyBpdCBjb3VsZCBiZWNvbWUgYSB2ZXJ5IGNvb2wgZm9ybSBoYW5kbGluZyBzeXN0ZW0gKGZvciBl eGFtcGxlIEknbSBtaXNzaW5nIHNvbWUgZGVmYXVsdCB2YWxpZGF0b3JzIGF0IHRoZSBtb21lbnQg YW5kIEknbSBub3QgY29tcGxldGVseSBzdXJlIGhvdyB0byBwYXNzIGNob2ljZXMgdG8gYSBzZWxl Y3QgYm94IGluIGEgcGVyIGZvcm0gaW5zdGFuY2UgYmFzaXMpLiBXVEZvcm1zIHdhcyBkZXJpdmVk IGZyb20gYW4gYXBwbGljYXRpb24gdGhhdCBpcyBhbHJlYWR5IGluIHByb2R1Y3Rpb24gc28gaXQg c29sdmVzIGFscmVhZHkgbWFueSBwcm9ibGVtcyBuaWNlbHkuIEl0J3MgYSBsaWJyYXJ5IEkgd2Fu dCB0byB3YXRjaCBjbG9zZWx5IHRoZSBuZXh0IHdlZWtzLgoKQW5kIEkgdGhpbmsgdGhhdCBhcHBy b2FjaCBzaG91bGQgYmVjb21lIHRoZSB3YXkgV2Vya3pldWcgaXMgZGV2ZWxvcGVkIGluIHRoZSBm dXR1cmUuIEltcGxlbWVudCBmZWF0dXJlcyBhIHJlbGVhc2UgZWFybGllciBhbmQgbWFyayB0aGVt IGFzICJ1bmRlciBjb25zaWRlcmF0aW9uIiBpZiB0aGV5IGFyZSBub3QgeWV0IHVzZWQgaW4gcHJv ZHVjdGlvbiBhcHBsaWNhdGlvbnMuIElmIHlvdSBhZG9wdCB0aGVtIGVhcmx5IHlvdSBjYW4gZ2l2 ZSBmZWVkYmFjayBhbmQgd2UgY2FuIGltcHJvdmUgaXQgdG8gdGhlIG5leHQgV2Vya3pldWcgcmVs ZWFzZSBhbmQgc3RyZWFtbGluZSB0aGUgQVBJLgoKV2hhdCdzIHRvIGRvIHVudGlsIHRoZSBuZXh0 IFdlcmt6ZXVnIHJlbGVhc2U/IEdlb3JnIGlzIGN1cnJlbnRseSB3b3JraW5nIG9uIG1ha2luZyB0 aGUgc3BoaW54IGRvY3VtZW50YXRpb24gYnVpbGRlciBpbmRlcGVuZGVudCBmcm9tIHRoZSBDUHl0 aG9uIGRvY3VtZW50YXRpb24gc28gdGhhdCBvdGhlciBwcm9qZWN0cyBjYW4gdXNlIGl0IHRvby4g SSB0aGVuIHdhbnQgdG8gc2VtaS1hdXRvbWF0aWNhbGx5IGJ1aWxkIGFuIEFQSSBkb2N1bWVudGF0 aW9uIGZvciBXZXJremV1ZyBhbmQgY29tYmluZSB0aGVtIHdpdGggaGFuZCB3cml0dGVuIHJzdCBw YWdlcyBmb3IgdGhlIFdlcmt6ZXVnIDAuMiBkb2N1bWVudGF0aW9uLiBJIGdvdCBzb21lIGZlZWRi YWNrIGZvciB0aGUgV2Vya3pldWcgZG9jcyBhbmQgbG9va3MgbGlrZSB0aGV5IGFyZSBhIGJpdCB0 b28gY2hhb3RpYyBhbmQgbWlzbGVhZGluZy4gRXNwZWNpYWxseSBnZXR0aW5nIHN0YXJ0ZWQgd2l0 aCBXZXJremV1ZyBpcyBzdGlsbCB0b28gY29tcGxpY2F0ZWQgc28gSSBob3BlIHdlIGNhbiBhZGRy ZXNzIHRoaXMgd2l0aCBhIG5ldyBkb2N1bWVudGF0aW9uIHRoYXQgY29tYmluZXMgYXV0b21hdGlj YWxseSBnZW5lcmF0ZWQgZG9jdW1lbnRhdGlvbiB3aXRoIHR1dG9yaWFscy4KClRoZSBkb2N1bWVu dGF0aW9uIHRvb2wgY291bGQgcHJvYmFibHkgYmUgdXNlZnVsIGZvciBvdGhlciBwcm9qZWN0cyB0 b28sIEkgZ3Vlc3MgRVMAAAABYUwAAE0AAVMAAAAEaHJlZlMAAAAbaHR0cDovL3B5c2lkZS5ibG9n c3BvdC5jb20vUwAAAAVHZW9yZ1MAAAE+IHdpbGwgZHJvcCBzb21lIGxpbmVzIGluIGhpcyBibG9n IG9uY2UgaXQncyByZWFkeS4KClVwZGF0ZXMgcmVnYXJkaW5nIEppbmphIHdpbGwgYmUgdXAgc2hv cnRseSwgdGhlcmUgaXMgY3VycmVudGx5IGEgYnJhbmNoIGRldmVsb3BlZCBieSBMYWtpbiBXZWNr ZXIgdG8gc3BlZWQgdXAgSmluamEgdGVtcGxhdGUgZXZhbHVhdGlvbi4gQW5kIGlmIHlvdSBhbHJl YWR5IGtub3cgd2hhdCBHSFJNTC9YQU1MIHdpbGwgZ29ubmEgYmU6IEkgd2lsbCB0cnkgdG8gZ2V0 IHRoYXQgcnVubmluZyB0aGlzIHdlZWtlbmQuCgpUaGF0J3MgaXQgZm9yIHRoZSBtb21lbnQgOy0p UwAAAAZwYXJzZXJTAAAABGh0bWxTAAAABWludHJvUlMAAAAATAAA How to fix Pythonhttp://lucumr.pocoo.org/cogitations/2008/01/10/how-to-fix-python/2008-01-10T16:23:01Z2008-01-10T16:23:01ZArmin Ronacherhow-to-fix-pythonyesyes2For a long time I thought I'm the only person disliking the stdlib, but apparently there are more :-) Not just that every library has it's own code style, it also has different names, some are implemented insanely bad (Cookie.py anyone?) or Javaish (threading, unittest) or just plain stupid (codeop). I know we can't just get rid of that stdlib, wait a moment, why can't we? Python 3 is upcoming and we all have to adapt our libraries and applications anyways. It wouldn't be too hard actually. Python loads modules from zip files anyways. Just move all the stuff into a zip file, move it into "old" or somethign and old applications just have to alter their imports "from cgi import escape" to "from old.cgi import escape". Or the other way round, the old libraries stay where they are and the new stdlib goes into "py.*" or "std.*". Insane or a good idea? You be the judge.For a long time I thought I'm the only person disliking the stdlib, but apparently there are more :-) Not just that every library has it's own code style, it also has different names, some are implemented insanely bad (Cookie.py anyone?) or Javaish (threading, unittest) or just plain stupid (codeop). I know we can't just get rid of that stdlib, wait a moment, why can't we? Python 3 is upcoming and we all have to adapt our libraries and applications anyways. It wouldn't be too hard actually. Python loads modules from zip files anyways. Just move all the stuff into a zip file, move it into "old" or somethign and old applications just have to alter their imports "from cgi import escape" to "from old.cgi import escape". Or the other way round, the old libraries stay where they are and the new stdlib goes into "py.*" or "std.*". Insane or a good idea? You be the judge.SQAAAANTAAAABGJvZHlSUwAAA25Gb3IgYSBsb25nIHRpbWUgSSB0aG91Z2h0IEknbSB0aGUgb25s eSBwZXJzb24gZGlzbGlraW5nIHRoZSBzdGRsaWIsIGJ1dCBhcHBhcmVudGx5IHRoZXJlIGFyZSBt b3JlIDotKSBOb3QganVzdCB0aGF0IGV2ZXJ5IGxpYnJhcnkgaGFzIGl0J3Mgb3duIGNvZGUgc3R5 bGUsIGl0IGFsc28gaGFzIGRpZmZlcmVudCBuYW1lcywgc29tZSBhcmUgaW1wbGVtZW50ZWQgaW5z YW5lbHkgYmFkIChDb29raWUucHkgYW55b25lPykgb3IgSmF2YWlzaCAodGhyZWFkaW5nLCB1bml0 dGVzdCkgb3IganVzdCBwbGFpbiBzdHVwaWQgKGNvZGVvcCkuIEkga25vdyB3ZSBjYW4ndCBqdXN0 IGdldCByaWQgb2YgdGhhdCBzdGRsaWIsIHdhaXQgYSBtb21lbnQsIHdoeSBjYW4ndCB3ZT8gUHl0 aG9uIDMgaXMgdXBjb21pbmcgYW5kIHdlIGFsbCBoYXZlIHRvIGFkYXB0IG91ciBsaWJyYXJpZXMg YW5kIGFwcGxpY2F0aW9ucyBhbnl3YXlzLgoKSXQgd291bGRuJ3QgYmUgdG9vIGhhcmQgYWN0dWFs bHkuIFB5dGhvbiBsb2FkcyBtb2R1bGVzIGZyb20gemlwIGZpbGVzIGFueXdheXMuIEp1c3QgbW92 ZSBhbGwgdGhlIHN0dWZmIGludG8gYSB6aXAgZmlsZSwgbW92ZSBpdCBpbnRvICJvbGQiIG9yIHNv bWV0aGlnbiBhbmQgb2xkIGFwcGxpY2F0aW9ucyBqdXN0IGhhdmUgdG8gYWx0ZXIgdGhlaXIgaW1w b3J0cyAiZnJvbSBjZ2kgaW1wb3J0IGVzY2FwZSIgdG8gImZyb20gb2xkLmNnaSBpbXBvcnQgZXNj YXBlIi4gT3IgdGhlIG90aGVyIHdheSByb3VuZCwgdGhlIG9sZCBsaWJyYXJpZXMgc3RheSB3aGVy ZSB0aGV5IGFyZSBhbmQgdGhlIG5ldyBzdGRsaWIgZ29lcyBpbnRvICJweS4qIiBvciAic3RkLioi LgoKSW5zYW5lIG9yIGEgZ29vZCBpZGVhPyBZb3UgYmUgdGhlIGp1ZGdlLkwAAFMAAAAGcGFyc2Vy UwAAAARodG1sUwAAAAVpbnRyb1JTAAAAAEwAAA== johnjohn.w@web.de2008-01-10T16:46:11Znono0Little bit too late for such a change, hein?Little bit too late for such a change, hein?SQAAAAJTAAAABGJvZHlSUwAAACxMaXR0bGUgYml0IHRvbyBsYXRlIGZvciBzdWNoIGEgY2hhbmdl LCBoZWluP0wAAFMAAAAGcGFyc2VyUwAAAARodG1s Brettbrett@python.org2008-01-11T01:46:53Znono0There is a difference between wiping out the stdlib entirely and cleaning it up. While some things definitely need removal or a re-implementation, I don't think the stdlib needs to go entirely. That would put us worse off than C where you have to hunt down various 3rd-party libraries, try to figure out which ones are good, etc. And you don't need to wait until Python 3.0 to come up with new modules and begin getting rid of old ones. People just need to write up a better implementation and be willing to maintain it in the stdlib.There is a difference between wiping out the stdlib entirely and cleaning it up. While some things definitely need removal or a re-implementation, I don't think the stdlib needs to go entirely. That would put us worse off than C where you have to hunt down various 3rd-party libraries, try to figure out which ones are good, etc. And you don't need to wait until Python 3.0 to come up with new modules and begin getting rid of old ones. People just need to write up a better implementation and be willing to maintain it in the stdlib.SQAAAAJTAAAABGJvZHlSUwAAAhdUaGVyZSBpcyBhIGRpZmZlcmVuY2UgYmV0d2VlbiB3aXBpbmcg b3V0IHRoZSBzdGRsaWIgZW50aXJlbHkgYW5kIGNsZWFuaW5nIGl0IHVwLiBXaGlsZSBzb21lIHRo aW5ncyBkZWZpbml0ZWx5IG5lZWQgcmVtb3ZhbCBvciBhIHJlLWltcGxlbWVudGF0aW9uLCBJIGRv bid0IHRoaW5rIHRoZSBzdGRsaWIgbmVlZHMgdG8gZ28gZW50aXJlbHkuIFRoYXQgd291bGQgcHV0 IHVzIHdvcnNlIG9mZiB0aGFuIEMgd2hlcmUgeW91IGhhdmUgdG8gaHVudCBkb3duIHZhcmlvdXMg M3JkLXBhcnR5IGxpYnJhcmllcywgdHJ5IHRvIGZpZ3VyZSBvdXQgd2hpY2ggb25lcyBhcmUgZ29v ZCwgZXRjLgoKQW5kIHlvdSBkb24ndCBuZWVkIHRvIHdhaXQgdW50aWwgUHl0aG9uIDMuMCB0byBj b21lIHVwIHdpdGggbmV3IG1vZHVsZXMgYW5kIGJlZ2luIGdldHRpbmcgcmlkIG9mIG9sZCBvbmVz LiBQZW9wbGUganVzdCBuZWVkIHRvIHdyaXRlIHVwIGEgYmV0dGVyIGltcGxlbWVudGF0aW9uIGFu ZCBiZSB3aWxsaW5nIHRvIG1haW50YWluIGl0IGluIHRoZSBzdGRsaWIuTAAAUwAAAAZwYXJzZXJT AAAABGh0bWw= Georggeorg@python.org2008-01-11T09:40:36Znono0Also, it's not really that bad ("every library has it’s own code style"...) -- most libraries at least follow PEP 8, and the javaNaming isn't so widespread that we couldn't fix it for Py3k. And as Brett says, if you got a working replacement for any badly implemented module and are willing to maintain it, there's almost nothing preventing replacing it.Also, it's not really that bad ("every library has it’s own code style"...) -- most libraries at least follow PEP 8, and the javaNaming isn't so widespread that we couldn't fix it for Py3k. And as Brett says, if you got a working replacement for any badly implemented module and are willing to maintain it, there's almost nothing preventing replacing it.SQAAAAJTAAAABGJvZHlSUwAAAWVBbHNvLCBpdCdzIG5vdCByZWFsbHkgdGhhdCBiYWQgKCJldmVy eSBsaWJyYXJ5IGhhcyBpdOKAmXMgb3duIGNvZGUgc3R5bGUiLi4uKSAtLSBtb3N0IGxpYnJhcmll cyBhdCBsZWFzdCBmb2xsb3cgUEVQIDgsIGFuZCB0aGUgamF2YU5hbWluZyBpc24ndCBzbyB3aWRl c3ByZWFkIHRoYXQgd2UgY291bGRuJ3QgZml4IGl0IGZvciBQeTNrLgoKQW5kIGFzIEJyZXR0IHNh eXMsIGlmIHlvdSBnb3QgYSB3b3JraW5nIHJlcGxhY2VtZW50IGZvciBhbnkgYmFkbHkgaW1wbGVt ZW50ZWQgbW9kdWxlIGFuZCBhcmUgd2lsbGluZyB0byBtYWludGFpbiBpdCwgdGhlcmUncyBhbG1v c3Qgbm90aGluZyBwcmV2ZW50aW5nIHJlcGxhY2luZyBpdC5MAABTAAAABnBhcnNlclMAAAAEaHRt bA== Python Template Engine Comparisonhttp://lucumr.pocoo.org/cogitations/2008/01/01/python-template-engine-comparison/2008-01-01T20:32:12Z2008-01-01T20:32:12ZArmin Ronacherpython-template-engine-comparisonyesyes2I was small-talking with <a href="http://techspot.zzzeek.org/">zzzeek</a> about some things when I told him that I'm using Jinja, Genshi and Mako depending on what I'm doing. He told me that it's unusual to switch tools like that but I don't think it's that unusual. All three template engines are totally different but have a one thing in common: All three are the "second generation" of template engines. Genshi is the formal successor of kid, Mako somewhat replaced Mygthy and Jinja was inspired by the django templates. All three of them are framework agnostic, use unicode internally and have a cool API you can use in WSGI applications without scratching your head. But what inspired those template engines and which template engine to chose for which situation? I often used PHP in the past to do simple header/footer inclusion. But what always drove me nuts was that I had to use mod_rewrite to get nice URLs or use a bunch of folders with index.php files or use files and folders and drop the extension in the apache config. While this is nice, this is now that portable and you can't have dynamic parts in the URL and once you want some more dynamic stuff such as RSS feeds etc. you notice that you made a mistake by choosing PHP. Some days ago I then started working on the website for TextPress (not yet online) and wanted to try something new: I wrote a tiny WSGI application (about 50 lines of code) that just uses werkzeug's routing system and uses template names as endpoints. These templates are then loaded with Mako, rendered and returned as responses. This is not possible in the same way with Jinja because you don't have python blocks and not so simple and straightforward with Genshi because you have to think about XML or use a rather limited text based template engine. Another very cool feature of Mako is that you can do dynamic inheritance which is not possible in Jinja. Mako is a great template engine if you know Python, if you need some logic in templates (and you know: logic in templates is not bad in every situation) and if you need the best performance. Without a doubt Mako is one of the fastest template engines for Python and the fastest template engine that does not use a C extension. Then there is Jinja which is also a text based template engine like Mako. However the focus is on a completely different level. When Mako is like PHP, Jinja is like Smarty (even though Mako is a million times better than PHP as template engine). When I stated working with Python as programming language for web applications I stumbled about django. I looked at the template engine and thought: WTF is that? The syntax seemed odd and the restrictions ridiculous. Later on I loved the syntax (and apparently others do to: the mini template engine by Ian Bicking (tempita if I recall correctly) and the Genshi text templates are using that syntax or a similar one too) but some of the restrictions seem still ridiculous. When I looked at all those Django templates I created over the time I noticed that I often moved calculations into template tags that could be function calls, that I did other calculations in in the view functions that did not belong there and even more important: that you could replace 95% of the custom template tags with function calls or function calls with an enclosed template block if the template engine had proper expressions. This lead to the development of what is now known as Jinja. The syntax, the fact that it's sandboxed and the designed friendliness is still very similar to Django, but unlike Django python like expressions are possible in Jinja. I'm using Jinja wherever I think web designers want to work on later on. For example as template engine for TextPress or other applications that should be styled by third party web designers. Genshi on the other hand is an XML template engine. As a result of that it's slower but also "context aware". It knows when it's processing a CDATA section, it knows when it's inside a tag or an attribute etc. This makes it possible to defend XSS in an automatic way. Per default Genshi inserts the text into the output stream as text and not as markup. That means all the HTML entities are automatically escaped for you. And because it's stream based you can rewrite streams during the rendering process. This makes it possible to fill form fields automatically, use XInclude for simple layout templates and a lot more. You can even translate your XML based templates into HTML4 on the fly. So you can use your XML tool chain internally and output HTML4 and use the best of both worlds. But because of this high flexibility Genshi also has some problems to fight: You need to have XML knowledge to use it. No problem if you are a programmer, but not that good if you are a web designer doing fancy layouts. You are also forced to use XML templates everywhere. It's true that Genshi has text templates too to fill the gaps, but they are not comparable with real text template engines and you are still operating on an XML stream, just that you don't see it. And lastly: this whole stream processing makes Genshi slow. Not so slow that you can't use it for big applications, but noticeably slower than Mako or Jinja. If you are using XML anyways in your application, Genshi is a very good idea. Also if you don't have template designers that don't know XML or if performance is not that much of a problem. Most of the time the bottleneck is the database anyways. I never had real problems with Genshi performance so far. I hope this post sums up why I'm using all three template engines and why I think we should be happy that we can chose between a couple of template engines :-) Why I'm not covering other template engines like Cheetah or SimpleTAL? Mostly because I looked at them, tried them out and never used them for something big. Mostly because Mako looks a lot nicer than Cheetah to me and SimpleTAL is far too much away from Python for me.I was small-talking with <a href="http://techspot.zzzeek.org/">zzzeek</a> about some things when I told him that I'm using Jinja, Genshi and Mako depending on what I'm doing. He told me that it's unusual to switch tools like that but I don't think it's that unusual. All three template engines are totally different but have a one thing in common: All three are the "second generation" of template engines. Genshi is the formal successor of kid, Mako somewhat replaced Mygthy and Jinja was inspired by the django templates. All three of them are framework agnostic, use unicode internally and have a cool API you can use in WSGI applications without scratching your head. But what inspired those template engines and which template engine to chose for which situation? I often used PHP in the past to do simple header/footer inclusion. But what always drove me nuts was that I had to use mod_rewrite to get nice URLs or use a bunch of folders with index.php files or use files and folders and drop the extension in the apache config. While this is nice, this is now that portable and you can't have dynamic parts in the URL and once you want some more dynamic stuff such as RSS feeds etc. you notice that you made a mistake by choosing PHP. Some days ago I then started working on the website for TextPress (not yet online) and wanted to try something new: I wrote a tiny WSGI application (about 50 lines of code) that just uses werkzeug's routing system and uses template names as endpoints. These templates are then loaded with Mako, rendered and returned as responses. This is not possible in the same way with Jinja because you don't have python blocks and not so simple and straightforward with Genshi because you have to think about XML or use a rather limited text based template engine. Another very cool feature of Mako is that you can do dynamic inheritance which is not possible in Jinja. Mako is a great template engine if you know Python, if you need some logic in templates (and you know: logic in templates is not bad in every situation) and if you need the best performance. Without a doubt Mako is one of the fastest template engines for Python and the fastest template engine that does not use a C extension. Then there is Jinja which is also a text based template engine like Mako. However the focus is on a completely different level. When Mako is like PHP, Jinja is like Smarty (even though Mako is a million times better than PHP as template engine). When I stated working with Python as programming language for web applications I stumbled about django. I looked at the template engine and thought: WTF is that? The syntax seemed odd and the restrictions ridiculous. Later on I loved the syntax (and apparently others do to: the mini template engine by Ian Bicking (tempita if I recall correctly) and the Genshi text templates are using that syntax or a similar one too) but some of the restrictions seem still ridiculous. When I looked at all those Django templates I created over the time I noticed that I often moved calculations into template tags that could be function calls, that I did other calculations in in the view functions that did not belong there and even more important: that you could replace 95% of the custom template tags with function calls or function calls with an enclosed template block if the template engine had proper expressions. This lead to the development of what is now known as Jinja. The syntax, the fact that it's sandboxed and the designed friendliness is still very similar to Django, but unlike Django python like expressions are possible in Jinja. I'm using Jinja wherever I think web designers want to work on later on. For example as template engine for TextPress or other applications that should be styled by third party web designers. Genshi on the other hand is an XML template engine. As a result of that it's slower but also "context aware". It knows when it's processing a CDATA section, it knows when it's inside a tag or an attribute etc. This makes it possible to defend XSS in an automatic way. Per default Genshi inserts the text into the output stream as text and not as markup. That means all the HTML entities are automatically escaped for you. And because it's stream based you can rewrite streams during the rendering process. This makes it possible to fill form fields automatically, use XInclude for simple layout templates and a lot more. You can even translate your XML based templates into HTML4 on the fly. So you can use your XML tool chain internally and output HTML4 and use the best of both worlds. But because of this high flexibility Genshi also has some problems to fight: You need to have XML knowledge to use it. No problem if you are a programmer, but not that good if you are a web designer doing fancy layouts. You are also forced to use XML templates everywhere. It's true that Genshi has text templates too to fill the gaps, but they are not comparable with real text template engines and you are still operating on an XML stream, just that you don't see it. And lastly: this whole stream processing makes Genshi slow. Not so slow that you can't use it for big applications, but noticeably slower than Mako or Jinja. If you are using XML anyways in your application, Genshi is a very good idea. Also if you don't have template designers that don't know XML or if performance is not that much of a problem. Most of the time the bottleneck is the database anyways. I never had real problems with Genshi performance so far. I hope this post sums up why I'm using all three template engines and why I think we should be happy that we can chose between a couple of template engines :-) Why I'm not covering other template engines like Cheetah or SimpleTAL? Mostly because I looked at them, tried them out and never used them for something big. Mostly because Mako looks a lot nicer than Cheetah to me and SimpleTAL is far too much away from Python for me.SQAAAANTAAAABGJvZHlSUwAAABlJIHdhcyBzbWFsbC10YWxraW5nIHdpdGggTAABRVMAAAABYUwA AE0AAVMAAAAEaHJlZlMAAAAbaHR0cDovL3RlY2hzcG90Lnp6emVlay5vcmcvUwAAAAZ6enplZWtT AAAXACBhYm91dCBzb21lIHRoaW5ncyB3aGVuIEkgdG9sZCBoaW0gdGhhdCBJJ20gdXNpbmcgSmlu amEsIEdlbnNoaSBhbmQgTWFrbyBkZXBlbmRpbmcgb24gd2hhdCBJJ20gZG9pbmcuIEhlIHRvbGQg bWUgdGhhdCBpdCdzIHVudXN1YWwgdG8gc3dpdGNoIHRvb2xzIGxpa2UgdGhhdCBidXQgSSBkb24n dCB0aGluayBpdCdzIHRoYXQgdW51c3VhbC4KCkFsbCB0aHJlZSB0ZW1wbGF0ZSBlbmdpbmVzIGFy ZSB0b3RhbGx5IGRpZmZlcmVudCBidXQgaGF2ZSBhIG9uZSB0aGluZyBpbiBjb21tb246IEFsbCB0 aHJlZSBhcmUgdGhlICJzZWNvbmQgZ2VuZXJhdGlvbiIgb2YgdGVtcGxhdGUgZW5naW5lcy4gR2Vu c2hpIGlzIHRoZSBmb3JtYWwgc3VjY2Vzc29yIG9mIGtpZCwgTWFrbyBzb21ld2hhdCByZXBsYWNl ZCBNeWd0aHkgYW5kIEppbmphIHdhcyBpbnNwaXJlZCBieSB0aGUgZGphbmdvIHRlbXBsYXRlcy4g QWxsIHRocmVlIG9mIHRoZW0gYXJlIGZyYW1ld29yayBhZ25vc3RpYywgdXNlIHVuaWNvZGUgaW50 ZXJuYWxseSBhbmQgaGF2ZSBhIGNvb2wgQVBJIHlvdSBjYW4gdXNlIGluIFdTR0kgYXBwbGljYXRp b25zIHdpdGhvdXQgc2NyYXRjaGluZyB5b3VyIGhlYWQuIEJ1dCB3aGF0IGluc3BpcmVkIHRob3Nl IHRlbXBsYXRlIGVuZ2luZXMgYW5kIHdoaWNoIHRlbXBsYXRlIGVuZ2luZSB0byBjaG9zZSBmb3Ig d2hpY2ggc2l0dWF0aW9uPwoKSSBvZnRlbiB1c2VkIFBIUCBpbiB0aGUgcGFzdCB0byBkbyBzaW1w bGUgaGVhZGVyL2Zvb3RlciBpbmNsdXNpb24uIEJ1dCB3aGF0IGFsd2F5cyBkcm92ZSBtZSBudXRz IHdhcyB0aGF0IEkgaGFkIHRvIHVzZSBtb2RfcmV3cml0ZSB0byBnZXQgbmljZSBVUkxzIG9yIHVz ZSBhIGJ1bmNoIG9mIGZvbGRlcnMgd2l0aCBpbmRleC5waHAgZmlsZXMgb3IgdXNlIGZpbGVzIGFu ZCBmb2xkZXJzIGFuZCBkcm9wIHRoZSBleHRlbnNpb24gaW4gdGhlIGFwYWNoZSBjb25maWcuIFdo aWxlIHRoaXMgaXMgbmljZSwgdGhpcyBpcyBub3cgdGhhdCBwb3J0YWJsZSBhbmQgeW91IGNhbid0 IGhhdmUgZHluYW1pYyBwYXJ0cyBpbiB0aGUgVVJMIGFuZCBvbmNlIHlvdSB3YW50IHNvbWUgbW9y ZSBkeW5hbWljIHN0dWZmIHN1Y2ggYXMgUlNTIGZlZWRzIGV0Yy4geW91IG5vdGljZSB0aGF0IHlv dSBtYWRlIGEgbWlzdGFrZSBieSBjaG9vc2luZyBQSFAuIFNvbWUgZGF5cyBhZ28gSSB0aGVuIHN0 YXJ0ZWQgd29ya2luZyBvbiB0aGUgd2Vic2l0ZSBmb3IgVGV4dFByZXNzIChub3QgeWV0IG9ubGlu ZSkgYW5kIHdhbnRlZCB0byB0cnkgc29tZXRoaW5nIG5ldzogSSB3cm90ZSBhIHRpbnkgV1NHSSBh cHBsaWNhdGlvbiAoYWJvdXQgNTAgbGluZXMgb2YgY29kZSkgdGhhdCBqdXN0IHVzZXMgd2Vya3pl dWcncyByb3V0aW5nIHN5c3RlbSBhbmQgdXNlcyB0ZW1wbGF0ZSBuYW1lcyBhcyBlbmRwb2ludHMu IFRoZXNlIHRlbXBsYXRlcyBhcmUgdGhlbiBsb2FkZWQgd2l0aCBNYWtvLCByZW5kZXJlZCBhbmQg cmV0dXJuZWQgYXMgcmVzcG9uc2VzLiBUaGlzIGlzIG5vdCBwb3NzaWJsZSBpbiB0aGUgc2FtZSB3 YXkgd2l0aCBKaW5qYSBiZWNhdXNlIHlvdSBkb24ndCBoYXZlIHB5dGhvbiBibG9ja3MgYW5kIG5v dCBzbyBzaW1wbGUgYW5kIHN0cmFpZ2h0Zm9yd2FyZCB3aXRoIEdlbnNoaSBiZWNhdXNlIHlvdSBo YXZlIHRvIHRoaW5rIGFib3V0IFhNTCBvciB1c2UgYSByYXRoZXIgbGltaXRlZCB0ZXh0IGJhc2Vk IHRlbXBsYXRlIGVuZ2luZS4gQW5vdGhlciB2ZXJ5IGNvb2wgZmVhdHVyZSBvZiBNYWtvIGlzIHRo YXQgeW91IGNhbiBkbyBkeW5hbWljIGluaGVyaXRhbmNlIHdoaWNoIGlzIG5vdCBwb3NzaWJsZSBp biBKaW5qYS4KCk1ha28gaXMgYSBncmVhdCB0ZW1wbGF0ZSBlbmdpbmUgaWYgeW91IGtub3cgUHl0 aG9uLCBpZiB5b3UgbmVlZCBzb21lIGxvZ2ljIGluIHRlbXBsYXRlcyAoYW5kIHlvdSBrbm93OiBs b2dpYyBpbiB0ZW1wbGF0ZXMgaXMgbm90IGJhZCBpbiBldmVyeSBzaXR1YXRpb24pIGFuZCBpZiB5 b3UgbmVlZCB0aGUgYmVzdCBwZXJmb3JtYW5jZS4gV2l0aG91dCBhIGRvdWJ0IE1ha28gaXMgb25l IG9mIHRoZSBmYXN0ZXN0IHRlbXBsYXRlIGVuZ2luZXMgZm9yIFB5dGhvbiBhbmQgdGhlIGZhc3Rl c3QgdGVtcGxhdGUgZW5naW5lIHRoYXQgZG9lcyBub3QgdXNlIGEgQyBleHRlbnNpb24uCgpUaGVu IHRoZXJlIGlzIEppbmphIHdoaWNoIGlzIGFsc28gYSB0ZXh0IGJhc2VkIHRlbXBsYXRlIGVuZ2lu ZSBsaWtlIE1ha28uIEhvd2V2ZXIgdGhlIGZvY3VzIGlzIG9uIGEgY29tcGxldGVseSBkaWZmZXJl bnQgbGV2ZWwuIFdoZW4gTWFrbyBpcyBsaWtlIFBIUCwgSmluamEgaXMgbGlrZSBTbWFydHkgKGV2 ZW4gdGhvdWdoIE1ha28gaXMgYSBtaWxsaW9uIHRpbWVzIGJldHRlciB0aGFuIFBIUCBhcyB0ZW1w bGF0ZSBlbmdpbmUpLiBXaGVuIEkgc3RhdGVkIHdvcmtpbmcgd2l0aCBQeXRob24gYXMgcHJvZ3Jh bW1pbmcgbGFuZ3VhZ2UgZm9yIHdlYiBhcHBsaWNhdGlvbnMgSSBzdHVtYmxlZCBhYm91dCBkamFu Z28uIEkgbG9va2VkIGF0IHRoZSB0ZW1wbGF0ZSBlbmdpbmUgYW5kIHRob3VnaHQ6IFdURiBpcyB0 aGF0PyBUaGUgc3ludGF4IHNlZW1lZCBvZGQgYW5kIHRoZSByZXN0cmljdGlvbnMgcmlkaWN1bG91 cy4gTGF0ZXIgb24gSSBsb3ZlZCB0aGUgc3ludGF4IChhbmQgYXBwYXJlbnRseSBvdGhlcnMgZG8g dG86IHRoZSBtaW5pIHRlbXBsYXRlIGVuZ2luZSBieSBJYW4gQmlja2luZyAodGVtcGl0YSBpZiBJ IHJlY2FsbCBjb3JyZWN0bHkpIGFuZCB0aGUgR2Vuc2hpIHRleHQgdGVtcGxhdGVzIGFyZSB1c2lu ZyB0aGF0IHN5bnRheCBvciBhIHNpbWlsYXIgb25lIHRvbykgYnV0IHNvbWUgb2YgdGhlIHJlc3Ry aWN0aW9ucyBzZWVtIHN0aWxsIHJpZGljdWxvdXMuIFdoZW4gSSBsb29rZWQgYXQgYWxsIHRob3Nl IERqYW5nbyB0ZW1wbGF0ZXMgSSBjcmVhdGVkIG92ZXIgdGhlIHRpbWUgSSBub3RpY2VkIHRoYXQg SSBvZnRlbiBtb3ZlZCBjYWxjdWxhdGlvbnMgaW50byB0ZW1wbGF0ZSB0YWdzIHRoYXQgY291bGQg YmUgZnVuY3Rpb24gY2FsbHMsIHRoYXQgSSBkaWQgb3RoZXIgY2FsY3VsYXRpb25zIGluIGluIHRo ZSB2aWV3IGZ1bmN0aW9ucyB0aGF0IGRpZCBub3QgYmVsb25nIHRoZXJlIGFuZCBldmVuIG1vcmUg aW1wb3J0YW50OiB0aGF0IHlvdSBjb3VsZCByZXBsYWNlIDk1JSBvZiB0aGUgY3VzdG9tIHRlbXBs YXRlIHRhZ3Mgd2l0aCBmdW5jdGlvbiBjYWxscyBvciBmdW5jdGlvbiBjYWxscyB3aXRoIGFuIGVu Y2xvc2VkIHRlbXBsYXRlIGJsb2NrIGlmIHRoZSB0ZW1wbGF0ZSBlbmdpbmUgaGFkIHByb3BlciBl eHByZXNzaW9ucy4gVGhpcyBsZWFkIHRvIHRoZSBkZXZlbG9wbWVudCBvZiB3aGF0IGlzIG5vdyBr bm93biBhcyBKaW5qYS4gVGhlIHN5bnRheCwgdGhlIGZhY3QgdGhhdCBpdCdzIHNhbmRib3hlZCBh bmQgdGhlIGRlc2lnbmVkIGZyaWVuZGxpbmVzcyBpcyBzdGlsbCB2ZXJ5IHNpbWlsYXIgdG8gRGph bmdvLCBidXQgdW5saWtlIERqYW5nbyBweXRob24gbGlrZSBleHByZXNzaW9ucyBhcmUgcG9zc2li bGUgaW4gSmluamEuCgpJJ20gdXNpbmcgSmluamEgd2hlcmV2ZXIgSSB0aGluayB3ZWIgZGVzaWdu ZXJzIHdhbnQgdG8gd29yayBvbiBsYXRlciBvbi4gRm9yIGV4YW1wbGUgYXMgdGVtcGxhdGUgZW5n aW5lIGZvciBUZXh0UHJlc3Mgb3Igb3RoZXIgYXBwbGljYXRpb25zIHRoYXQgc2hvdWxkIGJlIHN0 eWxlZCBieSB0aGlyZCBwYXJ0eSB3ZWIgZGVzaWduZXJzLgoKR2Vuc2hpIG9uIHRoZSBvdGhlciBo YW5kIGlzIGFuIFhNTCB0ZW1wbGF0ZSBlbmdpbmUuIEFzIGEgcmVzdWx0IG9mIHRoYXQgaXQncyBz bG93ZXIgYnV0IGFsc28gImNvbnRleHQgYXdhcmUiLiBJdCBrbm93cyB3aGVuIGl0J3MgcHJvY2Vz c2luZyBhIENEQVRBIHNlY3Rpb24sIGl0IGtub3dzIHdoZW4gaXQncyBpbnNpZGUgYSB0YWcgb3Ig YW4gYXR0cmlidXRlIGV0Yy4gVGhpcyBtYWtlcyBpdCBwb3NzaWJsZSB0byBkZWZlbmQgWFNTIGlu IGFuIGF1dG9tYXRpYyB3YXkuIFBlciBkZWZhdWx0IEdlbnNoaSBpbnNlcnRzIHRoZSB0ZXh0IGlu dG8gdGhlIG91dHB1dCBzdHJlYW0gYXMgdGV4dCBhbmQgbm90IGFzIG1hcmt1cC4gVGhhdCBtZWFu cyBhbGwgdGhlIEhUTUwgZW50aXRpZXMgYXJlIGF1dG9tYXRpY2FsbHkgZXNjYXBlZCBmb3IgeW91 LiBBbmQgYmVjYXVzZSBpdCdzIHN0cmVhbSBiYXNlZCB5b3UgY2FuIHJld3JpdGUgc3RyZWFtcyBk dXJpbmcgdGhlIHJlbmRlcmluZyBwcm9jZXNzLiBUaGlzIG1ha2VzIGl0IHBvc3NpYmxlIHRvIGZp bGwgZm9ybSBmaWVsZHMgYXV0b21hdGljYWxseSwgdXNlIFhJbmNsdWRlIGZvciBzaW1wbGUgbGF5 b3V0IHRlbXBsYXRlcyBhbmQgYSBsb3QgbW9yZS4gWW91IGNhbiBldmVuIHRyYW5zbGF0ZSB5b3Vy IFhNTCBiYXNlZCB0ZW1wbGF0ZXMgaW50byBIVE1MNCBvbiB0aGUgZmx5LiBTbyB5b3UgY2FuIHVz ZSB5b3VyIFhNTCB0b29sIGNoYWluIGludGVybmFsbHkgYW5kIG91dHB1dCBIVE1MNCBhbmQgdXNl IHRoZSBiZXN0IG9mIGJvdGggd29ybGRzLiBCdXQgYmVjYXVzZSBvZiB0aGlzIGhpZ2ggZmxleGli aWxpdHkgR2Vuc2hpIGFsc28gaGFzIHNvbWUgcHJvYmxlbXMgdG8gZmlnaHQ6IFlvdSBuZWVkIHRv IGhhdmUgWE1MIGtub3dsZWRnZSB0byB1c2UgaXQuIE5vIHByb2JsZW0gaWYgeW91IGFyZSBhIHBy b2dyYW1tZXIsIGJ1dCBub3QgdGhhdCBnb29kIGlmIHlvdSBhcmUgYSB3ZWIgZGVzaWduZXIgZG9p bmcgZmFuY3kgbGF5b3V0cy4gWW91IGFyZSBhbHNvIGZvcmNlZCB0byB1c2UgWE1MIHRlbXBsYXRl cyBldmVyeXdoZXJlLiBJdCdzIHRydWUgdGhhdCBHZW5zaGkgaGFzIHRleHQgdGVtcGxhdGVzIHRv byB0byBmaWxsIHRoZSBnYXBzLCBidXQgdGhleSBhcmUgbm90IGNvbXBhcmFibGUgd2l0aCByZWFs IHRleHQgdGVtcGxhdGUgZW5naW5lcyBhbmQgeW91IGFyZSBzdGlsbCBvcGVyYXRpbmcgb24gYW4g WE1MIHN0cmVhbSwganVzdCB0aGF0IHlvdSBkb24ndCBzZWUgaXQuIEFuZCBsYXN0bHk6IHRoaXMg d2hvbGUgc3RyZWFtIHByb2Nlc3NpbmcgbWFrZXMgR2Vuc2hpIHNsb3cuIE5vdCBzbyBzbG93IHRo YXQgeW91IGNhbid0IHVzZSBpdCBmb3IgYmlnIGFwcGxpY2F0aW9ucywgYnV0IG5vdGljZWFibHkg c2xvd2VyIHRoYW4gTWFrbyBvciBKaW5qYS4KCklmIHlvdSBhcmUgdXNpbmcgWE1MIGFueXdheXMg aW4geW91ciBhcHBsaWNhdGlvbiwgR2Vuc2hpIGlzIGEgdmVyeSBnb29kIGlkZWEuIEFsc28gaWYg eW91IGRvbid0IGhhdmUgdGVtcGxhdGUgZGVzaWduZXJzIHRoYXQgZG9uJ3Qga25vdyBYTUwgb3Ig aWYgcGVyZm9ybWFuY2UgaXMgbm90IHRoYXQgbXVjaCBvZiBhIHByb2JsZW0uIE1vc3Qgb2YgdGhl IHRpbWUgdGhlIGJvdHRsZW5lY2sgaXMgdGhlIGRhdGFiYXNlIGFueXdheXMuIEkgbmV2ZXIgaGFk IHJlYWwgcHJvYmxlbXMgd2l0aCBHZW5zaGkgcGVyZm9ybWFuY2Ugc28gZmFyLgoKSSBob3BlIHRo aXMgcG9zdCBzdW1zIHVwIHdoeSBJJ20gdXNpbmcgYWxsIHRocmVlIHRlbXBsYXRlIGVuZ2luZXMg YW5kIHdoeSBJIHRoaW5rIHdlIHNob3VsZCBiZSBoYXBweSB0aGF0IHdlIGNhbiBjaG9zZSBiZXR3 ZWVuIGEgY291cGxlIG9mIHRlbXBsYXRlIGVuZ2luZXMgOi0pIFdoeSBJJ20gbm90IGNvdmVyaW5n IG90aGVyIHRlbXBsYXRlIGVuZ2luZXMgbGlrZSBDaGVldGFoIG9yIFNpbXBsZVRBTD8gTW9zdGx5 IGJlY2F1c2UgSSBsb29rZWQgYXQgdGhlbSwgdHJpZWQgdGhlbSBvdXQgYW5kIG5ldmVyIHVzZWQg dGhlbSBmb3Igc29tZXRoaW5nIGJpZy4gTW9zdGx5IGJlY2F1c2UgTWFrbyBsb29rcyBhIGxvdCBu aWNlciB0aGFuIENoZWV0YWggdG8gbWUgYW5kIFNpbXBsZVRBTCBpcyBmYXIgdG9vIG11Y2ggYXdh eSBmcm9tIFB5dGhvbiBmb3IgbWUuUwAAAAZwYXJzZXJTAAAABGh0bWxTAAAABWludHJvUlMAAAAA TAAA Braydon Fullercourier@braydon.comhttp://braydon.com/2008-01-01T23:35:12Znono0"I hope this post sums up why I’m using all three template engines and why I think we should be happy that we can chose between a couple of template engines :-)" Word! :) I am using Cheetah on a current project, and haven't run into any problems yet. I'll have to try out Mako and see how it compares, and what will work best for my different projects. I had a similar reaction to Django's templates at first, but haven't used them yet to get to know it better."I hope this post sums up why I’m using all three template engines and why I think we should be happy that we can chose between a couple of template engines :-)" Word! :) I am using Cheetah on a current project, and haven't run into any problems yet. I'll have to try out Mako and see how it compares, and what will work best for my different projects. I had a similar reaction to Django's templates at first, but haven't used them yet to get to know it better.SQAAAAJTAAAABGJvZHlSUwAAAdEiSSBob3BlIHRoaXMgcG9zdCBzdW1zIHVwIHdoeSBJ4oCZbSB1 c2luZyBhbGwgdGhyZWUgdGVtcGxhdGUgZW5naW5lcyBhbmQgd2h5IEkgdGhpbmsgd2Ugc2hvdWxk IGJlIGhhcHB5IHRoYXQgd2UgY2FuIGNob3NlIGJldHdlZW4gYSBjb3VwbGUgb2YgdGVtcGxhdGUg ZW5naW5lcyA6LSkiCgpXb3JkISA6KQoKSSBhbSB1c2luZyBDaGVldGFoIG9uIGEgY3VycmVudCBw cm9qZWN0LCBhbmQgaGF2ZW4ndCBydW4gaW50byBhbnkgcHJvYmxlbXMgeWV0LiBJJ2xsIGhhdmUg dG8gdHJ5IG91dCBNYWtvIGFuZCBzZWUgaG93IGl0IGNvbXBhcmVzLCBhbmQgd2hhdCB3aWxsIHdv cmsgYmVzdCBmb3IgbXkgZGlmZmVyZW50IHByb2plY3RzLiBJIGhhZCBhIHNpbWlsYXIgcmVhY3Rp b24gdG8gRGphbmdvJ3MgdGVtcGxhdGVzIGF0IGZpcnN0LCBidXQgaGF2ZW4ndCB1c2VkIHRoZW0g eWV0IHRvIGdldCB0byBrbm93IGl0IGJldHRlci5MAABTAAAABnBhcnNlclMAAAAEaHRtbA== Graham DumpletonGraham.Dumpleton@gmail.comhttp://blog.dscpl.com.au2008-01-02T02:02:42Znono0You must have been reading my mind as it was only a few days ago that I was trying to get hold of you on IRC to discuss your opinions on different templating solutions. You weren't around at the time though. One question I still have though about Jinja is, in practice what it's sandboxing really means, given that in Python it is pretty well impossible to create a restricted execution environment that you can't break out of in some way. So, what are the benefits of otherwise of sandboxing in Jinja?You must have been reading my mind as it was only a few days ago that I was trying to get hold of you on IRC to discuss your opinions on different templating solutions. You weren't around at the time though. One question I still have though about Jinja is, in practice what it's sandboxing really means, given that in Python it is pretty well impossible to create a restricted execution environment that you can't break out of in some way. So, what are the benefits of otherwise of sandboxing in Jinja?SQAAAAJTAAAABGJvZHlSUwAAAfhZb3UgbXVzdCBoYXZlIGJlZW4gcmVhZGluZyBteSBtaW5kIGFz IGl0IHdhcyBvbmx5IGEgZmV3IGRheXMgYWdvIHRoYXQgSSB3YXMgdHJ5aW5nIHRvIGdldCBob2xk IG9mIHlvdSBvbiBJUkMgdG8gZGlzY3VzcyB5b3VyIG9waW5pb25zIG9uIGRpZmZlcmVudCB0ZW1w bGF0aW5nIHNvbHV0aW9ucy4gWW91IHdlcmVuJ3QgYXJvdW5kIGF0IHRoZSB0aW1lIHRob3VnaC4K Ck9uZSBxdWVzdGlvbiBJIHN0aWxsIGhhdmUgdGhvdWdoIGFib3V0IEppbmphIGlzLCBpbiBwcmFj dGljZSB3aGF0IGl0J3Mgc2FuZGJveGluZyByZWFsbHkgbWVhbnMsIGdpdmVuIHRoYXQgaW4gUHl0 aG9uIGl0IGlzIHByZXR0eSB3ZWxsIGltcG9zc2libGUgdG8gY3JlYXRlIGEgcmVzdHJpY3RlZCBl eGVjdXRpb24gZW52aXJvbm1lbnQgdGhhdCB5b3UgY2FuJ3QgYnJlYWsgb3V0IG9mIGluIHNvbWUg d2F5LgoKU28sIHdoYXQgYXJlIHRoZSBiZW5lZml0cyBvZiBvdGhlcndpc2Ugb2Ygc2FuZGJveGlu ZyBpbiBKaW5qYT9MAABTAAAABnBhcnNlclMAAAAEaHRtbA== Armin Ronacherarmin.ronacher@active-4.comhttp://lucumr.pocoo.org/2008-01-02T09:05:51Znono0Before the big parser rewrite Jinja wandered through the AST and intercepted all dangerous operations. This basically works the same with the new parser too, but some things such as "item assignment unpacking during iteration" is not allowed in the new syntax and so there is no check for that any more. So basically what Jinja does currently is disallowing all access to attributes like "__subclasses__", disallowing attribute modifications on objects passed to the context, recursive includes, infinite loops etc. I think as long as you can limit the syntax to expressions there are ways to restrict Python enough to allow the execution of untrusted code.Before the big parser rewrite Jinja wandered through the AST and intercepted all dangerous operations. This basically works the same with the new parser too, but some things such as "item assignment unpacking during iteration" is not allowed in the new syntax and so there is no check for that any more. So basically what Jinja does currently is disallowing all access to attributes like "__subclasses__", disallowing attribute modifications on objects passed to the context, recursive includes, infinite loops etc. I think as long as you can limit the syntax to expressions there are ways to restrict Python enough to allow the execution of untrusted code.SQAAAAJTAAAABGJvZHlSUwAAApNCZWZvcmUgdGhlIGJpZyBwYXJzZXIgcmV3cml0ZSBKaW5qYSB3 YW5kZXJlZCB0aHJvdWdoIHRoZSBBU1QgYW5kIGludGVyY2VwdGVkIGFsbCBkYW5nZXJvdXMgb3Bl cmF0aW9ucy4gVGhpcyBiYXNpY2FsbHkgd29ya3MgdGhlIHNhbWUgd2l0aCB0aGUgbmV3IHBhcnNl ciB0b28sIGJ1dCBzb21lIHRoaW5ncyBzdWNoIGFzICJpdGVtIGFzc2lnbm1lbnQgdW5wYWNraW5n IGR1cmluZyBpdGVyYXRpb24iIGlzIG5vdCBhbGxvd2VkIGluIHRoZSBuZXcgc3ludGF4IGFuZCBz byB0aGVyZSBpcyBubyBjaGVjayBmb3IgdGhhdCBhbnkgbW9yZS4KClNvIGJhc2ljYWxseSB3aGF0 IEppbmphIGRvZXMgY3VycmVudGx5IGlzIGRpc2FsbG93aW5nIGFsbCBhY2Nlc3MgdG8gYXR0cmli dXRlcyBsaWtlICJfX3N1YmNsYXNzZXNfXyIsIGRpc2FsbG93aW5nIGF0dHJpYnV0ZSBtb2RpZmlj YXRpb25zIG9uIG9iamVjdHMgcGFzc2VkIHRvIHRoZSBjb250ZXh0LCByZWN1cnNpdmUgaW5jbHVk ZXMsIGluZmluaXRlIGxvb3BzIGV0Yy4KCkkgdGhpbmsgYXMgbG9uZyBhcyB5b3UgY2FuIGxpbWl0 IHRoZSBzeW50YXggdG8gZXhwcmVzc2lvbnMgdGhlcmUgYXJlIHdheXMgdG8gcmVzdHJpY3QgUHl0 aG9uIGVub3VnaCB0byBhbGxvdyB0aGUgZXhlY3V0aW9uIG9mIHVudHJ1c3RlZCBjb2RlLkwAAFMA AAAGcGFyc2VyUwAAAARodG1s Eric Larsoneric@ionrock.orghttp://ionrock.org/blog/2008-01-02T21:31:59Znono0Great overview of these excellent templating libraries. If you (or anyone else) is interested in an XSLT based WSGI middleware templating solution, there is XSLTemplates (http://code.google.com/p/xsltemplates). I am the author, but really it is just a simple way to use XSLT with 4Suite/Amara within WSGI web applications. I tried to use Kid and just couldn't grab onto the mix between XSLT and other templating languages, so I looked into BuffetXSLT, which was lacking the more obvious templating pieces like passing in parameters and data structures (node-set in XSLT). This lead me to XSLTemplates. I'm aiming at making it easy to do things like adding your own helper functions and sending parameters and node-sets to templates. If any one does try it out, feel free to send along comments or suggestions.Great overview of these excellent templating libraries. If you (or anyone else) is interested in an XSLT based WSGI middleware templating solution, there is XSLTemplates (http://code.google.com/p/xsltemplates). I am the author, but really it is just a simple way to use XSLT with 4Suite/Amara within WSGI web applications. I tried to use Kid and just couldn't grab onto the mix between XSLT and other templating languages, so I looked into BuffetXSLT, which was lacking the more obvious templating pieces like passing in parameters and data structures (node-set in XSLT). This lead me to XSLTemplates. I'm aiming at making it easy to do things like adding your own helper functions and sending parameters and node-sets to templates. If any one does try it out, feel free to send along comments or suggestions.SQAAAAJTAAAABGJvZHlSUwAAAy9HcmVhdCBvdmVydmlldyBvZiB0aGVzZSBleGNlbGxlbnQgdGVt cGxhdGluZyBsaWJyYXJpZXMuIAoKSWYgeW91IChvciBhbnlvbmUgZWxzZSkgaXMgaW50ZXJlc3Rl ZCBpbiBhbiBYU0xUIGJhc2VkIFdTR0kgbWlkZGxld2FyZSB0ZW1wbGF0aW5nIHNvbHV0aW9uLCB0 aGVyZSBpcyBYU0xUZW1wbGF0ZXMgKGh0dHA6Ly9jb2RlLmdvb2dsZS5jb20vcC94c2x0ZW1wbGF0 ZXMpLiBJIGFtIHRoZSBhdXRob3IsIGJ1dCByZWFsbHkgaXQgaXMganVzdCBhIHNpbXBsZSB3YXkg dG8gdXNlIFhTTFQgd2l0aCA0U3VpdGUvQW1hcmEgd2l0aGluIFdTR0kgd2ViIGFwcGxpY2F0aW9u cy4gCgpJIHRyaWVkIHRvIHVzZSBLaWQgYW5kIGp1c3QgY291bGRuJ3QgZ3JhYiBvbnRvIHRoZSBt aXggYmV0d2VlbiBYU0xUIGFuZCBvdGhlciB0ZW1wbGF0aW5nIGxhbmd1YWdlcywgc28gSSBsb29r ZWQgaW50byBCdWZmZXRYU0xULCB3aGljaCB3YXMgbGFja2luZyB0aGUgbW9yZSBvYnZpb3VzIHRl bXBsYXRpbmcgcGllY2VzIGxpa2UgcGFzc2luZyBpbiBwYXJhbWV0ZXJzIGFuZCBkYXRhIHN0cnVj dHVyZXMgKG5vZGUtc2V0IGluIFhTTFQpLiBUaGlzIGxlYWQgbWUgdG8gWFNMVGVtcGxhdGVzLiAK CkknbSBhaW1pbmcgYXQgbWFraW5nIGl0IGVhc3kgdG8gZG8gdGhpbmdzIGxpa2UgYWRkaW5nIHlv dXIgb3duIGhlbHBlciBmdW5jdGlvbnMgYW5kIHNlbmRpbmcgcGFyYW1ldGVycyBhbmQgbm9kZS1z ZXRzIHRvIHRlbXBsYXRlcy4gSWYgYW55IG9uZSBkb2VzIHRyeSBpdCBvdXQsIGZlZWwgZnJlZSB0 byBzZW5kIGFsb25nIGNvbW1lbnRzIG9yIHN1Z2dlc3Rpb25zLkwAAFMAAAAGcGFyc2VyUwAAAARo dG1s No, no, It’s just restinghttp://lucumr.pocoo.org/cogitations/2007/12/23/no-no-its-just-resting/2007-12-23T22:28:10Z2007-12-23T22:28:10ZArmin Ronacherno-no-its-just-restingyesyes2Currently on <a href="http://pocoo.org/">pocoo.org</a> is a semi static webpage with a completely unmaintained semi static blog and completely outdated information. While pocoo is not dead yet (just resting) it's time to put something on the front page that represents the current state of the situation in a better way. Let's see if we can get that updated in the next two weeks. Oh, and TextPress is now up to date again, a bunch of bugs were fixed and we're much nearer to a release than some weeks ago, but unfortunately we're behind the roadmap once again :-)Currently on <a href="http://pocoo.org/">pocoo.org</a> is a semi static webpage with a completely unmaintained semi static blog and completely outdated information. While pocoo is not dead yet (just resting) it's time to put something on the front page that represents the current state of the situation in a better way. Let's see if we can get that updated in the next two weeks. Oh, and TextPress is now up to date again, a bunch of bugs were fixed and we're much nearer to a release than some weeks ago, but unfortunately we're behind the roadmap once again :-)SQAAAANTAAAABGJvZHlSUwAAAA1DdXJyZW50bHkgb24gTAABRVMAAAABYUwAAE0AAVMAAAAEaHJl ZlMAAAARaHR0cDovL3BvY29vLm9yZy9TAAAACXBvY29vLm9yZ1MAAAH/IGlzIGEgc2VtaSBzdGF0 aWMgd2VicGFnZSB3aXRoIGEgY29tcGxldGVseSB1bm1haW50YWluZWQgc2VtaSBzdGF0aWMgYmxv ZyBhbmQgY29tcGxldGVseSBvdXRkYXRlZCBpbmZvcm1hdGlvbi4gV2hpbGUgcG9jb28gaXMgbm90 IGRlYWQgeWV0IChqdXN0IHJlc3RpbmcpIGl0J3MgdGltZSB0byBwdXQgc29tZXRoaW5nIG9uIHRo ZSBmcm9udCBwYWdlIHRoYXQgcmVwcmVzZW50cyB0aGUgY3VycmVudCBzdGF0ZSBvZiB0aGUgc2l0 dWF0aW9uIGluIGEgYmV0dGVyIHdheS4KCkxldCdzIHNlZSBpZiB3ZSBjYW4gZ2V0IHRoYXQgdXBk YXRlZCBpbiB0aGUgbmV4dCB0d28gd2Vla3MuIE9oLCBhbmQgVGV4dFByZXNzIGlzIG5vdyB1cCB0 byBkYXRlIGFnYWluLCBhIGJ1bmNoIG9mIGJ1Z3Mgd2VyZSBmaXhlZCBhbmQgd2UncmUgbXVjaCBu ZWFyZXIgdG8gYSByZWxlYXNlIHRoYW4gc29tZSB3ZWVrcyBhZ28sIGJ1dCB1bmZvcnR1bmF0ZWx5 IHdlJ3JlIGJlaGluZCB0aGUgcm9hZG1hcCBvbmNlIGFnYWluIDotKVMAAAAGcGFyc2VyUwAAAARo dG1sUwAAAAVpbnRyb1JTAAAAAEwAAA== johnjohn.w@web.de2007-12-28T18:18:58Znono0Ahh, you're just five days late, you can still release it in 2007 ;) But great to see progress !!Ahh, you're just five days late, you can still release it in 2007 ;) But great to see progress !!SQAAAAJTAAAABGJvZHlSUwAAAGJBaGgsIHlvdSdyZSBqdXN0IGZpdmUgZGF5cyBsYXRlLCB5b3Ug Y2FuIHN0aWxsIHJlbGVhc2UgaXQgaW4gMjAwNyA7KQoKQnV0IGdyZWF0IHRvIHNlZSBwcm9ncmVz cyAhIUwAAFMAAAAGcGFyc2VyUwAAAARodG1s Merry Christmas!http://lucumr.pocoo.org/cogitations/2007/12/22/merry-christmas/2007-12-22T17:46:02Z2007-12-22T17:46:02ZArmin Ronachermerry-christmasyesyes2Again we're coming close to December the 24th, a day many people will spend with their families or friends to celebrate. I want to use this Christmas to say thank you to a couple of persons that helped me a lot the last years, either directly or indirectly due to their tremendous work in the Open Source community. First of all I want to thank you Georg Brandl, who you thought me a lot about Python's internals. You had an answer to pretty all of my questions and you were the first person I worked with on a real Open Source project. Even though we still don't have Pocoo released it was great fun to work with you. Thank you Benjamin Wiegand, Christoph Hack and Christopher Grebs for all your code contributions and your work on Pocoo and the Pocoo libraries. A big thank you to the whole ubuntuusers team, also those of you who left the team in the past. We had many problems in the past but I looking back those three years I think most of the time we worked together in the past were plesant :-) Thank you Marek Kubica for all those nice discussions we've had. And thanks for your work on the German Python community and your patches to the Pocoo libraries. I guess the python forum and wiki wouldn't be the same without you. Of course a big thank you to Alexander Schremmer who keeps the pocoo server running. Learned a lot from you :-) Also a big thank you to Fritz Cizmarov who introduced me to ubuntu. Unfortunately he passed away two years ago but I'll never forget him. I also want to thank Mike Bayers for his work on SQLAlchemy which I use on a daily basis, all the guys over at edgewall for Genshi and Trac, the mercurial people for their ass-kicking DVCS, Martijn Faassen for lxml and all the people working on ubuntu. Keep up the good work and Merry Christmas to you all!Again we're coming close to December the 24th, a day many people will spend with their families or friends to celebrate. I want to use this Christmas to say thank you to a couple of persons that helped me a lot the last years, either directly or indirectly due to their tremendous work in the Open Source community. First of all I want to thank you Georg Brandl, who you thought me a lot about Python's internals. You had an answer to pretty all of my questions and you were the first person I worked with on a real Open Source project. Even though we still don't have Pocoo released it was great fun to work with you. Thank you Benjamin Wiegand, Christoph Hack and Christopher Grebs for all your code contributions and your work on Pocoo and the Pocoo libraries. A big thank you to the whole ubuntuusers team, also those of you who left the team in the past. We had many problems in the past but I looking back those three years I think most of the time we worked together in the past were plesant :-) Thank you Marek Kubica for all those nice discussions we've had. And thanks for your work on the German Python community and your patches to the Pocoo libraries. I guess the python forum and wiki wouldn't be the same without you. Of course a big thank you to Alexander Schremmer who keeps the pocoo server running. Learned a lot from you :-) Also a big thank you to Fritz Cizmarov who introduced me to ubuntu. Unfortunately he passed away two years ago but I'll never forget him. I also want to thank Mike Bayers for his work on SQLAlchemy which I use on a daily basis, all the guys over at edgewall for Genshi and Trac, the mercurial people for their ass-kicking DVCS, Martijn Faassen for lxml and all the people working on ubuntu. Keep up the good work and Merry Christmas to you all!SQAAAANTAAAABGJvZHlSUwAABwVBZ2FpbiB3ZSdyZSBjb21pbmcgY2xvc2UgdG8gRGVjZW1iZXIg dGhlIDI0dGgsIGEgZGF5IG1hbnkgcGVvcGxlIHdpbGwgc3BlbmQgd2l0aCB0aGVpciBmYW1pbGll cyBvciBmcmllbmRzIHRvIGNlbGVicmF0ZS4gSSB3YW50IHRvIHVzZSB0aGlzIENocmlzdG1hcyB0 byBzYXkgdGhhbmsgeW91IHRvIGEgY291cGxlIG9mIHBlcnNvbnMgdGhhdCBoZWxwZWQgbWUgYSBs b3QgdGhlIGxhc3QgeWVhcnMsIGVpdGhlciBkaXJlY3RseSBvciBpbmRpcmVjdGx5IGR1ZSB0byB0 aGVpciB0cmVtZW5kb3VzIHdvcmsgaW4gdGhlIE9wZW4gU291cmNlIGNvbW11bml0eS4KCkZpcnN0 IG9mIGFsbCBJIHdhbnQgdG8gdGhhbmsgeW91IEdlb3JnIEJyYW5kbCwgd2hvIHlvdSB0aG91Z2h0 IG1lIGEgbG90IGFib3V0IFB5dGhvbidzIGludGVybmFscy4gWW91IGhhZCBhbiBhbnN3ZXIgdG8g cHJldHR5IGFsbCBvZiBteSBxdWVzdGlvbnMgYW5kIHlvdSB3ZXJlIHRoZSBmaXJzdCBwZXJzb24g SSB3b3JrZWQgd2l0aCBvbiBhIHJlYWwgT3BlbiBTb3VyY2UgcHJvamVjdC4gRXZlbiB0aG91Z2gg d2Ugc3RpbGwgZG9uJ3QgaGF2ZSBQb2NvbyByZWxlYXNlZCBpdCB3YXMgZ3JlYXQgZnVuIHRvIHdv cmsgd2l0aCB5b3UuCgpUaGFuayB5b3UgQmVuamFtaW4gV2llZ2FuZCwgQ2hyaXN0b3BoIEhhY2sg YW5kIENocmlzdG9waGVyIEdyZWJzIGZvciBhbGwgeW91ciBjb2RlIGNvbnRyaWJ1dGlvbnMgYW5k IHlvdXIgd29yayBvbiBQb2NvbyBhbmQgdGhlIFBvY29vIGxpYnJhcmllcy4KCkEgYmlnIHRoYW5r IHlvdSB0byB0aGUgd2hvbGUgdWJ1bnR1dXNlcnMgdGVhbSwgYWxzbyB0aG9zZSBvZiB5b3Ugd2hv IGxlZnQgdGhlIHRlYW0gaW4gdGhlIHBhc3QuIFdlIGhhZCBtYW55IHByb2JsZW1zIGluIHRoZSBw YXN0IGJ1dCBJIGxvb2tpbmcgYmFjayB0aG9zZSB0aHJlZSB5ZWFycyBJIHRoaW5rIG1vc3Qgb2Yg dGhlIHRpbWUgd2Ugd29ya2VkIHRvZ2V0aGVyIGluIHRoZSBwYXN0IHdlcmUgcGxlc2FudCA6LSkK ClRoYW5rIHlvdSBNYXJlayBLdWJpY2EgZm9yIGFsbCB0aG9zZSBuaWNlIGRpc2N1c3Npb25zIHdl J3ZlIGhhZC4gQW5kIHRoYW5rcyBmb3IgeW91ciB3b3JrIG9uIHRoZSBHZXJtYW4gUHl0aG9uIGNv bW11bml0eSBhbmQgeW91ciBwYXRjaGVzIHRvIHRoZSBQb2NvbyBsaWJyYXJpZXMuIEkgZ3Vlc3Mg dGhlIHB5dGhvbiBmb3J1bSBhbmQgd2lraSB3b3VsZG4ndCBiZSB0aGUgc2FtZSB3aXRob3V0IHlv dS4KCk9mIGNvdXJzZSBhIGJpZyB0aGFuayB5b3UgdG8gQWxleGFuZGVyIFNjaHJlbW1lciB3aG8g a2VlcHMgdGhlIHBvY29vIHNlcnZlciBydW5uaW5nLiBMZWFybmVkIGEgbG90IGZyb20geW91IDot KQoKQWxzbyBhIGJpZyB0aGFuayB5b3UgdG8gRnJpdHogQ2l6bWFyb3Ygd2hvIGludHJvZHVjZWQg bWUgdG8gdWJ1bnR1LiBVbmZvcnR1bmF0ZWx5IGhlIHBhc3NlZCBhd2F5IHR3byB5ZWFycyBhZ28g YnV0IEknbGwgbmV2ZXIgZm9yZ2V0IGhpbS4KCkkgYWxzbyB3YW50IHRvIHRoYW5rIE1pa2UgQmF5 ZXJzIGZvciBoaXMgd29yayBvbiBTUUxBbGNoZW15IHdoaWNoIEkgdXNlIG9uIGEgZGFpbHkgYmFz aXMsIGFsbCB0aGUgZ3V5cyBvdmVyIGF0IGVkZ2V3YWxsIGZvciBHZW5zaGkgYW5kIFRyYWMsIHRo ZSBtZXJjdXJpYWwgcGVvcGxlIGZvciB0aGVpciBhc3Mta2lja2luZyBEVkNTLCBNYXJ0aWpuIEZh YXNzZW4gZm9yIGx4bWwgYW5kIGFsbCB0aGUgcGVvcGxlIHdvcmtpbmcgb24gdWJ1bnR1LgoKS2Vl cCB1cCB0aGUgZ29vZCB3b3JrIGFuZCBNZXJyeSBDaHJpc3RtYXMgdG8geW91IGFsbCFMAABTAAAA BnBhcnNlclMAAAAEaHRtbFMAAAAFaW50cm9SUwAAAABMAAA= This Week in Pushin’ Bugs…http://lucumr.pocoo.org/cogitations/2007/12/17/this-week-in-pushin-bugs/2007-12-17T12:23:50Z2007-12-17T12:23:50ZArmin Ronacherthis-week-in-pushin-bugsyesyes2<a href="https://bugs.launchpad.net/ubuntu/+source/xkeyboard-config/+bug/59572">This wonderful feature request for the German Keyboard Layouts</a>. Open since quite a while and easy to fix (if someone knows how to do it). And if one finds some intuitive places for emdash, endash, ellipsis and some other often used typographical characters and gets that into the next LTS he/she gets a hug :-)<a href="https://bugs.launchpad.net/ubuntu/+source/xkeyboard-config/+bug/59572">This wonderful feature request for the German Keyboard Layouts</a>. Open since quite a while and easy to fix (if someone knows how to do it). And if one finds some intuitive places for emdash, endash, ellipsis and some other often used typographical characters and gets that into the next LTS he/she gets a hug :-)SQAAAANTAAAABGJvZHlSUwAAAABMAAFFUwAAAAFhTAAATQABUwAAAARocmVmUwAAAEVodHRwczov L2J1Z3MubGF1bmNocGFkLm5ldC91YnVudHUvK3NvdXJjZS94a2V5Ym9hcmQtY29uZmlnLytidWcv NTk1NzJTAAAAPlRoaXMgd29uZGVyZnVsIGZlYXR1cmUgcmVxdWVzdCBmb3IgdGhlIEdlcm1hbiBL ZXlib2FyZCBMYXlvdXRzUwAAAPkuIE9wZW4gc2luY2UgcXVpdGUgYSB3aGlsZSBhbmQgZWFzeSB0 byBmaXggKGlmIHNvbWVvbmUga25vd3MgaG93IHRvIGRvIGl0KS4KCkFuZCBpZiBvbmUgZmluZHMg c29tZSBpbnR1aXRpdmUgcGxhY2VzIGZvciBlbWRhc2gsIGVuZGFzaCwgZWxsaXBzaXMgYW5kIHNv bWUgb3RoZXIgb2Z0ZW4gdXNlZCB0eXBvZ3JhcGhpY2FsIGNoYXJhY3RlcnMgYW5kIGdldHMgdGhh dCBpbnRvIHRoZSBuZXh0IExUUyBoZS9zaGUgZ2V0cyBhIGh1ZyA6LSlTAAAABnBhcnNlclMAAAAE aHRtbFMAAAAFaW50cm9SUwAAAABMAAA= Werkzeug Identity Crisis?http://lucumr.pocoo.org/cogitations/2007/12/15/werkzeug-identity-crisis/2007-12-15T22:00:48Z2007-12-15T22:00:48ZArmin Ronacherwerkzeug-identity-crisisyesyes2After the <a href="http://werkzeug.pocoo.org/">Werkzeug</a> 0.1 release I got some feedback by <a href="http://blog.ianbicking.org/">Ian Bicking</a>. Summarized it was about why Werkzeug pretty much does what webob does. Afterwards I thought about the issue and talked with some current Werkzeug users. And to sum it up: Werkzeug stays a standalone library without webob dependency and will stay with the current request/response object implementation. While I agree that there are things webob does what Werkzeug (currently?) does not provide such as byteranges I still think it's on the right path. We have now a solid feature set in Werkzeug itself such as form data parsing, file uploads, conditional requests, simple redirects, useful exceptions, a good routing system, a simple bridge to wsgiref for a development server, a small helper library for management scripts and much more and additionally an optional contrib package with dozens of small helpers such as client side sessions, utilities for application sessions, the iterio library, a stream limiter for Django applications etc. Even more important than having everything you need to get started with WSGI in one library the implementation is easy to understand, fast and written in a way that you will never hit a border. If you find a piece of code in Werkzeug that only solves 90% of your problem but provides absolute no way without side effects to get the full 100% solution that's a bug and should be fixed. The minimal configuration you need to get a full featured web app running in a production environment with Werkzeug is currently something like Werkzeug + Genshi + SQLAlchemy + flup. Makes a total of four dependencies. It's not like I think dependencies are problems but what I noticed so far is the more libraries a user has to install the higher the number of problems and the lower the number of happy users. This is one thing Django does right: install django and you're done. If you don't like that philosophy there is pylons with a whole string of dependencies ;-)After the <a href="http://werkzeug.pocoo.org/">Werkzeug</a> 0.1 release I got some feedback by <a href="http://blog.ianbicking.org/">Ian Bicking</a>. Summarized it was about why Werkzeug pretty much does what webob does. Afterwards I thought about the issue and talked with some current Werkzeug users. And to sum it up: Werkzeug stays a standalone library without webob dependency and will stay with the current request/response object implementation. While I agree that there are things webob does what Werkzeug (currently?) does not provide such as byteranges I still think it's on the right path. We have now a solid feature set in Werkzeug itself such as form data parsing, file uploads, conditional requests, simple redirects, useful exceptions, a good routing system, a simple bridge to wsgiref for a development server, a small helper library for management scripts and much more and additionally an optional contrib package with dozens of small helpers such as client side sessions, utilities for application sessions, the iterio library, a stream limiter for Django applications etc. Even more important than having everything you need to get started with WSGI in one library the implementation is easy to understand, fast and written in a way that you will never hit a border. If you find a piece of code in Werkzeug that only solves 90% of your problem but provides absolute no way without side effects to get the full 100% solution that's a bug and should be fixed. The minimal configuration you need to get a full featured web app running in a production environment with Werkzeug is currently something like Werkzeug + Genshi + SQLAlchemy + flup. Makes a total of four dependencies. It's not like I think dependencies are problems but what I noticed so far is the more libraries a user has to install the higher the number of problems and the lower the number of happy users. This is one thing Django does right: install django and you're done. If you don't like that philosophy there is pylons with a whole string of dependencies ;-)SQAAAANTAAAABGJvZHlSUwAAAApBZnRlciB0aGUgTAACRVMAAAABYUwAAE0AAVMAAAAEaHJlZlMA AAAaaHR0cDovL3dlcmt6ZXVnLnBvY29vLm9yZy9TAAAACFdlcmt6ZXVnUwAAACQgMC4xIHJlbGVh c2UgSSBnb3Qgc29tZSBmZWVkYmFjayBieSBFUwAAAAFhTAAATQABUwAAAARocmVmUwAAABtodHRw Oi8vYmxvZy5pYW5iaWNraW5nLm9yZy9TAAAAC0lhbiBCaWNraW5nUwAAB3EuIFN1bW1hcml6ZWQg aXQgd2FzIGFib3V0IHdoeSBXZXJremV1ZyBwcmV0dHkgbXVjaCBkb2VzIHdoYXQgd2Vib2IgZG9l cy4gQWZ0ZXJ3YXJkcyBJIHRob3VnaHQgYWJvdXQgdGhlIGlzc3VlIGFuZCB0YWxrZWQgd2l0aCBz b21lIGN1cnJlbnQgV2Vya3pldWcgdXNlcnMuIEFuZCB0byBzdW0gaXQgdXA6IFdlcmt6ZXVnIHN0 YXlzIGEgc3RhbmRhbG9uZSBsaWJyYXJ5IHdpdGhvdXQgd2Vib2IgZGVwZW5kZW5jeSBhbmQgd2ls bCBzdGF5IHdpdGggdGhlIGN1cnJlbnQgcmVxdWVzdC9yZXNwb25zZSBvYmplY3QgaW1wbGVtZW50 YXRpb24uCgpXaGlsZSBJIGFncmVlIHRoYXQgdGhlcmUgYXJlIHRoaW5ncyB3ZWJvYiBkb2VzIHdo YXQgV2Vya3pldWcgKGN1cnJlbnRseT8pIGRvZXMgbm90IHByb3ZpZGUgc3VjaCBhcyBieXRlcmFu Z2VzIEkgc3RpbGwgdGhpbmsgaXQncyBvbiB0aGUgcmlnaHQgcGF0aC4gV2UgaGF2ZSBub3cgYSBz b2xpZCBmZWF0dXJlIHNldCBpbiBXZXJremV1ZyBpdHNlbGYgc3VjaCBhcyBmb3JtIGRhdGEgcGFy c2luZywgZmlsZSB1cGxvYWRzLCBjb25kaXRpb25hbCByZXF1ZXN0cywgc2ltcGxlIHJlZGlyZWN0 cywgdXNlZnVsIGV4Y2VwdGlvbnMsIGEgZ29vZCByb3V0aW5nIHN5c3RlbSwgYSBzaW1wbGUgYnJp ZGdlIHRvIHdzZ2lyZWYgZm9yIGEgZGV2ZWxvcG1lbnQgc2VydmVyLCBhIHNtYWxsIGhlbHBlciBs aWJyYXJ5IGZvciBtYW5hZ2VtZW50IHNjcmlwdHMgYW5kIG11Y2ggbW9yZSBhbmQgYWRkaXRpb25h bGx5IGFuIG9wdGlvbmFsIGNvbnRyaWIgcGFja2FnZSB3aXRoIGRvemVucyBvZiBzbWFsbCBoZWxw ZXJzIHN1Y2ggYXMgY2xpZW50IHNpZGUgc2Vzc2lvbnMsIHV0aWxpdGllcyBmb3IgYXBwbGljYXRp b24gc2Vzc2lvbnMsIHRoZSBpdGVyaW8gbGlicmFyeSwgYSBzdHJlYW0gbGltaXRlciBmb3IgRGph bmdvIGFwcGxpY2F0aW9ucyBldGMuCgpFdmVuIG1vcmUgaW1wb3J0YW50IHRoYW4gaGF2aW5nIGV2 ZXJ5dGhpbmcgeW91IG5lZWQgdG8gZ2V0IHN0YXJ0ZWQgd2l0aCBXU0dJIGluIG9uZSBsaWJyYXJ5 IHRoZSBpbXBsZW1lbnRhdGlvbiBpcyBlYXN5IHRvIHVuZGVyc3RhbmQsIGZhc3QgYW5kIHdyaXR0 ZW4gaW4gYSB3YXkgdGhhdCB5b3Ugd2lsbCBuZXZlciBoaXQgYSBib3JkZXIuIElmIHlvdSBmaW5k IGEgcGllY2Ugb2YgY29kZSBpbiBXZXJremV1ZyB0aGF0IG9ubHkgc29sdmVzIDkwJSBvZiB5b3Vy IHByb2JsZW0gYnV0IHByb3ZpZGVzIGFic29sdXRlIG5vIHdheSB3aXRob3V0IHNpZGUgZWZmZWN0 cyB0byBnZXQgdGhlIGZ1bGwgMTAwJSBzb2x1dGlvbiB0aGF0J3MgYSBidWcgYW5kIHNob3VsZCBi ZSBmaXhlZC4KClRoZSBtaW5pbWFsIGNvbmZpZ3VyYXRpb24geW91IG5lZWQgdG8gZ2V0IGEgZnVs bCBmZWF0dXJlZCB3ZWIgYXBwIHJ1bm5pbmcgaW4gYSBwcm9kdWN0aW9uIGVudmlyb25tZW50IHdp dGggV2Vya3pldWcgaXMgY3VycmVudGx5IHNvbWV0aGluZyBsaWtlIFdlcmt6ZXVnICsgR2Vuc2hp ICsgU1FMQWxjaGVteSArIGZsdXAuIE1ha2VzIGEgdG90YWwgb2YgZm91ciBkZXBlbmRlbmNpZXMu IEl0J3Mgbm90IGxpa2UgSSB0aGluayBkZXBlbmRlbmNpZXMgYXJlIHByb2JsZW1zIGJ1dCB3aGF0 IEkgbm90aWNlZCBzbyBmYXIgaXMgdGhlIG1vcmUgbGlicmFyaWVzIGEgdXNlciBoYXMgdG8gaW5z dGFsbCB0aGUgaGlnaGVyIHRoZSBudW1iZXIgb2YgcHJvYmxlbXMgYW5kIHRoZSBsb3dlciB0aGUg bnVtYmVyIG9mIGhhcHB5IHVzZXJzLiBUaGlzIGlzIG9uZSB0aGluZyBEamFuZ28gZG9lcyByaWdo dDogaW5zdGFsbCBkamFuZ28gYW5kIHlvdSdyZSBkb25lLgoKSWYgeW91IGRvbid0IGxpa2UgdGhh dCBwaGlsb3NvcGh5IHRoZXJlIGlzIHB5bG9ucyB3aXRoIGEgd2hvbGUgc3RyaW5nIG9mIGRlcGVu ZGVuY2llcyA7LSlTAAAABnBhcnNlclMAAAAEaHRtbFMAAAAFaW50cm9SUwAAAABMAAA= Braydon Fullercourier@braydon.comhttp://braydon.com2007-12-16T04:46:28Znono0I'm a fan of dependencies, but then again it's apt-get, and yum simplifies all that for us. Werkzeug looks interesting, I will need to try it soon.I'm a fan of dependencies, but then again it's apt-get, and yum simplifies all that for us. Werkzeug looks interesting, I will need to try it soon.SQAAAAJTAAAABGJvZHlSUwAAAJRJJ20gYSBmYW4gb2YgZGVwZW5kZW5jaWVzLCBidXQgdGhlbiBh Z2FpbiBpdCdzIGFwdC1nZXQsIGFuZCB5dW0gc2ltcGxpZmllcyBhbGwgdGhhdCBmb3IgdXMuCgpX ZXJremV1ZyBsb29rcyBpbnRlcmVzdGluZywgSSB3aWxsIG5lZWQgdG8gdHJ5IGl0IHNvb24uTAAA UwAAAAZwYXJzZXJTAAAABGh0bWw= Scott Benjaminscott.benjamin@gmail.comhttp://www.scott-benjamin.com/2007-12-17T03:47:07Znono0I think that Werkzeug is quite light on the dependencies. Those chosen, which just happens to be the developers choice, aren't as bad as 15 where you don't really have any idea how they fit together.I think that Werkzeug is quite light on the dependencies. Those chosen, which just happens to be the developers choice, aren't as bad as 15 where you don't really have any idea how they fit together.SQAAAAJTAAAABGJvZHlSUwAAAMhJIHRoaW5rIHRoYXQgV2Vya3pldWcgaXMgcXVpdGUgbGlnaHQg b24gdGhlIGRlcGVuZGVuY2llcy4gVGhvc2UgY2hvc2VuLCAgd2hpY2gganVzdCBoYXBwZW5zIHRv IGJlIHRoZSBkZXZlbG9wZXJzIGNob2ljZSwgYXJlbid0IGFzIGJhZCBhcyAxNSB3aGVyZSB5b3Ug ZG9uJ3QgcmVhbGx5IGhhdmUgYW55IGlkZWEgaG93IHRoZXkgZml0IHRvZ2V0aGVyLkwAAFMAAAAG cGFyc2VyUwAAAARodG1s Secure Client Side Sessionshttp://lucumr.pocoo.org/cogitations/2007/12/15/secure-client-side-sessions/2007-12-15T17:19:56Z2007-12-15T17:19:56ZArmin Ronachersecure-client-side-sessionsyesyes2Since a few changesets <a href="http://werkzeug.pocoo.org/">Werkzeug</a> provides a module for client side sessions. While it's of course not yet perfect I think it's an interesting approach and we're currently replacing django's sessions with Werkzeug's secure cookie. How does it work? Basically the data is stored as pickled data inside the cookie. The pickled data is hashed and added to the cookie too. Whenever the data is loaded from the cookie a new hash is created and the two hashes are compared. If they match the data is unserialized, otherwise a new SecureCookie object is created with empty data. As a matter of fact there is no "session key" so if you want to use it with django you have to fake the "session key" by inserting it into the data. We use the following session middleware as replacement for the django session middleware: <!-- PYGMENTS_CACHE><div class="highlight"><pre><span class="k">try</span><span class="p">:</span> <span class="k">from</span> <span class="nn">hashlib</span> <span class="k">import</span> <span class="n">md5</span> <span class="k">except</span> <span class="ne">ImportError</span><span class="p">:</span> <span class="k">from</span> <span class="nn">md5</span> <span class="k">import</span> <span class="n">md5</span> <span class="k">from</span> <span class="nn">time</span> <span class="k">import</span> <span class="n">time</span> <span class="k">from</span> <span class="nn">random</span> <span class="k">import</span> <span class="n">random</span> <span class="k">from</span> <span class="nn">django.conf</span> <span class="k">import</span> <span class="n">settings</span> <span class="k">from</span> <span class="nn">django.utils.http</span> <span class="k">import</span> <span class="n">cookie_date</span> <span class="k">from</span> <span class="nn">werkzeug.contrib.securecookie</span> <span class="k">import</span> <span class="n">SecureCookie</span> <span class="k">class</span> <span class="nc">Session</span><span class="p">(</span><span class="n">SecureCookie</span><span class="p">):</span> <span class="nd">@property</span> <span class="k">def</span> <span class="nf">session_key</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="k">if</span> <span class="ow">not</span> <span class="s">&#39;session_key&#39;</span> <span class="ow">in</span> <span class="bp">self</span><span class="p">:</span> <span class="bp">self</span><span class="p">[</span><span class="s">&#39;session_key&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">md5</span><span class="p">(</span><span class="s">&#39;</span><span class="si">%s%s%s</span><span class="s">&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="n">random</span><span class="p">(),</span> <span class="n">time</span><span class="p">(),</span> <span class="n">settings</span><span class="o">.</span><span class="n">SECRET_KEY</span><span class="p">))</span><span class="o">.</span><span class="n">hexdigest</span><span class="p">()</span> <span class="k">return</span> <span class="bp">self</span><span class="p">[</span><span class="s">&#39;session_key&#39;</span><span class="p">]</span> <span class="k">class</span> <span class="nc">ClientSideSessionMiddleware</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span> <span class="k">def</span> <span class="nf">process_request</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">request</span><span class="p">):</span> <span class="n">data</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">COOKIES</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">settings</span><span class="o">.</span><span class="n">SESSION_COOKIE_NAME</span><span class="p">)</span> <span class="k">if</span> <span class="n">data</span><span class="p">:</span> <span class="n">session</span> <span class="o">=</span> <span class="n">Session</span><span class="o">.</span><span class="n">unserialize</span><span class="p">(</span><span class="n">data</span><span class="p">,</span> <span class="n">settings</span><span class="o">.</span><span class="n">SECRET_KEY</span><span class="p">)</span> <span class="k">else</span><span class="p">:</span> <span class="n">session</span> <span class="o">=</span> <span class="n">Session</span><span class="p">(</span><span class="n">secret_key</span><span class="o">=</span><span class="n">settings</span><span class="o">.</span><span class="n">SECRET_KEY</span><span class="p">)</span> <span class="n">request</span><span class="o">.</span><span class="n">session</span> <span class="o">=</span> <span class="n">session</span> <span class="k">def</span> <span class="nf">process_response</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">request</span><span class="p">,</span> <span class="n">response</span><span class="p">):</span> <span class="k">try</span><span class="p">:</span> <span class="n">modified</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">session</span><span class="o">.</span><span class="n">modified</span> <span class="k">except</span> <span class="ne">AttributeError</span><span class="p">:</span> <span class="k">return</span> <span class="n">response</span> <span class="k">if</span> <span class="n">modified</span> <span class="ow">or</span> <span class="n">settings</span><span class="o">.</span><span class="n">SESSION_SAVE_EVERY_REQUEST</span><span class="p">:</span> <span class="k">if</span> <span class="n">request</span><span class="o">.</span><span class="n">session</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#39;is_permanent_session&#39;</span><span class="p">):</span> <span class="n">max_age</span> <span class="o">=</span> <span class="n">settings</span><span class="o">.</span><span class="n">SESSION_COOKIE_AGE</span> <span class="n">expires_time</span> <span class="o">=</span> <span class="n">time</span><span class="p">()</span> <span class="o">+</span> <span class="n">settings</span><span class="o">.</span><span class="n">SESSION_COOKIE_AGE</span> <span class="n">expires</span> <span class="o">=</span> <span class="n">cookie_date</span><span class="p">(</span><span class="n">expires_time</span><span class="p">)</span> <span class="k">else</span><span class="p">:</span> <span class="n">max_age</span> <span class="o">=</span> <span class="n">expires</span> <span class="o">=</span> <span class="bp">None</span> <span class="n">response</span><span class="o">.</span><span class="n">set_cookie</span><span class="p">(</span><span class="n">settings</span><span class="o">.</span><span class="n">SESSION_COOKIE_NAME</span><span class="p">,</span> <span class="n">request</span><span class="o">.</span><span class="n">session</span><span class="o">.</span><span class="n">serialize</span><span class="p">(),</span> <span class="n">max_age</span><span class="o">=</span><span class="n">max_age</span><span class="p">,</span> <span class="n">expires</span><span class="o">=</span><span class="n">expires</span><span class="p">,</span> <span class="n">domain</span><span class="o">=</span><span class="n">settings</span><span class="o">.</span><span class="n">SESSION_COOKIE_DOMAIN</span><span class="p">,</span> <span class="n">secure</span><span class="o">=</span><span class="n">settings</span><span class="o">.</span><span class="n">SESSION_COOKIE_SECURE</span> <span class="ow">or</span> <span class="bp">None</span><span class="p">)</span> <span class="k">return</span> <span class="n">response</span> </pre></div> <PYGMENTS_CACHE --><!-- PYGMENTS_RAW(python)>try: from hashlib import md5 except ImportError: from md5 import md5 from time import time from random import random from django.conf import settings from django.utils.http import cookie_date from werkzeug.contrib.securecookie import SecureCookie class Session(SecureCookie): @property def session_key(self): if not 'session_key' in self: self['session_key'] = md5('%s%s%s' % (random(), time(), settings.SECRET_KEY)).hexdigest() return self['session_key'] class ClientSideSessionMiddleware(object): def process_request(self, request): data = request.COOKIES.get(settings.SESSION_COOKIE_NAME) if data: session = Session.unserialize(data, settings.SECRET_KEY) else: session = Session(secret_key=settings.SECRET_KEY) request.session = session def process_response(self, request, response): try: modified = request.session.modified except AttributeError: return response if modified or settings.SESSION_SAVE_EVERY_REQUEST: if request.session.get('is_permanent_session'): max_age = settings.SESSION_COOKIE_AGE expires_time = time() + settings.SESSION_COOKIE_AGE expires = cookie_date(expires_time) else: max_age = expires = None response.set_cookie(settings.SESSION_COOKIE_NAME, request.session.serialize(), max_age=max_age, expires=expires, domain=settings.SESSION_COOKIE_DOMAIN, secure=settings.SESSION_COOKIE_SECURE or None) return response<PYGMENTS_RAW --> Additionally to the normal django session middleware this middleware can handle both persistent sessions and browser-session bound sessions. Per default a session ends at the end of the browser session, if you want to make it persistent you have to set "is_permanent_session" in the session data to True. Keep in mind that cookies have a size limit and that users will be able to look at that data (but not alter it). The example above requires the current werkzeug tip and not the 0.1 release version.Since a few changesets <a href="http://werkzeug.pocoo.org/">Werkzeug</a> provides a module for client side sessions. While it's of course not yet perfect I think it's an interesting approach and we're currently replacing django's sessions with Werkzeug's secure cookie. How does it work? Basically the data is stored as pickled data inside the cookie. The pickled data is hashed and added to the cookie too. Whenever the data is loaded from the cookie a new hash is created and the two hashes are compared. If they match the data is unserialized, otherwise a new SecureCookie object is created with empty data. As a matter of fact there is no "session key" so if you want to use it with django you have to fake the "session key" by inserting it into the data. We use the following session middleware as replacement for the django session middleware: Additionally to the normal django session middleware this middleware can handle both persistent sessions and browser-session bound sessions. Per default a session ends at the end of the browser session, if you want to make it persistent you have to set "is_permanent_session" in the session data to True. Keep in mind that cookies have a size limit and that users will be able to look at that data (but not alter it). The example above requires the current werkzeug tip and not the 0.1 release version.SQAAAANTAAAABGJvZHlSUwAAABdTaW5jZSBhIGZldyBjaGFuZ2VzZXRzIEwAAUVTAAAAAWFMAABN AAFTAAAABGhyZWZTAAAAGmh0dHA6Ly93ZXJremV1Zy5wb2Nvby5vcmcvUwAAAAhXZXJremV1Z1MA AAUJIHByb3ZpZGVzIGEgbW9kdWxlIGZvciBjbGllbnQgc2lkZSBzZXNzaW9ucy4gV2hpbGUgaXQn cyBvZiBjb3Vyc2Ugbm90IHlldCBwZXJmZWN0IEkgdGhpbmsgaXQncyBhbiBpbnRlcmVzdGluZyBh cHByb2FjaCBhbmQgd2UncmUgY3VycmVudGx5IHJlcGxhY2luZyBkamFuZ28ncyBzZXNzaW9ucyB3 aXRoIFdlcmt6ZXVnJ3Mgc2VjdXJlIGNvb2tpZS4KCkhvdyBkb2VzIGl0IHdvcms/IEJhc2ljYWxs eSB0aGUgZGF0YSBpcyBzdG9yZWQgYXMgcGlja2xlZCBkYXRhIGluc2lkZSB0aGUgY29va2llLiAg VGhlIHBpY2tsZWQgZGF0YSBpcyBoYXNoZWQgYW5kIGFkZGVkIHRvIHRoZSBjb29raWUgdG9vLiBX aGVuZXZlciB0aGUgZGF0YSBpcyBsb2FkZWQgZnJvbSB0aGUgY29va2llIGEgbmV3IGhhc2ggaXMg Y3JlYXRlZCBhbmQgdGhlIHR3byBoYXNoZXMgYXJlIGNvbXBhcmVkLiAgSWYgdGhleSBtYXRjaCB0 aGUgZGF0YSBpcyB1bnNlcmlhbGl6ZWQsIG90aGVyd2lzZSBhIG5ldyBTZWN1cmVDb29raWUgb2Jq ZWN0IGlzIGNyZWF0ZWQgd2l0aCBlbXB0eSBkYXRhLiAgQXMgYSBtYXR0ZXIgb2YgZmFjdCB0aGVy ZSBpcyBubyAic2Vzc2lvbiBrZXkiIHNvIGlmIHlvdSB3YW50IHRvIHVzZSBpdCB3aXRoIGRqYW5n byB5b3UgaGF2ZSB0byBmYWtlIHRoZSAic2Vzc2lvbiBrZXkiIGJ5IGluc2VydGluZyBpdCBpbnRv IHRoZSBkYXRhLiAgV2UgdXNlIHRoZSBmb2xsb3dpbmcgc2Vzc2lvbiBtaWRkbGV3YXJlIGFzIHJl cGxhY2VtZW50IGZvciB0aGUgZGphbmdvIHNlc3Npb24gbWlkZGxld2FyZToKCgoKQWRkaXRpb25h bGx5IHRvIHRoZSBub3JtYWwgZGphbmdvIHNlc3Npb24gbWlkZGxld2FyZSB0aGlzIG1pZGRsZXdh cmUgY2FuIGhhbmRsZSBib3RoIHBlcnNpc3RlbnQgc2Vzc2lvbnMgYW5kIGJyb3dzZXItc2Vzc2lv biBib3VuZCBzZXNzaW9ucy4gUGVyIGRlZmF1bHQgYSBzZXNzaW9uIGVuZHMgYXQgdGhlIGVuZCBv ZiB0aGUgYnJvd3NlciBzZXNzaW9uLCBpZiB5b3Ugd2FudCB0byBtYWtlIGl0IHBlcnNpc3RlbnQg eW91IGhhdmUgdG8gc2V0ICJpc19wZXJtYW5lbnRfc2Vzc2lvbiIgaW4gdGhlIHNlc3Npb24gZGF0 YSB0byBUcnVlLgoKS2VlcCBpbiBtaW5kIHRoYXQgY29va2llcyBoYXZlIGEgc2l6ZSBsaW1pdCBh bmQgdGhhdCB1c2VycyB3aWxsIGJlIGFibGUgdG8gbG9vayBhdCB0aGF0IGRhdGEgKGJ1dCBub3Qg YWx0ZXIgaXQpLiBUaGUgZXhhbXBsZSBhYm92ZSByZXF1aXJlcyB0aGUgY3VycmVudCB3ZXJremV1 ZyB0aXAgYW5kIG5vdCB0aGUgMC4xIHJlbGVhc2UgdmVyc2lvbi5TAAAABnBhcnNlclMAAAAEaHRt bFMAAAAFaW50cm9SUwAAAABMAAA= SmileyChrissmileychris@gmail.com2007-12-16T04:41:37Znono0Couldn't you have just written a custom session backend to do this?Couldn't you have just written a custom session backend to do this?SQAAAAJTAAAABGJvZHlSUwAAAENDb3VsZG4ndCB5b3UgaGF2ZSBqdXN0IHdyaXR0ZW4gYSBjdXN0 b20gc2Vzc2lvbiBiYWNrZW5kIHRvIGRvIHRoaXM/TAAAUwAAAAZwYXJzZXJTAAAABGh0bWw= Armin Ronacherarmin.ronacher@active-4.comhttp://lucumr.pocoo.org/2007-12-16T10:50:25Znono0You mean a django session backend? Primarly because it wasn't written for django. That you can use it with django is just a goody that comes for free because the module doesn't require any specific Werkzeug implementation details. And even if someone wants to integrate it into the django session system in the first place there would be no other way than writing a different session middleware because the session store cannot alter the cookie that is set.You mean a django session backend? Primarly because it wasn't written for django. That you can use it with django is just a goody that comes for free because the module doesn't require any specific Werkzeug implementation details. And even if someone wants to integrate it into the django session system in the first place there would be no other way than writing a different session middleware because the session store cannot alter the cookie that is set.SQAAAAJTAAAABGJvZHlSUwAAAcpZb3UgbWVhbiBhIGRqYW5nbyBzZXNzaW9uIGJhY2tlbmQ/IFBy aW1hcmx5IGJlY2F1c2UgaXQgd2Fzbid0IHdyaXR0ZW4gZm9yIGRqYW5nby4gVGhhdCB5b3UgY2Fu IHVzZSBpdCB3aXRoIGRqYW5nbyBpcyBqdXN0IGEgZ29vZHkgdGhhdCBjb21lcyBmb3IgZnJlZSBi ZWNhdXNlIHRoZSBtb2R1bGUgZG9lc24ndCByZXF1aXJlIGFueSBzcGVjaWZpYyBXZXJremV1ZyBp bXBsZW1lbnRhdGlvbiBkZXRhaWxzLgoKQW5kIGV2ZW4gaWYgc29tZW9uZSB3YW50cyB0byBpbnRl Z3JhdGUgaXQgaW50byB0aGUgZGphbmdvIHNlc3Npb24gc3lzdGVtIGluIHRoZSBmaXJzdCBwbGFj ZSB0aGVyZSB3b3VsZCBiZSBubyBvdGhlciB3YXkgdGhhbiB3cml0aW5nIGEgZGlmZmVyZW50IHNl c3Npb24gbWlkZGxld2FyZSBiZWNhdXNlIHRoZSBzZXNzaW9uIHN0b3JlIGNhbm5vdCBhbHRlciB0 aGUgY29va2llIHRoYXQgaXMgc2V0LkwAAFMAAAAGcGFyc2VyUwAAAARodG1s Django’s Problems and Why 2.0 is a Bad Ideahttp://lucumr.pocoo.org/cogitations/2007/12/12/djangos-problems-and-why-20-is-a-bad-idea/2007-12-12T11:00:58Z2007-12-12T11:00:58ZArmin Ronacherdjangos-problems-and-why-20-is-a-bad-ideayesyes2I stumbled about <a href="http://groups.google.com/group/django-developers/browse_thread/thread/b4c237ad76f9eeca">this thread on django-developers</a> which proposes calling the Django 1.0 release Django 2.0. One the one hand version numbers say nothing. Just take Wine or Trac as two examples that are already very stable but still below the magical 1.0 release. Open Source software often takes some time until a 1.0 is released and that's perfectly fine. However skipping a version number is purely a marketing trick IMO. Just think of Java which currently names 1.6 Java 6 whereas 1.4 still was Java 2. With django it looks like the plan is to keep up with Rails which went to 2.0 a few days ago. While I love to see that django kicks ass and it's moving toward a stable release I have a bad feeling naming it 2.0. Because there is currently a huge gap between rails and django unfortunately. Rails has gained really good integrated migrations, REST webservices, a debugger and many other things django is still lacking. Django makes an incredible good framework if you get your problem into the use case of django. But as soon as you break out of it and need something that goes beyond what's possible in django you wish you have chosen something else. The django ORM is far from optimal, the admin rocks but as soon as the number of users exceeds 10.000 users it's impossible to use it (chose yourself in a dropdown of 50.000 users …) or becomes utterly complex. Complex data models also look awkward in the admin or become too complicated to manage. And if you want to stick with the admin you cannot replace the user model. Now what do you do if you have a forum and want to count the posts? Use a UserProfile module? And how do you want to display a list of users sorted by their number of posts? Yes there are ways to hack around it but the more complex the application becomes the more you of django's strengths become obsolete. The application I'm working on right now now is only using two more contrib modules. The auth and the admin, and it looks like we have to drop them too, due to the limitations. All applications in that project hack around ORM limitations, we have an incredible number of recreated base middlewares, we have to monkey patch the request object to hack in subdomain support. I was talking with David Cramer from curse gaming about some of the issues and he told me that they have forked django at a given point and patched the ORM. The django template engine was replaced by Jinja (our application does the same) and they are caching the hell out of the application to scale it. Bryan McLemore from the curse team told me some time ago that some pages have up to 30 queries on a page. I don't want to say that django fails in what it's doing. But it's far from 2.0.I stumbled about <a href="http://groups.google.com/group/django-developers/browse_thread/thread/b4c237ad76f9eeca">this thread on django-developers</a> which proposes calling the Django 1.0 release Django 2.0. One the one hand version numbers say nothing. Just take Wine or Trac as two examples that are already very stable but still below the magical 1.0 release. Open Source software often takes some time until a 1.0 is released and that's perfectly fine. However skipping a version number is purely a marketing trick IMO. Just think of Java which currently names 1.6 Java 6 whereas 1.4 still was Java 2. With django it looks like the plan is to keep up with Rails which went to 2.0 a few days ago. While I love to see that django kicks ass and it's moving toward a stable release I have a bad feeling naming it 2.0. Because there is currently a huge gap between rails and django unfortunately. Rails has gained really good integrated migrations, REST webservices, a debugger and many other things django is still lacking. Django makes an incredible good framework if you get your problem into the use case of django. But as soon as you break out of it and need something that goes beyond what's possible in django you wish you have chosen something else. The django ORM is far from optimal, the admin rocks but as soon as the number of users exceeds 10.000 users it's impossible to use it (chose yourself in a dropdown of 50.000 users …) or becomes utterly complex. Complex data models also look awkward in the admin or become too complicated to manage. And if you want to stick with the admin you cannot replace the user model. Now what do you do if you have a forum and want to count the posts? Use a UserProfile module? And how do you want to display a list of users sorted by their number of posts? Yes there are ways to hack around it but the more complex the application becomes the more you of django's strengths become obsolete. The application I'm working on right now now is only using two more contrib modules. The auth and the admin, and it looks like we have to drop them too, due to the limitations. All applications in that project hack around ORM limitations, we have an incredible number of recreated base middlewares, we have to monkey patch the request object to hack in subdomain support. I was talking with David Cramer from curse gaming about some of the issues and he told me that they have forked django at a given point and patched the ORM. The django template engine was replaced by Jinja (our application does the same) and they are caching the hell out of the application to scale it. Bryan McLemore from the curse team told me some time ago that some pages have up to 30 queries on a page. I don't want to say that django fails in what it's doing. But it's far from 2.0.SQAAAANTAAAABGJvZHlSUwAAABFJIHN0dW1ibGVkIGFib3V0IEwAAUVTAAAAAWFMAABNAAFTAAAA BGhyZWZTAAAAVmh0dHA6Ly9ncm91cHMuZ29vZ2xlLmNvbS9ncm91cC9kamFuZ28tZGV2ZWxvcGVy cy9icm93c2VfdGhyZWFkL3RocmVhZC9iNGMyMzdhZDc2ZjllZWNhUwAAACB0aGlzIHRocmVhZCBv biBkamFuZ28tZGV2ZWxvcGVyc1MAAApjIHdoaWNoIHByb3Bvc2VzIGNhbGxpbmcgdGhlIERqYW5n byAxLjAgcmVsZWFzZSBEamFuZ28gMi4wLiBPbmUgdGhlIG9uZSBoYW5kIHZlcnNpb24gbnVtYmVy cyBzYXkgbm90aGluZy4gSnVzdCB0YWtlIFdpbmUgb3IgVHJhYyBhcyB0d28gZXhhbXBsZXMgdGhh dCBhcmUgYWxyZWFkeSB2ZXJ5IHN0YWJsZSBidXQgc3RpbGwgYmVsb3cgdGhlIG1hZ2ljYWwgMS4w IHJlbGVhc2UuIE9wZW4gU291cmNlIHNvZnR3YXJlIG9mdGVuIHRha2VzIHNvbWUgdGltZSB1bnRp bCBhIDEuMCBpcyByZWxlYXNlZCBhbmQgdGhhdCdzIHBlcmZlY3RseSBmaW5lLiBIb3dldmVyIHNr aXBwaW5nIGEgdmVyc2lvbiBudW1iZXIgaXMgcHVyZWx5IGEgbWFya2V0aW5nIHRyaWNrIElNTy4g SnVzdCB0aGluayBvZiBKYXZhIHdoaWNoIGN1cnJlbnRseSBuYW1lcyAxLjYgSmF2YSA2IHdoZXJl YXMgMS40IHN0aWxsIHdhcyBKYXZhIDIuCgpXaXRoIGRqYW5nbyBpdCBsb29rcyBsaWtlIHRoZSBw bGFuIGlzIHRvIGtlZXAgdXAgd2l0aCBSYWlscyB3aGljaCB3ZW50IHRvIDIuMCBhIGZldyBkYXlz IGFnby4gV2hpbGUgSSBsb3ZlIHRvIHNlZSB0aGF0IGRqYW5nbyBraWNrcyBhc3MgYW5kIGl0J3Mg bW92aW5nIHRvd2FyZCBhIHN0YWJsZSByZWxlYXNlIEkgaGF2ZSBhIGJhZCBmZWVsaW5nIG5hbWlu ZyBpdCAyLjAuIEJlY2F1c2UgdGhlcmUgaXMgY3VycmVudGx5IGEgaHVnZSBnYXAgYmV0d2VlbiBy YWlscyBhbmQgZGphbmdvIHVuZm9ydHVuYXRlbHkuIFJhaWxzIGhhcyBnYWluZWQgcmVhbGx5IGdv b2QgaW50ZWdyYXRlZCBtaWdyYXRpb25zLCBSRVNUIHdlYnNlcnZpY2VzLCBhIGRlYnVnZ2VyIGFu ZCBtYW55IG90aGVyIHRoaW5ncyBkamFuZ28gaXMgc3RpbGwgbGFja2luZy4KCkRqYW5nbyBtYWtl cyBhbiBpbmNyZWRpYmxlIGdvb2QgZnJhbWV3b3JrIGlmIHlvdSBnZXQgeW91ciBwcm9ibGVtIGlu dG8gdGhlIHVzZSBjYXNlIG9mIGRqYW5nby4gQnV0IGFzIHNvb24gYXMgeW91IGJyZWFrIG91dCBv ZiBpdCBhbmQgbmVlZCBzb21ldGhpbmcgdGhhdCBnb2VzIGJleW9uZCB3aGF0J3MgcG9zc2libGUg aW4gZGphbmdvIHlvdSB3aXNoIHlvdSBoYXZlIGNob3NlbiBzb21ldGhpbmcgZWxzZS4gVGhlIGRq YW5nbyBPUk0gaXMgZmFyIGZyb20gb3B0aW1hbCwgdGhlIGFkbWluIHJvY2tzIGJ1dCBhcyBzb29u IGFzIHRoZSBudW1iZXIgb2YgdXNlcnMgZXhjZWVkcyAxMC4wMDAgdXNlcnMgaXQncyBpbXBvc3Np YmxlIHRvIHVzZSBpdCAoY2hvc2UgeW91cnNlbGYgaW4gYSBkcm9wZG93biBvZiA1MC4wMDAgdXNl cnMg4oCmKSBvciBiZWNvbWVzIHV0dGVybHkgY29tcGxleC4gQ29tcGxleCBkYXRhIG1vZGVscyBh bHNvIGxvb2sgYXdrd2FyZCBpbiB0aGUgYWRtaW4gb3IgYmVjb21lIHRvbyBjb21wbGljYXRlZCB0 byBtYW5hZ2UuIEFuZCBpZiB5b3Ugd2FudCB0byBzdGljayB3aXRoIHRoZSBhZG1pbiB5b3UgY2Fu bm90IHJlcGxhY2UgdGhlIHVzZXIgbW9kZWwuIE5vdyB3aGF0IGRvIHlvdSBkbyBpZiB5b3UgaGF2 ZSBhIGZvcnVtIGFuZCB3YW50IHRvIGNvdW50IHRoZSBwb3N0cz8gVXNlIGEgVXNlclByb2ZpbGUg bW9kdWxlPyBBbmQgaG93IGRvIHlvdSB3YW50IHRvIGRpc3BsYXkgYSBsaXN0IG9mIHVzZXJzIHNv cnRlZCBieSB0aGVpciBudW1iZXIgb2YgcG9zdHM/CgpZZXMgdGhlcmUgYXJlIHdheXMgdG8gaGFj ayBhcm91bmQgaXQgYnV0IHRoZSBtb3JlIGNvbXBsZXggdGhlIGFwcGxpY2F0aW9uIGJlY29tZXMg dGhlIG1vcmUgeW91IG9mIGRqYW5nbydzIHN0cmVuZ3RocyBiZWNvbWUgb2Jzb2xldGUuIFRoZSBh cHBsaWNhdGlvbiBJJ20gd29ya2luZyBvbiByaWdodCBub3cgbm93IGlzIG9ubHkgdXNpbmcgdHdv IG1vcmUgY29udHJpYiBtb2R1bGVzLiBUaGUgYXV0aCBhbmQgdGhlIGFkbWluLCBhbmQgaXQgbG9v a3MgbGlrZSB3ZSBoYXZlIHRvIGRyb3AgdGhlbSB0b28sIGR1ZSB0byB0aGUgbGltaXRhdGlvbnMu IEFsbCBhcHBsaWNhdGlvbnMgaW4gdGhhdCBwcm9qZWN0IGhhY2sgYXJvdW5kIE9STSBsaW1pdGF0 aW9ucywgd2UgaGF2ZSBhbiBpbmNyZWRpYmxlIG51bWJlciBvZiByZWNyZWF0ZWQgYmFzZSBtaWRk bGV3YXJlcywgd2UgaGF2ZSB0byBtb25rZXkgcGF0Y2ggdGhlIHJlcXVlc3Qgb2JqZWN0IHRvIGhh Y2sgaW4gc3ViZG9tYWluIHN1cHBvcnQuCgpJIHdhcyB0YWxraW5nIHdpdGggRGF2aWQgQ3JhbWVy IGZyb20gY3Vyc2UgZ2FtaW5nIGFib3V0IHNvbWUgb2YgdGhlIGlzc3VlcyBhbmQgaGUgdG9sZCBt ZSB0aGF0IHRoZXkgaGF2ZSBmb3JrZWQgZGphbmdvIGF0IGEgZ2l2ZW4gcG9pbnQgYW5kIHBhdGNo ZWQgdGhlIE9STS4gVGhlIGRqYW5nbyB0ZW1wbGF0ZSBlbmdpbmUgd2FzIHJlcGxhY2VkIGJ5IEpp bmphIChvdXIgYXBwbGljYXRpb24gZG9lcyB0aGUgc2FtZSkgYW5kIHRoZXkgYXJlIGNhY2hpbmcg dGhlIGhlbGwgb3V0IG9mIHRoZSBhcHBsaWNhdGlvbiB0byBzY2FsZSBpdC4gQnJ5YW4gTWNMZW1v cmUgZnJvbSB0aGUgY3Vyc2UgdGVhbSB0b2xkIG1lIHNvbWUgdGltZSBhZ28gdGhhdCBzb21lIHBh Z2VzIGhhdmUgdXAgdG8gMzAgcXVlcmllcyBvbiBhIHBhZ2UuCgpJIGRvbid0IHdhbnQgdG8gc2F5 IHRoYXQgZGphbmdvIGZhaWxzIGluIHdoYXQgaXQncyBkb2luZy4gQnV0IGl0J3MgZmFyIGZyb20g Mi4wLlMAAAAGcGFyc2VyUwAAAARodG1sUwAAAAVpbnRyb1JTAAAAAEwAAA== Ericeric.nilsson@slaskpost.se2007-12-12T11:59:36Znono0I usally say django is great for websites and webapps while rails is great for services and APIs. The whole discussion with version number is just overkill, just get it released in stead. Also, webdevelopment is evolving each day. Something new and great today could be deprecated tomorrow, verison number doesnt say a shit. So just use the svn revision number, tag it with a flashy name (like ubuntu do on their releases) and just get it out! Real webdevelopers will use the trunk anyway, because as i said, webdevelopment is evolving.I usally say django is great for websites and webapps while rails is great for services and APIs. The whole discussion with version number is just overkill, just get it released in stead. Also, webdevelopment is evolving each day. Something new and great today could be deprecated tomorrow, verison number doesnt say a shit. So just use the svn revision number, tag it with a flashy name (like ubuntu do on their releases) and just get it out! Real webdevelopers will use the trunk anyway, because as i said, webdevelopment is evolving.SQAAAAJTAAAABGJvZHlSUwAAAh1JIHVzYWxseSBzYXkgZGphbmdvIGlzIGdyZWF0IGZvciB3ZWJz aXRlcyBhbmQgd2ViYXBwcyB3aGlsZSByYWlscyBpcyBncmVhdCBmb3Igc2VydmljZXMgYW5kIEFQ SXMuCgpUaGUgd2hvbGUgZGlzY3Vzc2lvbiB3aXRoIHZlcnNpb24gbnVtYmVyIGlzIGp1c3Qgb3Zl cmtpbGwsIGp1c3QgZ2V0IGl0IHJlbGVhc2VkIGluIHN0ZWFkLiAKCkFsc28sIHdlYmRldmVsb3Bt ZW50IGlzIGV2b2x2aW5nIGVhY2ggZGF5LiBTb21ldGhpbmcgbmV3IGFuZCBncmVhdCB0b2RheSBj b3VsZCBiZSBkZXByZWNhdGVkIHRvbW9ycm93LCB2ZXJpc29uIG51bWJlciBkb2VzbnQgc2F5IGEg c2hpdC4gCgpTbyBqdXN0IHVzZSB0aGUgc3ZuIHJldmlzaW9uIG51bWJlciwgdGFnIGl0IHdpdGgg YSBmbGFzaHkgbmFtZSAobGlrZSB1YnVudHUgZG8gb24gdGhlaXIgcmVsZWFzZXMpIGFuZCBqdXN0 IGdldCBpdCBvdXQhIFJlYWwgd2ViZGV2ZWxvcGVycyB3aWxsIHVzZSB0aGUgdHJ1bmsgYW55d2F5 LCBiZWNhdXNlIGFzIGkgc2FpZCwgd2ViZGV2ZWxvcG1lbnQgaXMgZXZvbHZpbmcuTAAAUwAAAAZw YXJzZXJTAAAABGh0bWw= Ericeric.nilsson@slaskpost.se2007-12-12T12:08:24Znono0Also, rails is lacking great things from django aswell, as form handling with newsforms for example. I think i like the way django handles models better though it would of course be great with some kind of migrations supportAlso, rails is lacking great things from django aswell, as form handling with newsforms for example. I think i like the way django handles models better though it would of course be great with some kind of migrations supportSQAAAAJTAAAABGJvZHlSUwAAAOBBbHNvLCByYWlscyBpcyBsYWNraW5nIGdyZWF0IHRoaW5ncyBm cm9tIGRqYW5nbyBhc3dlbGwsIGFzIGZvcm0gaGFuZGxpbmcgd2l0aCBuZXdzZm9ybXMgZm9yIGV4 YW1wbGUuIEkgdGhpbmsgaSBsaWtlIHRoZSB3YXkgZGphbmdvIGhhbmRsZXMgbW9kZWxzIGJldHRl ciB0aG91Z2ggaXQgd291bGQgb2YgY291cnNlIGJlIGdyZWF0IHdpdGggc29tZSBraW5kIG9mIG1p Z3JhdGlvbnMgc3VwcG9ydEwAAFMAAAAGcGFyc2VyUwAAAARodG1s Eric Florenzanofloguy@gmail.cimhttp://www.eflorenzano.com2007-12-12T12:39:00Znono0More than 10,000 admins on a site? Sounds like too many cooks in the kitchen to me. Seriously though, at that point you are definitely at the upper bound of the use case for the admin app, so it starts to sound silly to complain. At some point you need to code your own app. Regarding ordering by number of posts: denormalization is your friend. It would take any competant coder 5-10 minutes to create some signals and callbacks to update a num_posts field on a UserProfile. Someday when aggregation support is included in the ORM, this will become even easier, but still, todays solition is pretty darn easy. Beyond those two (non)issues, you really didn't make any points. The fact that you were able to easily swap in Jinja is actually a testament to the modularity of Django itself.More than 10,000 admins on a site? Sounds like too many cooks in the kitchen to me. Seriously though, at that point you are definitely at the upper bound of the use case for the admin app, so it starts to sound silly to complain. At some point you need to code your own app. Regarding ordering by number of posts: denormalization is your friend. It would take any competant coder 5-10 minutes to create some signals and callbacks to update a num_posts field on a UserProfile. Someday when aggregation support is included in the ORM, this will become even easier, but still, todays solition is pretty darn easy. Beyond those two (non)issues, you really didn't make any points. The fact that you were able to easily swap in Jinja is actually a testament to the modularity of Django itself.SQAAAAJTAAAABGJvZHlSUwAAAxxNb3JlIHRoYW4gMTAsMDAwIGFkbWlucyBvbiBhIHNpdGU/ICBT b3VuZHMgbGlrZSB0b28gbWFueSBjb29rcyBpbiB0aGUga2l0Y2hlbiB0byBtZS4gIFNlcmlvdXNs eSB0aG91Z2gsIGF0IHRoYXQgcG9pbnQgeW91IGFyZSBkZWZpbml0ZWx5IGF0IHRoZSB1cHBlciBi b3VuZCBvZiB0aGUgdXNlIGNhc2UgZm9yIHRoZSBhZG1pbiBhcHAsIHNvIGl0IHN0YXJ0cyB0byBz b3VuZCBzaWxseSB0byBjb21wbGFpbi4gIEF0IHNvbWUgcG9pbnQgeW91IG5lZWQgdG8gY29kZSB5 b3VyIG93biBhcHAuCgpSZWdhcmRpbmcgb3JkZXJpbmcgYnkgbnVtYmVyIG9mIHBvc3RzOiAgZGVu b3JtYWxpemF0aW9uIGlzIHlvdXIgZnJpZW5kLiAgSXQgd291bGQgdGFrZSBhbnkgY29tcGV0YW50 IGNvZGVyIDUtMTAgbWludXRlcyB0byBjcmVhdGUgc29tZSBzaWduYWxzIGFuZCBjYWxsYmFja3Mg dG8gdXBkYXRlIGEgbnVtX3Bvc3RzIGZpZWxkIG9uIGEgVXNlclByb2ZpbGUuICBTb21lZGF5IHdo ZW4gYWdncmVnYXRpb24gc3VwcG9ydCBpcyBpbmNsdWRlZCBpbiB0aGUgT1JNLCB0aGlzIHdpbGwg YmVjb21lIGV2ZW4gZWFzaWVyLCBidXQgc3RpbGwsIHRvZGF5cyBzb2xpdGlvbiBpcyBwcmV0dHkg ZGFybiBlYXN5LgoKQmV5b25kIHRob3NlIHR3byAobm9uKWlzc3VlcywgeW91IHJlYWxseSBkaWRu J3QgbWFrZSBhbnkgcG9pbnRzLiAgVGhlIGZhY3QgdGhhdCB5b3Ugd2VyZSBhYmxlIHRvIGVhc2ls eSBzd2FwIGluIEppbmphIGlzIGFjdHVhbGx5IGEgdGVzdGFtZW50IHRvIHRoZSBtb2R1bGFyaXR5 IG9mIERqYW5nbyBpdHNlbGYuTAAAUwAAAAZwYXJzZXJTAAAABGh0bWw= Armin Ronacherarmin.ronacher@active-4.comhttp://lucumr.pocoo.org/2007-12-12T13:01:20Znono0Yes. newforms is django's killerfeature. It's so far the best form validation system I found. Also that the django core is translated is a very good thing. While our project is not multilingual it's not English and it's a cool that django can output German error messages. Our problem is not the updating of the num_posts fields in the UserProfile, our problem is the displaying of a user list paginated and sorted by the number of posts. Yes we can (And do) sort the user profiles by the number of posts and resolve the associated user object but still the process is a lot more complex than we want it to be :-/ And no, we don't have 10.000 admins, just about 50.000 users and as many user objects :-) So we also have 50.000 items in a dropdown.Yes. newforms is django's killerfeature. It's so far the best form validation system I found. Also that the django core is translated is a very good thing. While our project is not multilingual it's not English and it's a cool that django can output German error messages. Our problem is not the updating of the num_posts fields in the UserProfile, our problem is the displaying of a user list paginated and sorted by the number of posts. Yes we can (And do) sort the user profiles by the number of posts and resolve the associated user object but still the process is a lot more complex than we want it to be :-/ And no, we don't have 10.000 admins, just about 50.000 users and as many user objects :-) So we also have 50.000 items in a dropdown.SQAAAAJTAAAABGJvZHlSUwAAAu5ZZXMuIG5ld2Zvcm1zIGlzIGRqYW5nbydzIGtpbGxlcmZlYXR1 cmUuIEl0J3Mgc28gZmFyIHRoZSBiZXN0IGZvcm0gdmFsaWRhdGlvbiBzeXN0ZW0gSSBmb3VuZC4g QWxzbyB0aGF0IHRoZSBkamFuZ28gY29yZSBpcyB0cmFuc2xhdGVkIGlzIGEgdmVyeSBnb29kIHRo aW5nLiBXaGlsZSBvdXIgcHJvamVjdCBpcyBub3QgbXVsdGlsaW5ndWFsIGl0J3Mgbm90IEVuZ2xp c2ggYW5kIGl0J3MgYSBjb29sIHRoYXQgZGphbmdvIGNhbiBvdXRwdXQgR2VybWFuIGVycm9yIG1l c3NhZ2VzLgoKT3VyIHByb2JsZW0gaXMgbm90IHRoZSB1cGRhdGluZyBvZiB0aGUgbnVtX3Bvc3Rz IGZpZWxkcyBpbiB0aGUgVXNlclByb2ZpbGUsIG91ciBwcm9ibGVtIGlzIHRoZSBkaXNwbGF5aW5n IG9mIGEgdXNlciBsaXN0IHBhZ2luYXRlZCBhbmQgc29ydGVkIGJ5IHRoZSBudW1iZXIgb2YgcG9z dHMuICBZZXMgd2UgY2FuIChBbmQgZG8pIHNvcnQgdGhlIHVzZXIgcHJvZmlsZXMgYnkgdGhlIG51 bWJlciBvZiBwb3N0cyBhbmQgcmVzb2x2ZSB0aGUgYXNzb2NpYXRlZCB1c2VyIG9iamVjdCBidXQg c3RpbGwgdGhlIHByb2Nlc3MgaXMgYSBsb3QgbW9yZSBjb21wbGV4IHRoYW4gd2Ugd2FudCBpdCB0 byBiZSA6LS8KCkFuZCBubywgd2UgZG9uJ3QgaGF2ZSAxMC4wMDAgYWRtaW5zLCBqdXN0IGFib3V0 IDUwLjAwMCB1c2VycyBhbmQgYXMgbWFueSB1c2VyIG9iamVjdHMgOi0pIFNvIHdlIGFsc28gaGF2 ZSA1MC4wMDAgaXRlbXMgaW4gYSBkcm9wZG93bi5MAABTAAAABnBhcnNlclMAAAAEaHRtbA== Eric Florenzanofloguy@gmail.comhttp://www.eflorenzano.com/2007-12-12T13:17:40Znono0Haha, I see what you meant about the 50,000 users now. That makes it a much more valid point :) Still though, the admin app is modular enough that if you have 50,000 users, you should be able to write some Javascript to code in an autocomplete box or something.Haha, I see what you meant about the 50,000 users now. That makes it a much more valid point :) Still though, the admin app is modular enough that if you have 50,000 users, you should be able to write some Javascript to code in an autocomplete box or something.SQAAAAJTAAAABGJvZHlSUwAAAQdIYWhhLCBJIHNlZSB3aGF0IHlvdSBtZWFudCBhYm91dCB0aGUg NTAsMDAwIHVzZXJzIG5vdy4gIFRoYXQgbWFrZXMgaXQgYSBtdWNoIG1vcmUgdmFsaWQgcG9pbnQg OikgIFN0aWxsIHRob3VnaCwgdGhlIGFkbWluIGFwcCBpcyBtb2R1bGFyIGVub3VnaCB0aGF0IGlm IHlvdSBoYXZlIDUwLDAwMCB1c2VycywgeW91IHNob3VsZCBiZSBhYmxlIHRvIHdyaXRlIHNvbWUg SmF2YXNjcmlwdCB0byBjb2RlIGluIGFuIGF1dG9jb21wbGV0ZSBib3ggb3Igc29tZXRoaW5nLkwA AFMAAAAGcGFyc2VyUwAAAARodG1s Onnoonno@filosofie.behttp://filosofie.be2007-12-12T13:19:02Znono0The Admin is an app made with django. It is not Django, it is nice to have it if you need to make a website. But if you make an app then you better roll out your own Admin. I can't understand why people think the admin is Django and it should do al sorts of things. The Admin is Django + a admin application. If you have 10.000 users you write your own user view.The Admin is an app made with django. It is not Django, it is nice to have it if you need to make a website. But if you make an app then you better roll out your own Admin. I can't understand why people think the admin is Django and it should do al sorts of things. The Admin is Django + a admin application. If you have 10.000 users you write your own user view.SQAAAAJTAAAABGJvZHlSUwAAAW1UaGUgQWRtaW4gaXMgYW4gYXBwIG1hZGUgd2l0aCBkamFuZ28u IEl0IGlzIG5vdCBEamFuZ28sIGl0IGlzIG5pY2UgdG8gaGF2ZSBpdCBpZiB5b3UgbmVlZCB0byBt YWtlIGEgd2Vic2l0ZS4gQnV0IGlmIHlvdSBtYWtlIGFuIGFwcCB0aGVuIHlvdSBiZXR0ZXIgcm9s bCBvdXQgeW91ciBvd24gQWRtaW4uIEkgY2FuJ3QgdW5kZXJzdGFuZCB3aHkgcGVvcGxlIHRoaW5r IHRoZSBhZG1pbiBpcyBEamFuZ28gYW5kIGl0IHNob3VsZCBkbyBhbCBzb3J0cyBvZiB0aGluZ3Mu IFRoZSBBZG1pbiBpcyBEamFuZ28gKyBhIGFkbWluIGFwcGxpY2F0aW9uLiAKCklmIHlvdSBoYXZl IDEwLjAwMCB1c2VycyB5b3Ugd3JpdGUgeW91ciBvd24gdXNlciB2aWV3LkwAAFMAAAAGcGFyc2Vy UwAAAARodG1s Danieldaniel@eight.nlhttp://blog.eight.nl2007-12-12T13:19:24Znono0I can see why developers would argue that version numbers aren't important, but developers aren't the only ones to decide which technology is used. (sadly) So some business decider with a project with huge stakes hears two camps of developers, one supporting a 0.xx version technology and the other supporting a 2.xx version. The camp with the 0.xx version technology has got some explaining to do! (instead of discussing what should be the issue: the features etc.)I can see why developers would argue that version numbers aren't important, but developers aren't the only ones to decide which technology is used. (sadly) So some business decider with a project with huge stakes hears two camps of developers, one supporting a 0.xx version technology and the other supporting a 2.xx version. The camp with the 0.xx version technology has got some explaining to do! (instead of discussing what should be the issue: the features etc.)SQAAAAJTAAAABGJvZHlSUwAAAdJJIGNhbiBzZWUgd2h5IGRldmVsb3BlcnMgd291bGQgYXJndWUg dGhhdCB2ZXJzaW9uIG51bWJlcnMgYXJlbid0IGltcG9ydGFudCwgYnV0IGRldmVsb3BlcnMgYXJl bid0IHRoZSBvbmx5IG9uZXMgdG8gZGVjaWRlIHdoaWNoIHRlY2hub2xvZ3kgaXMgdXNlZC4gKHNh ZGx5KQpTbyBzb21lIGJ1c2luZXNzIGRlY2lkZXIgd2l0aCBhIHByb2plY3Qgd2l0aCBodWdlIHN0 YWtlcyBoZWFycyB0d28gY2FtcHMgb2YgZGV2ZWxvcGVycywgb25lIHN1cHBvcnRpbmcgYSAwLnh4 IHZlcnNpb24gdGVjaG5vbG9neSBhbmQgdGhlIG90aGVyIHN1cHBvcnRpbmcgYSAyLnh4IHZlcnNp b24uClRoZSBjYW1wIHdpdGggdGhlIDAueHggdmVyc2lvbiB0ZWNobm9sb2d5IGhhcyBnb3Qgc29t ZSBleHBsYWluaW5nIHRvIGRvIQooaW5zdGVhZCBvZiBkaXNjdXNzaW5nIHdoYXQgc2hvdWxkIGJl IHRoZSBpc3N1ZTogdGhlIGZlYXR1cmVzIGV0Yy4pTAAAUwAAAAZwYXJzZXJTAAAABGh0bWw= Braydon Fullercourier@braydon.comhttp://braydon.com2007-12-12T13:27:39Znono0I'm not sure what the point of jumping to calling it v2. If they are departing, or breaking compatibility with previous versions, etc. then that would make sense. Or signal a major change, but if it's just to be a higher number for comparison reasons, that's kinda confusing. Django, RoR seems to be most about convenience, than anything else. IMO Combining disparate pieces of software together leads to the most interesting software. Although everything isn't all in one place (from the developers point of view, documentation, dependencies, etc.) the diversity can be healthy and keep things agile flexible, and avoid becoming bloated.I'm not sure what the point of jumping to calling it v2. If they are departing, or breaking compatibility with previous versions, etc. then that would make sense. Or signal a major change, but if it's just to be a higher number for comparison reasons, that's kinda confusing. Django, RoR seems to be most about convenience, than anything else. IMO Combining disparate pieces of software together leads to the most interesting software. Although everything isn't all in one place (from the developers point of view, documentation, dependencies, etc.) the diversity can be healthy and keep things agile flexible, and avoid becoming bloated.SQAAAAJTAAAABGJvZHlSUwAAAoBJJ20gbm90IHN1cmUgd2hhdCB0aGUgcG9pbnQgb2YganVtcGlu ZyB0byBjYWxsaW5nIGl0IHYyLiBJZiB0aGV5IGFyZSBkZXBhcnRpbmcsIG9yIGJyZWFraW5nICBj b21wYXRpYmlsaXR5IHdpdGggcHJldmlvdXMgdmVyc2lvbnMsIGV0Yy4gdGhlbiB0aGF0IHdvdWxk IG1ha2Ugc2Vuc2UuIE9yIHNpZ25hbCBhIG1ham9yIGNoYW5nZSwgYnV0IGlmIGl0J3MganVzdCB0 byBiZSBhIGhpZ2hlciBudW1iZXIgZm9yIGNvbXBhcmlzb24gcmVhc29ucywgdGhhdCdzIGtpbmRh IGNvbmZ1c2luZy4KCkRqYW5nbywgUm9SIHNlZW1zIHRvIGJlIG1vc3QgYWJvdXQgY29udmVuaWVu Y2UsIHRoYW4gYW55dGhpbmcgZWxzZS4gSU1PIENvbWJpbmluZyBkaXNwYXJhdGUgcGllY2VzIG9m IHNvZnR3YXJlIHRvZ2V0aGVyIGxlYWRzIHRvIHRoZSBtb3N0IGludGVyZXN0aW5nIHNvZnR3YXJl LiBBbHRob3VnaCBldmVyeXRoaW5nIGlzbid0IGFsbCBpbiBvbmUgcGxhY2UgKGZyb20gdGhlIGRl dmVsb3BlcnMgcG9pbnQgb2YgdmlldywgZG9jdW1lbnRhdGlvbiwgZGVwZW5kZW5jaWVzLCBldGMu KSB0aGUgZGl2ZXJzaXR5IGNhbiBiZSBoZWFsdGh5IGFuZCBrZWVwIHRoaW5ncyBhZ2lsZSBmbGV4 aWJsZSwgYW5kIGF2b2lkIGJlY29taW5nIGJsb2F0ZWQuTAAAUwAAAAZwYXJzZXJTAAAABGh0bWw= Simon Willisonsimon@simonwillison.nethttp://simonwillison.nett/2007-12-12T13:29:19Znono0You should be able to solve the 50,000 users problem using the "raw_id_admin=True" flag on the ForeignKey field - that replaces the "select an object from this select dropdown" widget with a text field that you can enter an integer ID in along with a link that launches a search interface to help you find the ID. If that doesn't solve your problem, this is a serious bug in Django's admin: it's meant to be able to scale up to large numbers of related objects.You should be able to solve the 50,000 users problem using the "raw_id_admin=True" flag on the ForeignKey field - that replaces the "select an object from this select dropdown" widget with a text field that you can enter an integer ID in along with a link that launches a search interface to help you find the ID. If that doesn't solve your problem, this is a serious bug in Django's admin: it's meant to be able to scale up to large numbers of related objects.SQAAAAJTAAAABGJvZHlSUwAAAc5Zb3Ugc2hvdWxkIGJlIGFibGUgdG8gc29sdmUgdGhlIDUwLDAw MCB1c2VycyBwcm9ibGVtIHVzaW5nIHRoZSAicmF3X2lkX2FkbWluPVRydWUiIGZsYWcgb24gdGhl IEZvcmVpZ25LZXkgZmllbGQgLSB0aGF0IHJlcGxhY2VzIHRoZSAic2VsZWN0IGFuIG9iamVjdCBm cm9tIHRoaXMgc2VsZWN0IGRyb3Bkb3duIiB3aWRnZXQgd2l0aCBhIHRleHQgZmllbGQgdGhhdCB5 b3UgY2FuIGVudGVyIGFuIGludGVnZXIgSUQgaW4gYWxvbmcgd2l0aCBhIGxpbmsgdGhhdCBsYXVu Y2hlcyBhIHNlYXJjaCBpbnRlcmZhY2UgdG8gaGVscCB5b3UgZmluZCB0aGUgSUQuCgpJZiB0aGF0 IGRvZXNuJ3Qgc29sdmUgeW91ciBwcm9ibGVtLCB0aGlzIGlzIGEgc2VyaW91cyBidWcgaW4gRGph bmdvJ3MgYWRtaW46IGl0J3MgbWVhbnQgdG8gYmUgYWJsZSB0byBzY2FsZSB1cCB0byBsYXJnZSBu dW1iZXJzIG9mIHJlbGF0ZWQgb2JqZWN0cy5MAABTAAAABnBhcnNlclMAAAAEaHRtbA== Pradeep Gowdabtbytes@yahoo.comhttp://www.btbytes.com2007-12-12T14:31:55Znono0Having too many values in the drop down list is not a difficult problem to solve. Our app (which used the automatic django admin interface to the fullest possible extent) had a purchase Order module in which the user keys in Item code. As you can imagine there are thousands of items in the item master table. We got around this by using newforms and Javascript autocomplete. Moving an app from automatic admin interface to newforms is pretty easy.Having too many values in the drop down list is not a difficult problem to solve. Our app (which used the automatic django admin interface to the fullest possible extent) had a purchase Order module in which the user keys in Item code. As you can imagine there are thousands of items in the item master table. We got around this by using newforms and Javascript autocomplete. Moving an app from automatic admin interface to newforms is pretty easy.SQAAAAJTAAAABGJvZHlSUwAAAcVIYXZpbmcgdG9vIG1hbnkgdmFsdWVzIGluIHRoZSBkcm9wIGRv d24gbGlzdCBpcyBub3QgYSBkaWZmaWN1bHQgcHJvYmxlbSB0byBzb2x2ZS4gCgpPdXIgYXBwICh3 aGljaCB1c2VkIHRoZSBhdXRvbWF0aWMgZGphbmdvIGFkbWluIGludGVyZmFjZSB0byB0aGUgZnVs bGVzdCBwb3NzaWJsZSBleHRlbnQpIGhhZCBhIHB1cmNoYXNlIE9yZGVyIG1vZHVsZSBpbiB3aGlj aCB0aGUgdXNlciBrZXlzIGluIEl0ZW0gY29kZS4gQXMgeW91IGNhbiBpbWFnaW5lIHRoZXJlIGFy ZSB0aG91c2FuZHMgb2YgaXRlbXMgaW4gdGhlIGl0ZW0gbWFzdGVyIHRhYmxlLiAKCldlIGdvdCBh cm91bmQgdGhpcyBieSB1c2luZyBuZXdmb3JtcyBhbmQgSmF2YXNjcmlwdCBhdXRvY29tcGxldGUu CgpNb3ZpbmcgYW4gYXBwIGZyb20gYXV0b21hdGljIGFkbWluIGludGVyZmFjZSB0byBuZXdmb3Jt cyBpcyBwcmV0dHkgZWFzeS5MAABTAAAABnBhcnNlclMAAAAEaHRtbA== neeleshneeleshs@gmail.comhttp://mirroronthenet.org2007-12-12T14:43:23Znono0An issue I bumped in to with Django was aggregate functions. There is not much support for SQL aggregate functions in Django.(http://code.djangoproject.com/ticket/3566) Rails wins here (count, avg etc) , by providing more aggregate functions and the ease with which you can use SQL directly (Whether its a good thing or not is another debate, but it helps getting things done).An issue I bumped in to with Django was aggregate functions. There is not much support for SQL aggregate functions in Django.(http://code.djangoproject.com/ticket/3566) Rails wins here (count, avg etc) , by providing more aggregate functions and the ease with which you can use SQL directly (Whether its a good thing or not is another debate, but it helps getting things done).SQAAAAJTAAAABGJvZHlSUwAAAXtBbiBpc3N1ZSBJIGJ1bXBlZCBpbiB0byB3aXRoIERqYW5nbyB3 YXMgYWdncmVnYXRlIGZ1bmN0aW9ucy4gIFRoZXJlIGlzIG5vdCBtdWNoIHN1cHBvcnQgZm9yIFNR TCBhZ2dyZWdhdGUgZnVuY3Rpb25zIGluIERqYW5nby4oaHR0cDovL2NvZGUuZGphbmdvcHJvamVj dC5jb20vdGlja2V0LzM1NjYpICBSYWlscyB3aW5zIGhlcmUgKGNvdW50LCBhdmcgZXRjKSAsIGJ5 IHByb3ZpZGluZyBtb3JlIGFnZ3JlZ2F0ZSBmdW5jdGlvbnMgYW5kIHRoZSBlYXNlIHdpdGggd2hp Y2ggeW91IGNhbiB1c2UgU1FMIGRpcmVjdGx5IChXaGV0aGVyIGl0cyBhIGdvb2QgdGhpbmcgb3Ig bm90IGlzIGFub3RoZXIgZGViYXRlLCBidXQgaXQgaGVscHMgZ2V0dGluZyB0aGluZ3MgZG9uZSku TAAAUwAAAAZwYXJzZXJTAAAABGh0bWw= Konradkonryd@gmail.comhttp://konryd.blogspot.com2007-12-12T16:27:49Znono0It's a funny thing though - there's no group of developers that can avoid bikeshed discussion. www.yellow.bikeshed.comIt's a funny thing though - there's no group of developers that can avoid bikeshed discussion. www.yellow.bikeshed.comSQAAAAJTAAAABGJvZHlSUwAAAHdJdCdzIGEgZnVubnkgdGhpbmcgdGhvdWdoIC0gdGhlcmUncyBu byBncm91cCBvZiBkZXZlbG9wZXJzIHRoYXQgY2FuIGF2b2lkIGJpa2VzaGVkIGRpc2N1c3Npb24u Cgp3d3cueWVsbG93LmJpa2VzaGVkLmNvbUwAAFMAAAAGcGFyc2VyUwAAAARodG1s Jeff Croftjeff@jeffcroft.comhttp://jeffcroft.com/2007-12-12T17:06:47Znono0I actually agree with some of your points about the Django admin interface not being optimal Wilson designed it, what, three years ago, and it hasn't been touched since. It's definitely in need of an update, and has been for some time. But, how can you use problems with the totally-optional admin app as a way to say, "Django isn't where Rails it at," when Rails doesn't include an admin application at all? If you don't like the admin app, you can do exactly what you'd do in Rails: build your own. The Django admin is simply a tool available that you can use if it works for you. If it doesn't, you'll build one, just like you would in Rails. Same goes for auth. If you don't like it, don't use it. But, you can't say the optional auth app's problems make Django worse than Rails, when Rails doesn't include an auth app at all. Right?I actually agree with some of your points about the Django admin interface not being optimal Wilson designed it, what, three years ago, and it hasn't been touched since. It's definitely in need of an update, and has been for some time. But, how can you use problems with the totally-optional admin app as a way to say, "Django isn't where Rails it at," when Rails doesn't include an admin application at all? If you don't like the admin app, you can do exactly what you'd do in Rails: build your own. The Django admin is simply a tool available that you can use if it works for you. If it doesn't, you'll build one, just like you would in Rails. Same goes for auth. If you don't like it, don't use it. But, you can't say the optional auth app's problems make Django worse than Rails, when Rails doesn't include an auth app at all. Right?SQAAAAJTAAAABGJvZHlSUwAAA0lJIGFjdHVhbGx5IGFncmVlIHdpdGggc29tZSBvZiB5b3VyIHBv aW50cyBhYm91dCB0aGUgRGphbmdvIGFkbWluIGludGVyZmFjZSBub3QgYmVpbmcgb3B0aW1hbCBX aWxzb24gZGVzaWduZWQgaXQsIHdoYXQsIHRocmVlIHllYXJzIGFnbywgYW5kIGl0IGhhc24ndCBi ZWVuIHRvdWNoZWQgc2luY2UuIEl0J3MgZGVmaW5pdGVseSBpbiBuZWVkIG9mIGFuIHVwZGF0ZSwg YW5kIGhhcyBiZWVuIGZvciBzb21lIHRpbWUuIAoKQnV0LCBob3cgY2FuIHlvdSB1c2UgcHJvYmxl bXMgd2l0aCB0aGUgdG90YWxseS1vcHRpb25hbCBhZG1pbiBhcHAgYXMgYSB3YXkgdG8gc2F5LCAi RGphbmdvIGlzbid0IHdoZXJlIFJhaWxzIGl0IGF0LCIgd2hlbiBSYWlscyBkb2Vzbid0IGluY2x1 ZGUgYW4gYWRtaW4gYXBwbGljYXRpb24gYXQgYWxsPyBJZiB5b3UgZG9uJ3QgbGlrZSB0aGUgYWRt aW4gYXBwLCB5b3UgY2FuIGRvIGV4YWN0bHkgd2hhdCB5b3UnZCBkbyBpbiBSYWlsczogYnVpbGQg eW91ciBvd24uIFRoZSBEamFuZ28gYWRtaW4gaXMgc2ltcGx5IGEgdG9vbCBhdmFpbGFibGUgdGhh dCB5b3UgY2FuIHVzZSBpZiBpdCB3b3JrcyBmb3IgeW91LiBJZiBpdCBkb2Vzbid0LCB5b3UnbGwg YnVpbGQgb25lLCBqdXN0IGxpa2UgeW91IHdvdWxkIGluIFJhaWxzLgoKU2FtZSBnb2VzIGZvciBh dXRoLiBJZiB5b3UgZG9uJ3QgbGlrZSBpdCwgZG9uJ3QgdXNlIGl0LiBCdXQsIHlvdSBjYW4ndCBz YXkgdGhlIG9wdGlvbmFsIGF1dGggYXBwJ3MgcHJvYmxlbXMgbWFrZSBEamFuZ28gd29yc2UgdGhh biBSYWlscywgd2hlbiBSYWlscyBkb2Vzbid0IGluY2x1ZGUgYW4gYXV0aCBhcHAgYXQgYWxsLgoK UmlnaHQ/TAAAUwAAAAZwYXJzZXJTAAAABGh0bWw= Armin Ronacherarmin.ronacher@active-4.comhttp://lucumr.pocoo.org/2007-12-12T17:45:56Znono0Woa. Quite a lot of response. Guess I have to straighten out some things. Yes it's true that django admin is not strictly part of the framework and yes, it's an addon library. However very tightly integrated into the django system, especially the ORM. This is not a bad thing and there is huge potential. On the other hand it's also true that having an administration application being part of the framework is a plus over rails. But if we look at django the framework has four major elements: The object relational mapper, the form validation library and the WSGI/mod_python/HTTP modules and finally the template engine. The first element, the ORM is "crippled" compared to SQLAlchemy. One the one hand because there is no session system which becomes pain in the ass pretty soon if you see what the session system does in an SQLAlchemy powered application. However there are also strengths of the ORM, namely that it's incredible user friendly. But zzzeek is working incredible hard on making SQLAlchemy easier and easier and recent versions are great fun to work with. And yes, you can of course use SQLAlchemy with django, but then you loose the admin and all the other great features that depend on the models. The form validation and the admin system are certainly django's biggest plus over alternative solutions. But as it turns out the admin becomes problematic for more complex data models and you have to create your own administration interface anyways. Python has a huge number of great libraries, don't forget about that. There is Genshi which, without doubt, is the so far best XML based template engine I found for an agile scripting language. There is SQLAlchemy which permanently blows my mind in what's possible and how you can use the library. There is WSGI and libraries that built up on it (like Paste, Werkzeug, Webob...). There is a huge number of libraries you probably don't know yet ;-) Those libraries combined together make (currently) a good scaling application if you know what you're doing. Django certainly leaves TurboGears out in the rain. It's easy to integrate other libraries in django, even if others often claim that this is not the case. But you also lose all the strengths of django other frameworks don't have (admin, auth). And if you lose all of them you are left with a (well performing) WSGI library plus a bunch of utilities you could have otherwise to. So I really would say: Make that a 1.0 release and blow our minds with cool additions in the future (like migrations, an even better extensible administrator interface, row based permissions, subclass-able models) and revive the SQLAlchemy branch which would be the ultimate feature in django. Regards, ArminWoa. Quite a lot of response. Guess I have to straighten out some things. Yes it's true that django admin is not strictly part of the framework and yes, it's an addon library. However very tightly integrated into the django system, especially the ORM. This is not a bad thing and there is huge potential. On the other hand it's also true that having an administration application being part of the framework is a plus over rails. But if we look at django the framework has four major elements: The object relational mapper, the form validation library and the WSGI/mod_python/HTTP modules and finally the template engine. The first element, the ORM is "crippled" compared to SQLAlchemy. One the one hand because there is no session system which becomes pain in the ass pretty soon if you see what the session system does in an SQLAlchemy powered application. However there are also strengths of the ORM, namely that it's incredible user friendly. But zzzeek is working incredible hard on making SQLAlchemy easier and easier and recent versions are great fun to work with. And yes, you can of course use SQLAlchemy with django, but then you loose the admin and all the other great features that depend on the models. The form validation and the admin system are certainly django's biggest plus over alternative solutions. But as it turns out the admin becomes problematic for more complex data models and you have to create your own administration interface anyways. Python has a huge number of great libraries, don't forget about that. There is Genshi which, without doubt, is the so far best XML based template engine I found for an agile scripting language. There is SQLAlchemy which permanently blows my mind in what's possible and how you can use the library. There is WSGI and libraries that built up on it (like Paste, Werkzeug, Webob...). There is a huge number of libraries you probably don't know yet ;-) Those libraries combined together make (currently) a good scaling application if you know what you're doing. Django certainly leaves TurboGears out in the rain. It's easy to integrate other libraries in django, even if others often claim that this is not the case. But you also lose all the strengths of django other frameworks don't have (admin, auth). And if you lose all of them you are left with a (well performing) WSGI library plus a bunch of utilities you could have otherwise to. So I really would say: Make that a 1.0 release and blow our minds with cool additions in the future (like migrations, an even better extensible administrator interface, row based permissions, subclass-able models) and revive the SQLAlchemy branch which would be the ultimate feature in django. Regards, ArminSQAAAAJTAAAABGJvZHlSUwAACp1Xb2EuIFF1aXRlIGEgbG90IG9mIHJlc3BvbnNlLiBHdWVzcyBJ IGhhdmUgdG8gc3RyYWlnaHRlbiBvdXQgc29tZSB0aGluZ3MuCgpZZXMgaXQncyB0cnVlIHRoYXQg ZGphbmdvIGFkbWluIGlzIG5vdCBzdHJpY3RseSBwYXJ0IG9mIHRoZSBmcmFtZXdvcmsgYW5kIHll cywgaXQncyBhbiBhZGRvbiBsaWJyYXJ5LiBIb3dldmVyIHZlcnkgdGlnaHRseSBpbnRlZ3JhdGVk IGludG8gdGhlIGRqYW5nbyBzeXN0ZW0sIGVzcGVjaWFsbHkgdGhlIE9STS4gVGhpcyBpcyBub3Qg YSBiYWQgdGhpbmcgYW5kIHRoZXJlIGlzIGh1Z2UgcG90ZW50aWFsLiBPbiB0aGUgb3RoZXIgaGFu ZCBpdCdzIGFsc28gdHJ1ZSB0aGF0IGhhdmluZyBhbiBhZG1pbmlzdHJhdGlvbiBhcHBsaWNhdGlv biBiZWluZyBwYXJ0IG9mIHRoZSBmcmFtZXdvcmsgaXMgYSBwbHVzIG92ZXIgcmFpbHMuCgpCdXQg aWYgd2UgbG9vayBhdCBkamFuZ28gdGhlIGZyYW1ld29yayBoYXMgZm91ciBtYWpvciBlbGVtZW50 czogVGhlIG9iamVjdCByZWxhdGlvbmFsIG1hcHBlciwgdGhlIGZvcm0gdmFsaWRhdGlvbiBsaWJy YXJ5IGFuZCB0aGUgV1NHSS9tb2RfcHl0aG9uL0hUVFAgbW9kdWxlcyBhbmQgZmluYWxseSB0aGUg dGVtcGxhdGUgZW5naW5lLiBUaGUgZmlyc3QgZWxlbWVudCwgdGhlIE9STSBpcyAiY3JpcHBsZWQi IGNvbXBhcmVkIHRvIFNRTEFsY2hlbXkuIE9uZSB0aGUgb25lIGhhbmQgYmVjYXVzZSB0aGVyZSBp cyBubyBzZXNzaW9uIHN5c3RlbSB3aGljaCBiZWNvbWVzIHBhaW4gaW4gdGhlIGFzcyBwcmV0dHkg c29vbiBpZiB5b3Ugc2VlIHdoYXQgdGhlIHNlc3Npb24gc3lzdGVtIGRvZXMgaW4gYW4gU1FMQWxj aGVteSBwb3dlcmVkIGFwcGxpY2F0aW9uLiBIb3dldmVyIHRoZXJlIGFyZSBhbHNvIHN0cmVuZ3Ro cyBvZiB0aGUgT1JNLCBuYW1lbHkgdGhhdCBpdCdzIGluY3JlZGlibGUgdXNlciBmcmllbmRseS4g QnV0IHp6emVlayBpcyB3b3JraW5nIGluY3JlZGlibGUgaGFyZCBvbiBtYWtpbmcgU1FMQWxjaGVt eSBlYXNpZXIgYW5kIGVhc2llciBhbmQgcmVjZW50IHZlcnNpb25zIGFyZSBncmVhdCBmdW4gdG8g d29yayB3aXRoLiBBbmQgeWVzLCB5b3UgY2FuIG9mIGNvdXJzZSB1c2UgU1FMQWxjaGVteSB3aXRo IGRqYW5nbywgYnV0IHRoZW4geW91IGxvb3NlIHRoZSBhZG1pbiBhbmQgYWxsIHRoZSBvdGhlciBn cmVhdCBmZWF0dXJlcyB0aGF0IGRlcGVuZCBvbiB0aGUgbW9kZWxzLgoKVGhlIGZvcm0gdmFsaWRh dGlvbiBhbmQgdGhlIGFkbWluIHN5c3RlbSBhcmUgY2VydGFpbmx5IGRqYW5nbydzIGJpZ2dlc3Qg cGx1cyBvdmVyIGFsdGVybmF0aXZlIHNvbHV0aW9ucy4gQnV0IGFzIGl0IHR1cm5zIG91dCB0aGUg YWRtaW4gYmVjb21lcyBwcm9ibGVtYXRpYyBmb3IgbW9yZSBjb21wbGV4IGRhdGEgbW9kZWxzIGFu ZCB5b3UgaGF2ZSB0byBjcmVhdGUgeW91ciBvd24gYWRtaW5pc3RyYXRpb24gaW50ZXJmYWNlIGFu eXdheXMuCgpQeXRob24gaGFzIGEgaHVnZSBudW1iZXIgb2YgZ3JlYXQgbGlicmFyaWVzLCBkb24n dCBmb3JnZXQgYWJvdXQgdGhhdC4gVGhlcmUgaXMgR2Vuc2hpIHdoaWNoLCB3aXRob3V0IGRvdWJ0 LCBpcyB0aGUgc28gZmFyIGJlc3QgWE1MIGJhc2VkIHRlbXBsYXRlIGVuZ2luZSBJIGZvdW5kIGZv ciBhbiBhZ2lsZSBzY3JpcHRpbmcgbGFuZ3VhZ2UuIFRoZXJlIGlzIFNRTEFsY2hlbXkgd2hpY2gg cGVybWFuZW50bHkgYmxvd3MgbXkgbWluZCBpbiB3aGF0J3MgcG9zc2libGUgYW5kIGhvdyB5b3Ug Y2FuIHVzZSB0aGUgbGlicmFyeS4gVGhlcmUgaXMgV1NHSSBhbmQgbGlicmFyaWVzIHRoYXQgYnVp bHQgdXAgb24gaXQgKGxpa2UgUGFzdGUsIFdlcmt6ZXVnLCBXZWJvYi4uLikuIFRoZXJlIGlzIGEg aHVnZSBudW1iZXIgb2YgbGlicmFyaWVzIHlvdSBwcm9iYWJseSBkb24ndCBrbm93IHlldCA7LSkg VGhvc2UgbGlicmFyaWVzIGNvbWJpbmVkIHRvZ2V0aGVyIG1ha2UgKGN1cnJlbnRseSkgYSBnb29k IHNjYWxpbmcgYXBwbGljYXRpb24gaWYgeW91IGtub3cgd2hhdCB5b3UncmUgZG9pbmcuCgpEamFu Z28gY2VydGFpbmx5IGxlYXZlcyBUdXJib0dlYXJzIG91dCBpbiB0aGUgcmFpbi4gSXQncyBlYXN5 IHRvIGludGVncmF0ZSBvdGhlciBsaWJyYXJpZXMgaW4gZGphbmdvLCBldmVuIGlmIG90aGVycyBv ZnRlbiBjbGFpbSB0aGF0IHRoaXMgaXMgbm90IHRoZSBjYXNlLiBCdXQgeW91IGFsc28gbG9zZSBh bGwgdGhlIHN0cmVuZ3RocyBvZiBkamFuZ28gb3RoZXIgZnJhbWV3b3JrcyBkb24ndCBoYXZlIChh ZG1pbiwgYXV0aCkuIEFuZCBpZiB5b3UgbG9zZSBhbGwgb2YgdGhlbSB5b3UgYXJlIGxlZnQgd2l0 aCBhICh3ZWxsIHBlcmZvcm1pbmcpIFdTR0kgbGlicmFyeSBwbHVzIGEgYnVuY2ggb2YgdXRpbGl0 aWVzIHlvdSBjb3VsZCBoYXZlIG90aGVyd2lzZSB0by4KClNvIEkgcmVhbGx5IHdvdWxkIHNheTog TWFrZSB0aGF0IGEgMS4wIHJlbGVhc2UgYW5kIGJsb3cgb3VyIG1pbmRzIHdpdGggY29vbCBhZGRp dGlvbnMgaW4gdGhlIGZ1dHVyZSAobGlrZSBtaWdyYXRpb25zLCBhbiBldmVuIGJldHRlciBleHRl bnNpYmxlIGFkbWluaXN0cmF0b3IgaW50ZXJmYWNlLCByb3cgYmFzZWQgcGVybWlzc2lvbnMsIHN1 YmNsYXNzLWFibGUgbW9kZWxzKSBhbmQgcmV2aXZlIHRoZSBTUUxBbGNoZW15IGJyYW5jaCB3aGlj aCB3b3VsZCBiZSB0aGUgdWx0aW1hdGUgZmVhdHVyZSBpbiBkamFuZ28uCgpSZWdhcmRzLApBcm1p bkwAAFMAAAAGcGFyc2VyUwAAAARodG1s Paulpaul@prescod.net2007-12-12T17:51:46Znono0I think that one could just as easily make the case that Rails is immature compared to Django because of its (non-)handling of authentication, administration, Unicode and threading. Maybe Django should be at 3.0!I think that one could just as easily make the case that Rails is immature compared to Django because of its (non-)handling of authentication, administration, Unicode and threading. Maybe Django should be at 3.0!SQAAAAJTAAAABGJvZHlSUwAAANRJIHRoaW5rIHRoYXQgb25lIGNvdWxkIGp1c3QgYXMgZWFzaWx5 IG1ha2UgdGhlIGNhc2UgdGhhdCBSYWlscyBpcyBpbW1hdHVyZSBjb21wYXJlZCB0byBEamFuZ28g YmVjYXVzZSBvZiBpdHMgKG5vbi0paGFuZGxpbmcgb2YgYXV0aGVudGljYXRpb24sIGFkbWluaXN0 cmF0aW9uLCBVbmljb2RlIGFuZCB0aHJlYWRpbmcuIE1heWJlIERqYW5nbyBzaG91bGQgYmUgYXQg My4wIUwAAFMAAAAGcGFyc2VyUwAAAARodG1s Armin Ronacherarmin.ronacher@active-4.comhttp://lucumr.pocoo.org/2007-12-12T18:04:29Znono0Paul: Rails is miles ahead of django so far. (Unfortunately). There are plugins that add auth/admin and other fancy stuff to it. And Rails does handle Unicode. And I wouldn't say that django handles threads much better than rails. While Rails might not be threadsafe, Python has a GIL and performs better in a Forking Environment too most of the time (of course consuming more memory).Paul: Rails is miles ahead of django so far. (Unfortunately). There are plugins that add auth/admin and other fancy stuff to it. And Rails does handle Unicode. And I wouldn't say that django handles threads much better than rails. While Rails might not be threadsafe, Python has a GIL and performs better in a Forking Environment too most of the time (of course consuming more memory).SQAAAAJTAAAABGJvZHlSUwAAAYFQYXVsOiBSYWlscyBpcyBtaWxlcyBhaGVhZCBvZiBkamFuZ28g c28gZmFyLiAoVW5mb3J0dW5hdGVseSkuIFRoZXJlIGFyZSBwbHVnaW5zIHRoYXQgYWRkIGF1dGgv YWRtaW4gYW5kIG90aGVyIGZhbmN5IHN0dWZmIHRvIGl0LiBBbmQgUmFpbHMgZG9lcyBoYW5kbGUg VW5pY29kZS4gQW5kIEkgd291bGRuJ3Qgc2F5IHRoYXQgZGphbmdvIGhhbmRsZXMgdGhyZWFkcyBt dWNoIGJldHRlciB0aGFuIHJhaWxzLiBXaGlsZSBSYWlscyBtaWdodCBub3QgYmUgdGhyZWFkc2Fm ZSwgUHl0aG9uIGhhcyBhIEdJTCBhbmQgcGVyZm9ybXMgYmV0dGVyIGluIGEgRm9ya2luZyBFbnZp cm9ubWVudCB0b28gbW9zdCBvZiB0aGUgdGltZSAob2YgY291cnNlIGNvbnN1bWluZyBtb3JlIG1l bW9yeSkuTAAAUwAAAAZwYXJzZXJTAAAABGh0bWw= Chris McAvoychris.mcavoy@gmail.comhttp://weblog.lonelylion.com2007-12-12T18:19:46Znono0I think you make some good points, but they should really be directed at any of the full stack "2.0" web app frameworks. All ORM's end up getting in the way at some point (IMHO), you always end up saying "this would be way more efficient in straight SQL." I've been involved in projects that have addressed the issue in one of two ways, re-work the schema to fit the ORM or work around the ORM to get at raw sql. Both are good solutions depending on the situation. The real strength of Django, Rails, Turbogears, Pylons, and any other newish set of web tools is that they give you a set of usable defaults. However, there's no way to anticipate every need, so they'll all end up "failing" at some point. As long as they give you a reliable facility to fall back to some sort of "raw," you're in the clear. So, given that limitation, my take on it is that the good frameworks are ones that perform well and are reliable. I've had to recommend Rails or Django in a few situations. Today, December 12th, 2007, I recommend using Django, as the base platform is easier to deploy, faster, and more reliable. The free stuff you get with it is a real bonus for the early stages of development. That said, I haven't looked at Rails 2.0, or the latest versions of Pylons or Turbogears. As for 1.0 or 2.0, I don't give a crap.I think you make some good points, but they should really be directed at any of the full stack "2.0" web app frameworks. All ORM's end up getting in the way at some point (IMHO), you always end up saying "this would be way more efficient in straight SQL." I've been involved in projects that have addressed the issue in one of two ways, re-work the schema to fit the ORM or work around the ORM to get at raw sql. Both are good solutions depending on the situation. The real strength of Django, Rails, Turbogears, Pylons, and any other newish set of web tools is that they give you a set of usable defaults. However, there's no way to anticipate every need, so they'll all end up "failing" at some point. As long as they give you a reliable facility to fall back to some sort of "raw," you're in the clear. So, given that limitation, my take on it is that the good frameworks are ones that perform well and are reliable. I've had to recommend Rails or Django in a few situations. Today, December 12th, 2007, I recommend using Django, as the base platform is easier to deploy, faster, and more reliable. The free stuff you get with it is a real bonus for the early stages of development. That said, I haven't looked at Rails 2.0, or the latest versions of Pylons or Turbogears. As for 1.0 or 2.0, I don't give a crap.SQAAAAJTAAAABGJvZHlSUwAABTBJIHRoaW5rIHlvdSBtYWtlIHNvbWUgZ29vZCBwb2ludHMsIGJ1 dCB0aGV5IHNob3VsZCByZWFsbHkgYmUgZGlyZWN0ZWQgYXQgYW55IG9mIHRoZSBmdWxsIHN0YWNr ICIyLjAiIHdlYiBhcHAgZnJhbWV3b3Jrcy4gIEFsbCBPUk0ncyBlbmQgdXAgZ2V0dGluZyBpbiB0 aGUgd2F5IGF0IHNvbWUgcG9pbnQgKElNSE8pLCB5b3UgYWx3YXlzIGVuZCB1cCBzYXlpbmcgInRo aXMgd291bGQgYmUgd2F5IG1vcmUgZWZmaWNpZW50IGluIHN0cmFpZ2h0IFNRTC4iICBJJ3ZlIGJl ZW4gaW52b2x2ZWQgaW4gcHJvamVjdHMgdGhhdCBoYXZlIGFkZHJlc3NlZCB0aGUgaXNzdWUgaW4g b25lIG9mIHR3byB3YXlzLCByZS13b3JrIHRoZSBzY2hlbWEgdG8gZml0IHRoZSBPUk0gb3Igd29y ayBhcm91bmQgdGhlIE9STSB0byBnZXQgYXQgcmF3IHNxbC4gIEJvdGggYXJlIGdvb2Qgc29sdXRp b25zIGRlcGVuZGluZyBvbiB0aGUgc2l0dWF0aW9uLiAgVGhlIHJlYWwgc3RyZW5ndGggb2YgRGph bmdvLCBSYWlscywgVHVyYm9nZWFycywgUHlsb25zLCBhbmQgYW55IG90aGVyIG5ld2lzaCBzZXQg b2Ygd2ViIHRvb2xzIGlzIHRoYXQgdGhleSBnaXZlIHlvdSBhIHNldCBvZiB1c2FibGUgZGVmYXVs dHMuICBIb3dldmVyLCB0aGVyZSdzIG5vIHdheSB0byBhbnRpY2lwYXRlIGV2ZXJ5IG5lZWQsIHNv IHRoZXknbGwgYWxsIGVuZCB1cCAiZmFpbGluZyIgYXQgc29tZSBwb2ludC4gIEFzIGxvbmcgYXMg dGhleSBnaXZlIHlvdSBhIHJlbGlhYmxlIGZhY2lsaXR5IHRvIGZhbGwgYmFjayB0byBzb21lIHNv cnQgb2YgInJhdywiIHlvdSdyZSBpbiB0aGUgY2xlYXIuCgpTbywgZ2l2ZW4gdGhhdCBsaW1pdGF0 aW9uLCBteSB0YWtlIG9uIGl0IGlzIHRoYXQgdGhlIGdvb2QgZnJhbWV3b3JrcyBhcmUgb25lcyB0 aGF0IHBlcmZvcm0gd2VsbCBhbmQgYXJlIHJlbGlhYmxlLiAgSSd2ZSBoYWQgdG8gcmVjb21tZW5k IFJhaWxzIG9yIERqYW5nbyBpbiBhIGZldyBzaXR1YXRpb25zLiAgVG9kYXksIERlY2VtYmVyIDEy dGgsIDIwMDcsIEkgcmVjb21tZW5kIHVzaW5nIERqYW5nbywgYXMgdGhlIGJhc2UgcGxhdGZvcm0g aXMgZWFzaWVyIHRvIGRlcGxveSwgZmFzdGVyLCBhbmQgbW9yZSByZWxpYWJsZS4gIFRoZSBmcmVl IHN0dWZmIHlvdSBnZXQgd2l0aCBpdCBpcyBhIHJlYWwgYm9udXMgZm9yIHRoZSBlYXJseSBzdGFn ZXMgb2YgZGV2ZWxvcG1lbnQuICBUaGF0IHNhaWQsIEkgaGF2ZW4ndCBsb29rZWQgYXQgUmFpbHMg Mi4wLCBvciB0aGUgbGF0ZXN0IHZlcnNpb25zIG9mIFB5bG9ucyBvciBUdXJib2dlYXJzLiAKCkFz IGZvciAxLjAgb3IgMi4wLCBJIGRvbid0IGdpdmUgYSBjcmFwLkwAAFMAAAAGcGFyc2VyUwAAAARo dG1s Marcelo Fernándezfernandezm22@yahoo.com.arhttp://marcelosoft.blogspot.com2007-12-12T18:55:13Znono0Hi Armin, I couldn't agree more with you. I've implemented Django and "suffered" the same things (mainly) with the ORM layer. On the other side, I think the template system is great, and the Jinja library is there to expand it. http://jinja.pocoo.org/ Cheers! MarceloHi Armin, I couldn't agree more with you. I've implemented Django and "suffered" the same things (mainly) with the ORM layer. On the other side, I think the template system is great, and the Jinja library is there to expand it. http://jinja.pocoo.org/ Cheers! MarceloSQAAAAJTAAAABGJvZHlSUwAAAQ1IaSBBcm1pbiwgSSBjb3VsZG4ndCBhZ3JlZSBtb3JlIHdpdGgg eW91LiBJJ3ZlIGltcGxlbWVudGVkIERqYW5nbyBhbmQgInN1ZmZlcmVkIiB0aGUgc2FtZSB0aGlu Z3MgKG1haW5seSkgd2l0aCB0aGUgT1JNIGxheWVyLiBPbiB0aGUgb3RoZXIgc2lkZSwgSSB0aGlu ayB0aGUgdGVtcGxhdGUgc3lzdGVtIGlzIGdyZWF0LCBhbmQgdGhlIEppbmphIGxpYnJhcnkgaXMg dGhlcmUgdG8gZXhwYW5kIGl0LgoKaHR0cDovL2ppbmphLnBvY29vLm9yZy8KCkNoZWVycyEKTWFy Y2Vsb0wAAFMAAAAGcGFyc2VyUwAAAARodG1s AkitaOnRailsfabioakita@gmail.comhttp://www.akitaonrails.com2007-12-12T19:09:23Znono0Though I realize this is a Django discussion, I couldn't resist trying a bit of Rails here. For those of you that never tried Rails, I've compiled a very very speed up "Rails 2.0 Screencast":http://www.akitaonrails.com/2007/12/10/the-first-rails-2-0-screencast-english. In less than 30 min you can see some of the new features and what can be accomplished. About Rails not having an Admin app, it can be an advantage or disadvantage depending on your point of view. If you're mainly dealing with content management, this is a plus. Though mixing a Framework with a highly integrated App is arguably an optimal situation. I'd like to have Rails being the kitchen-sink and I can later add ActiveScaffold, for example, if I want very fast admin screens. Authentication can be done is several different ways and I also don't think it belongs to the framework, as we have several plugins to tackle this matter as well. That said, I also don't think there only needs to be one framework, there is room for DJango, Rails, and many more.Though I realize this is a Django discussion, I couldn't resist trying a bit of Rails here. For those of you that never tried Rails, I've compiled a very very speed up "Rails 2.0 Screencast":http://www.akitaonrails.com/2007/12/10/the-first-rails-2-0-screencast-english. In less than 30 min you can see some of the new features and what can be accomplished. About Rails not having an Admin app, it can be an advantage or disadvantage depending on your point of view. If you're mainly dealing with content management, this is a plus. Though mixing a Framework with a highly integrated App is arguably an optimal situation. I'd like to have Rails being the kitchen-sink and I can later add ActiveScaffold, for example, if I want very fast admin screens. Authentication can be done is several different ways and I also don't think it belongs to the framework, as we have several plugins to tackle this matter as well. That said, I also don't think there only needs to be one framework, there is room for DJango, Rails, and many more.SQAAAAJTAAAABGJvZHlSUwAABAhUaG91Z2ggSSByZWFsaXplIHRoaXMgaXMgYSBEamFuZ28gZGlz Y3Vzc2lvbiwgSSBjb3VsZG4ndCByZXNpc3QgdHJ5aW5nIGEgYml0IG9mIFJhaWxzIGhlcmUuIEZv ciB0aG9zZSBvZiB5b3UgdGhhdCBuZXZlciB0cmllZCBSYWlscywgSSd2ZSBjb21waWxlZCBhIHZl cnkgdmVyeSBzcGVlZCB1cCAiUmFpbHMgMi4wIFNjcmVlbmNhc3QiOmh0dHA6Ly93d3cuYWtpdGFv bnJhaWxzLmNvbS8yMDA3LzEyLzEwL3RoZS1maXJzdC1yYWlscy0yLTAtc2NyZWVuY2FzdC1lbmds aXNoLiBJbiBsZXNzIHRoYW4gMzAgbWluIHlvdSBjYW4gc2VlIHNvbWUgb2YgdGhlIG5ldyBmZWF0 dXJlcyBhbmQgd2hhdCBjYW4gYmUgYWNjb21wbGlzaGVkLiAKCkFib3V0IFJhaWxzIG5vdCBoYXZp bmcgYW4gQWRtaW4gYXBwLCBpdCBjYW4gYmUgYW4gYWR2YW50YWdlIG9yIGRpc2FkdmFudGFnZSBk ZXBlbmRpbmcgb24geW91ciBwb2ludCBvZiB2aWV3LiBJZiB5b3UncmUgbWFpbmx5IGRlYWxpbmcg d2l0aCBjb250ZW50IG1hbmFnZW1lbnQsIHRoaXMgaXMgYSBwbHVzLiBUaG91Z2ggbWl4aW5nIGEg RnJhbWV3b3JrIHdpdGggYSBoaWdobHkgaW50ZWdyYXRlZCBBcHAgaXMgYXJndWFibHkgYW4gb3B0 aW1hbCBzaXR1YXRpb24uIEknZCBsaWtlIHRvIGhhdmUgUmFpbHMgYmVpbmcgdGhlIGtpdGNoZW4t c2luayBhbmQgSSBjYW4gbGF0ZXIgYWRkIEFjdGl2ZVNjYWZmb2xkLCBmb3IgZXhhbXBsZSwgaWYg SSB3YW50IHZlcnkgZmFzdCBhZG1pbiBzY3JlZW5zLiBBdXRoZW50aWNhdGlvbiBjYW4gYmUgZG9u ZSBpcyBzZXZlcmFsIGRpZmZlcmVudCB3YXlzIGFuZCBJIGFsc28gZG9uJ3QgdGhpbmsgaXQgYmVs b25ncyB0byB0aGUgZnJhbWV3b3JrLCBhcyB3ZSBoYXZlIHNldmVyYWwgcGx1Z2lucyB0byB0YWNr bGUgdGhpcyBtYXR0ZXIgYXMgd2VsbC4KClRoYXQgc2FpZCwgSSBhbHNvIGRvbid0IHRoaW5rIHRo ZXJlIG9ubHkgbmVlZHMgdG8gYmUgb25lIGZyYW1ld29yaywgdGhlcmUgaXMgcm9vbSBmb3IgREph bmdvLCBSYWlscywgYW5kIG1hbnkgbW9yZS5MAABTAAAABnBhcnNlclMAAAAEaHRtbA== Armin Ronacherarmin.ronacher@active-4.comhttp://lucumr.pocoo.org/2007-12-12T19:25:10Znono0@AkitaOnRails: Python has more to offer than just Django. If one wants something like rails there is Pylons or a custom WSGI application which, thanks to SQLAlchemy, gives you a very good database access. Seriously. Replacing Django with Rails is like switching from one evil to the other. And even if Rails still leads the framework war, Django is doing great progress. I just don't think that it's ready for 2.0 *yet* :-) Regards, Armin@AkitaOnRails: Python has more to offer than just Django. If one wants something like rails there is Pylons or a custom WSGI application which, thanks to SQLAlchemy, gives you a very good database access. Seriously. Replacing Django with Rails is like switching from one evil to the other. And even if Rails still leads the framework war, Django is doing great progress. I just don't think that it's ready for 2.0 *yet* :-) Regards, ArminSQAAAAJTAAAABGJvZHlSUwAAAbhAQWtpdGFPblJhaWxzOiBQeXRob24gaGFzIG1vcmUgdG8gb2Zm ZXIgdGhhbiBqdXN0IERqYW5nby4gSWYgb25lIHdhbnRzIHNvbWV0aGluZyBsaWtlIHJhaWxzIHRo ZXJlIGlzIFB5bG9ucyBvciBhIGN1c3RvbSBXU0dJIGFwcGxpY2F0aW9uIHdoaWNoLCB0aGFua3Mg dG8gU1FMQWxjaGVteSwgZ2l2ZXMgeW91IGEgdmVyeSBnb29kIGRhdGFiYXNlIGFjY2Vzcy4gU2Vy aW91c2x5LiBSZXBsYWNpbmcgRGphbmdvIHdpdGggUmFpbHMgaXMgbGlrZSBzd2l0Y2hpbmcgZnJv bSBvbmUgZXZpbCB0byB0aGUgb3RoZXIuIEFuZCBldmVuIGlmIFJhaWxzIHN0aWxsIGxlYWRzIHRo ZSBmcmFtZXdvcmsgd2FyLCBEamFuZ28gaXMgZG9pbmcgZ3JlYXQgcHJvZ3Jlc3MuCgpJIGp1c3Qg ZG9uJ3QgdGhpbmsgdGhhdCBpdCdzIHJlYWR5IGZvciAyLjAgKnlldCogOi0pCgpSZWdhcmRzLApB cm1pbkwAAFMAAAAGcGFyc2VyUwAAAARodG1s casseencas@casoraaaa.com2007-12-12T21:46:11Znono0Rails is great and in my op is a littel more mature than django and other python frameworks. But the point is not rails vs django but rather python vs ruby. And as you all know, python is like poetry ; )Rails is great and in my op is a littel more mature than django and other python frameworks. But the point is not rails vs django but rather python vs ruby. And as you all know, python is like poetry ; )SQAAAAJTAAAABGJvZHlSUwAAAMtSYWlscyBpcyBncmVhdCBhbmQgaW4gbXkgb3AgaXMgYSBsaXR0 ZWwgbW9yZSBtYXR1cmUgdGhhbiBkamFuZ28gYW5kIG90aGVyIHB5dGhvbiBmcmFtZXdvcmtzLiBC dXQgdGhlIHBvaW50IGlzIG5vdCByYWlscyB2cyBkamFuZ28gYnV0IHJhdGhlciBweXRob24gdnMg cnVieS4gQW5kIGFzIHlvdSBhbGwga25vdywgcHl0aG9uIGlzIGxpa2UgcG9ldHJ5IDsgKUwAAFMA AAAGcGFyc2VyUwAAAARodG1s heraldsheofjq@hot.com2007-12-13T01:12:45Znono0"But the point is not rails vs django but rather python vs ruby. And as you all know, python is like poetry ; )" Ruby is cleaner (except for 'end', but python forces you to indent+':' so that is not a huge compensational win, since you cant choose to not have that) than python. The ambiguity cat.meow() is a joke, the variable mandatory "self" name in python is a joke too. (I am not saying python itself is a joke, python has some great things going for it, which you notice if you see that really many use python) To be honest... i think both python and ruby lost the battle of the www to... PHP And this makes me sad. Php is a horrible language, but people use it. Everyone talks about the www. Django and RoR are web FRAMEWORKs. WEB! This is where PHP won, and both python and ruby should focus in GOOD deal with the www. Www is all about interacting with other people. We dont need a fancy erlang - we need software from people, for people. And when i write people, I mean BILLIONS of people! Everyone is a user! The www has won. PHP won the first round, it is time to make it lose again!"But the point is not rails vs django but rather python vs ruby. And as you all know, python is like poetry ; )" Ruby is cleaner (except for 'end', but python forces you to indent+':' so that is not a huge compensational win, since you cant choose to not have that) than python. The ambiguity cat.meow() is a joke, the variable mandatory "self" name in python is a joke too. (I am not saying python itself is a joke, python has some great things going for it, which you notice if you see that really many use python) To be honest... i think both python and ruby lost the battle of the www to... PHP And this makes me sad. Php is a horrible language, but people use it. Everyone talks about the www. Django and RoR are web FRAMEWORKs. WEB! This is where PHP won, and both python and ruby should focus in GOOD deal with the www. Www is all about interacting with other people. We dont need a fancy erlang - we need software from people, for people. And when i write people, I mean BILLIONS of people! Everyone is a user! The www has won. PHP won the first round, it is time to make it lose again!SQAAAAJTAAAABGJvZHlSUwAABE8iQnV0IHRoZSBwb2ludCBpcyBub3QgcmFpbHMgdnMgZGphbmdv IGJ1dCByYXRoZXIgcHl0aG9uIHZzIHJ1YnkuIEFuZCBhcyB5b3UgYWxsIGtub3csIHB5dGhvbiBp cyBsaWtlIHBvZXRyeSA7ICkiClJ1YnkgaXMgY2xlYW5lciAoZXhjZXB0IGZvciAnZW5kJywgYnV0 IHB5dGhvbiBmb3JjZXMgeW91IHRvIGluZGVudCsnOicgc28gdGhhdCBpcyBub3QgYSBodWdlIGNv bXBlbnNhdGlvbmFsIHdpbiwgc2luY2UgeW91IGNhbnQgY2hvb3NlIHRvIG5vdCBoYXZlIHRoYXQp IHRoYW4gcHl0aG9uLiBUaGUgYW1iaWd1aXR5IGNhdC5tZW93KCkgaXMgYSBqb2tlLCB0aGUgdmFy aWFibGUgbWFuZGF0b3J5ICJzZWxmIiBuYW1lIGluIHB5dGhvbiBpcyBhIGpva2UgdG9vLiAoSSBh bSBub3Qgc2F5aW5nIHB5dGhvbiBpdHNlbGYgaXMgYSBqb2tlLCBweXRob24gaGFzIHNvbWUgZ3Jl YXQgdGhpbmdzIGdvaW5nIGZvciBpdCwgd2hpY2ggeW91IG5vdGljZSBpZiB5b3Ugc2VlIHRoYXQg cmVhbGx5IG1hbnkgdXNlIHB5dGhvbikKClRvIGJlIGhvbmVzdC4uLiBpIHRoaW5rIGJvdGggcHl0 aG9uIGFuZCBydWJ5IGxvc3QgdGhlIGJhdHRsZSBvZiB0aGUgd3d3IHRvLi4uClBIUAoKQW5kIHRo aXMgbWFrZXMgbWUgc2FkLiBQaHAgaXMgYSBob3JyaWJsZSBsYW5ndWFnZSwgYnV0IHBlb3BsZSB1 c2UgaXQuIAoKRXZlcnlvbmUgdGFsa3MgYWJvdXQgdGhlIHd3dy4gRGphbmdvIGFuZCBSb1IgYXJl IHdlYiBGUkFNRVdPUktzLgpXRUIhIFRoaXMgaXMgd2hlcmUgUEhQIHdvbiwgYW5kIGJvdGggcHl0 aG9uIGFuZCBydWJ5IHNob3VsZCBmb2N1cyAKaW4gR09PRCBkZWFsIHdpdGggdGhlIHd3dy4gV3d3 IGlzIGFsbCBhYm91dCBpbnRlcmFjdGluZyB3aXRoIG90aGVyIHBlb3BsZS4KV2UgZG9udCBuZWVk IGEgZmFuY3kgZXJsYW5nIC0gd2UgbmVlZCBzb2Z0d2FyZSBmcm9tIHBlb3BsZSwgZm9yIHBlb3Bs ZS4gQW5kIAp3aGVuIGkgd3JpdGUgcGVvcGxlLCBJIG1lYW4gQklMTElPTlMgb2YgcGVvcGxlISBF dmVyeW9uZSBpcyBhIHVzZXIhCgpUaGUgd3d3IGhhcyB3b24uIAoKUEhQIHdvbiB0aGUgZmlyc3Qg cm91bmQsIGl0IGlzIHRpbWUgdG8gbWFrZSBpdCBsb3NlIGFnYWluIUwAAFMAAAAGcGFyc2VyUwAA AARodG1s jamesjames_027@yahoo.com2007-12-13T04:51:39Znono0@AkitaOnRails: Django and Rails are both good web frameworks for the reason both of them are having a success. Since you're a rails user. does rails has something like Django's newforms? And I like what you can do to Django's middleware very powerful :). The only room for improvement I think Django should do is for the templates. In the end I agree with casseen, it's python vs ruby. @Armin: Thanks for informing that SQLAlchemy is getting easier to use :) Cheers@AkitaOnRails: Django and Rails are both good web frameworks for the reason both of them are having a success. Since you're a rails user. does rails has something like Django's newforms? And I like what you can do to Django's middleware very powerful :). The only room for improvement I think Django should do is for the templates. In the end I agree with casseen, it's python vs ruby. @Armin: Thanks for informing that SQLAlchemy is getting easier to use :) CheersSQAAAAJTAAAABGJvZHlSUwAAAdNAQWtpdGFPblJhaWxzOiBEamFuZ28gYW5kIFJhaWxzIGFyZSBi b3RoIGdvb2Qgd2ViIGZyYW1ld29ya3MgZm9yIHRoZSByZWFzb24gYm90aCBvZiB0aGVtIGFyZSBo YXZpbmcgYSBzdWNjZXNzLiBTaW5jZSB5b3UncmUgYSByYWlscyB1c2VyLiBkb2VzIHJhaWxzIGhh cyBzb21ldGhpbmcgbGlrZSBEamFuZ28ncyBuZXdmb3Jtcz8gQW5kIEkgbGlrZSB3aGF0IHlvdSBj YW4gZG8gdG8gRGphbmdvJ3MgbWlkZGxld2FyZSB2ZXJ5IHBvd2VyZnVsIDopLiBUaGUgb25seSBy b29tIGZvciBpbXByb3ZlbWVudCBJIHRoaW5rIERqYW5nbyBzaG91bGQgZG8gaXMgZm9yIHRoZSB0 ZW1wbGF0ZXMuIEluIHRoZSBlbmQgSSBhZ3JlZSB3aXRoIGNhc3NlZW4sIGl0J3MgcHl0aG9uIHZz IHJ1YnkuCgpAQXJtaW46IFRoYW5rcyBmb3IgaW5mb3JtaW5nIHRoYXQgU1FMQWxjaGVteSBpcyBn ZXR0aW5nIGVhc2llciB0byB1c2UgOikKCkNoZWVyc0wAAFMAAAAGcGFyc2VyUwAAAARodG1s AndrewSKkurinnyi@hotmail.com2007-12-13T07:08:37Znono0Have you tried monkey patching the User model itself, to add the number of user posts directly to User? It's incredibly easy. http://www.amitu.com/blog/2007/july/django-extending-user-model/Have you tried monkey patching the User model itself, to add the number of user posts directly to User? It's incredibly easy. http://www.amitu.com/blog/2007/july/django-extending-user-model/SQAAAAJTAAAABGJvZHlSUwAAAMBIYXZlIHlvdSB0cmllZCBtb25rZXkgcGF0Y2hpbmcgdGhlIFVz ZXIgbW9kZWwgaXRzZWxmLCB0byBhZGQgdGhlIG51bWJlciBvZiB1c2VyIHBvc3RzIGRpcmVjdGx5 IHRvIFVzZXI/IEl0J3MgaW5jcmVkaWJseSBlYXN5LiAKCmh0dHA6Ly93d3cuYW1pdHUuY29tL2Js b2cvMjAwNy9qdWx5L2RqYW5nby1leHRlbmRpbmctdXNlci1tb2RlbC9MAABTAAAABnBhcnNlclMA AAAEaHRtbA== Emptymtrier@gmail.comhttp://blog.michaeltrier.com2007-12-15T01:52:12Znono0Great post. I think Django is great. I blog about it, I write about it, and I spend considerable time helping people learn it. That said I think it's important to make a fair assessment about your strengths and weaknesses as a project, and constantly work to produce something that's better. I agree with you on the whole 2.0 version number thing. It's nonsense.Great post. I think Django is great. I blog about it, I write about it, and I spend considerable time helping people learn it. That said I think it's important to make a fair assessment about your strengths and weaknesses as a project, and constantly work to produce something that's better. I agree with you on the whole 2.0 version number thing. It's nonsense.SQAAAAJTAAAABGJvZHlSUwAAAXFHcmVhdCBwb3N0LiAgSSB0aGluayBEamFuZ28gaXMgZ3JlYXQu ICBJIGJsb2cgYWJvdXQgaXQsIEkgd3JpdGUgYWJvdXQgaXQsIGFuZCBJIHNwZW5kIGNvbnNpZGVy YWJsZSB0aW1lIGhlbHBpbmcgcGVvcGxlIGxlYXJuIGl0LiAgVGhhdCBzYWlkIEkgdGhpbmsgaXQn cyBpbXBvcnRhbnQgdG8gbWFrZSBhIGZhaXIgYXNzZXNzbWVudCBhYm91dCB5b3VyIHN0cmVuZ3Ro cyBhbmQgd2Vha25lc3NlcyBhcyBhIHByb2plY3QsIGFuZCBjb25zdGFudGx5IHdvcmsgdG8gcHJv ZHVjZSBzb21ldGhpbmcgdGhhdCdzIGJldHRlci4gIAoKSSBhZ3JlZSB3aXRoIHlvdSBvbiB0aGUg d2hvbGUgMi4wIHZlcnNpb24gbnVtYmVyIHRoaW5nLiAgSXQncyBub25zZW5zZS5MAABTAAAABnBh cnNlclMAAAAEaHRtbA== Benjamin Wiegandbeewee@ubuntuusers.de2007-12-15T19:39:29Znono0Thanks for your Post, AndrewSK. Your sollution is dirty but works :)Thanks for your Post, AndrewSK. Your sollution is dirty but works :)SQAAAAJTAAAABGJvZHlSUwAAAERUaGFua3MgZm9yIHlvdXIgUG9zdCwgQW5kcmV3U0suIFlvdXIg c29sbHV0aW9uIGlzIGRpcnR5IGJ1dCB3b3JrcyA6KUwAAFMAAAAGcGFyc2VyUwAAAARodG1s Extenuating Circumstances – links for 2008-01-07http://danhon.com/2008/01/07/links-for-2008-01-07/2008-01-07T10:20:53Znoyes0[...] Lucumr Cogitations » Blog Archive » Django’s Problems and Why 2.0 is a Bad Idea (tags: comparison django rails ruby webdev python orm curse fork development) [...][...] Lucumr Cogitations » Blog Archive » Django&#8217;s Problems and Why 2.0 is a Bad Idea (tags: comparison django rails ruby webdev python orm curse fork development) [...]SQAAAAJTAAAABGJvZHlSUwAAAK1bLi4uXSBMdWN1bXIgQ29naXRhdGlvbnMgwrsgQmxvZyBBcmNo aXZlIMK7IERqYW5nb+KAmXMgUHJvYmxlbXMgYW5kIFdoeSAyLjAgaXMgYSBCYWQgSWRlYSAodGFn czogY29tcGFyaXNvbiBkamFuZ28gcmFpbHMgcnVieSB3ZWJkZXYgcHl0aG9uIG9ybSBjdXJzZSBm b3JrIGRldmVsb3BtZW50KSBbLi4uXUwAAFMAAAAGcGFyc2VyUwAAAARodG1s Werkzeug Example Applications Onlinehttp://lucumr.pocoo.org/cogitations/2007/12/11/werkzeug-example-applications-online/2007-12-11T22:30:00Z2007-12-11T22:30:00ZArmin Ronacherwerkzeug-example-applications-onlineyesyes2I now installed the <a href="http://werkzeug.pocoo.org/">Werkzeug</a> example applications on pocoo.org. So you don't have to pull all the code if you want to try them out :-) Here is the <a href="http://werkzeug.pocoo.org/e/simplewiki/">Wiki</a> and the <a href="http://werkzeug.pocoo.org/e/plnt/">Planet</a>. Have fun testing.I now installed the <a href="http://werkzeug.pocoo.org/">Werkzeug</a> example applications on pocoo.org. So you don't have to pull all the code if you want to try them out :-) Here is the <a href="http://werkzeug.pocoo.org/e/simplewiki/">Wiki</a> and the <a href="http://werkzeug.pocoo.org/e/plnt/">Planet</a>. Have fun testing.SQAAAANTAAAABGJvZHlSUwAAABRJIG5vdyBpbnN0YWxsZWQgdGhlIEwAA0VTAAAAAWFMAABNAAFT AAAABGhyZWZTAAAAGmh0dHA6Ly93ZXJremV1Zy5wb2Nvby5vcmcvUwAAAAhXZXJremV1Z1MAAAB5 IGV4YW1wbGUgYXBwbGljYXRpb25zIG9uIHBvY29vLm9yZy4gIFNvIHlvdSBkb24ndCBoYXZlIHRv IHB1bGwgYWxsIHRoZSBjb2RlIGlmIHlvdSB3YW50IHRvIHRyeSB0aGVtIG91dCA6LSkKCkhlcmUg aXMgdGhlIEVTAAAAAWFMAABNAAFTAAAABGhyZWZTAAAAJ2h0dHA6Ly93ZXJremV1Zy5wb2Nvby5v cmcvZS9zaW1wbGV3aWtpL1MAAAAEV2lraVMAAAAJIGFuZCB0aGUgRVMAAAABYUwAAE0AAVMAAAAE aHJlZlMAAAAhaHR0cDovL3dlcmt6ZXVnLnBvY29vLm9yZy9lL3BsbnQvUwAAAAZQbGFuZXRTAAAA Ey4gSGF2ZSBmdW4gdGVzdGluZy5TAAAABnBhcnNlclMAAAAEaHRtbFMAAAAFaW50cm9SUwAAAABM AAA= Werkzeug Debugger in Djangohttp://lucumr.pocoo.org/cogitations/2007/12/10/werkzeug-debugged-in-django/2007-12-10T17:30:24Z2007-12-10T17:30:24ZArmin Ronacherwerkzeug-debugged-in-djangoyesyes2(Thanks monkey patching). Ugly but works: <a href="http://dev.pocoo.org/projects/werkzeug/wiki/UsingDebuggerWithDjango">using the werkzeug debugger with django</a>. Now digg/reddit it ;-)(Thanks monkey patching). Ugly but works: <a href="http://dev.pocoo.org/projects/werkzeug/wiki/UsingDebuggerWithDjango">using the werkzeug debugger with django</a>. Now digg/reddit it ;-)SQAAAANTAAAABGJvZHlSUwAAACsoVGhhbmtzIG1vbmtleSBwYXRjaGluZykuICBVZ2x5IGJ1dCB3 b3JrczogTAABRVMAAAABYUwAAE0AAVMAAAAEaHJlZlMAAABDaHR0cDovL2Rldi5wb2Nvby5vcmcv cHJvamVjdHMvd2Vya3pldWcvd2lraS9Vc2luZ0RlYnVnZ2VyV2l0aERqYW5nb1MAAAAndXNpbmcg dGhlIHdlcmt6ZXVnIGRlYnVnZ2VyIHdpdGggZGphbmdvUwAAABkuCgpOb3cgZGlnZy9yZWRkaXQg aXQgOy0pUwAAAAZwYXJzZXJTAAAABGh0bWxTAAAABWludHJvUlMAAAAATAAA Eric Florenzanofloguy@gmail.comhttp://www.eflorenzano.com/2007-12-10T20:21:20Znono0Cool stuff, I asked about this in a comment on your last blog post and today it's already patched in!Cool stuff, I asked about this in a comment on your last blog post and today it's already patched in!SQAAAAJTAAAABGJvZHlSUwAAAGVDb29sIHN0dWZmLCBJIGFza2VkIGFib3V0IHRoaXMgaW4gYSBj b21tZW50IG9uIHlvdXIgbGFzdCBibG9nIHBvc3QgYW5kIHRvZGF5IGl0J3MgYWxyZWFkeSBwYXRj aGVkIGluIUwAAFMAAAAGcGFyc2VyUwAAAARodG1s Arnearne@rcs4u.dehttp://www.arnebrodowski.de/blog/2007-12-15T14:34:28Znono0I've added: <pre>import django from django.core.servers.basehttp import AdminMediaHandler [...] if __name__ == '__main__': path = django.__path__[0] + '/contrib/admin/media/' run_simple('localhost', 8080, DebuggedApplication(AdminMediaHandler(WSGIHandler(),path), True))</pre> now it also serves my admin-media files correctly in the development environment, this is how django would do it, when the dev-server is used.I've added: <pre>import django from django.core.servers.basehttp import AdminMediaHandler [...] if __name__ == '__main__': path = django.__path__[0] + '/contrib/admin/media/' run_simple('localhost', 8080, DebuggedApplication(AdminMediaHandler(WSGIHandler(),path), True))</pre> now it also serves my admin-media files correctly in the development environment, this is how django would do it, when the dev-server is used.SQAAAAJTAAAABGJvZHlSUwAAAAxJJ3ZlIGFkZGVkOgpMAAFFUwAAAANwcmVMAABNAABTAAABBWlt cG9ydCBkamFuZ28KZnJvbSBkamFuZ28uY29yZS5zZXJ2ZXJzLmJhc2VodHRwIGltcG9ydCBBZG1p bk1lZGlhSGFuZGxlcgpbLi4uXQppZiBfX25hbWVfXyA9PSAnX19tYWluX18nOgogICAgcGF0aCA9 IGRqYW5nby5fX3BhdGhfX1swXSArICcvY29udHJpYi9hZG1pbi9tZWRpYS8nCiAgICBydW5fc2lt cGxlKCdsb2NhbGhvc3QnLCA4MDgwLCBEZWJ1Z2dlZEFwcGxpY2F0aW9uKEFkbWluTWVkaWFIYW5k bGVyKFdTR0lIYW5kbGVyKCkscGF0aCksIFRydWUpKVMAAACQCgpub3cgaXQgYWxzbyBzZXJ2ZXMg bXkgYWRtaW4tbWVkaWEgZmlsZXMgY29ycmVjdGx5IGluIHRoZSBkZXZlbG9wbWVudCBlbnZpcm9u bWVudCwgdGhpcyBpcyBob3cgZGphbmdvIHdvdWxkIGRvIGl0LCB3aGVuIHRoZSBkZXYtc2VydmVy IGlzIHVzZWQuUwAAAAZwYXJzZXJTAAAABGh0bWw= Amazon byteflow: Дебаг Джангиhttp://piranha.org.ua/blog/2007/12/16/django-debug/2007-12-15T22:32:49Znoyes0[...] после одной отличной новости можно значительно облегчить себе [...][...] после одной отличной новости можно значительно облегчить себе [...]SQAAAAJTAAAABGJvZHlSUwAAAH9bLi4uXSDQv9C+0YHQu9C1INC+0LTQvdC+0Lkg0L7RgtC70LjR h9C90L7QuSDQvdC+0LLQvtGB0YLQuCDQvNC+0LbQvdC+INC30L3QsNGH0LjRgtC10LvRjNC90L4g 0L7QsdC70LXQs9GH0LjRgtGMINGB0LXQsdC1IFsuLi5dTAAAUwAAAAZwYXJzZXJTAAAABGh0bWw= Nickfignya@gmail.com2007-12-19T16:40:25Znono0only this modified version worked for me in Windows: <pre>#!/usr/bin/env python import os, sys from os.path import abspath, dirname from werkzeug import run_simple, DebuggedApplication from django.views import debug from django.core.handlers.wsgi import WSGIHandler def null_technical_500_response(request, exc_type, exc_value, tb): raise exc_type, exc_value, tb debug.technical_500_response = null_technical_500_response os.environ['DJANGO_SETTINGS_MODULE'] = 'settings' path = os.path.abspath(dirname(dirname(abspath(__file__)))) sys.path.append(path) if __name__ == '__main__': run_simple('localhost', 8080, DebuggedApplication(WSGIHandler(), True), True)</pre>only this modified version worked for me in Windows: <pre>#!/usr/bin/env python import os, sys from os.path import abspath, dirname from werkzeug import run_simple, DebuggedApplication from django.views import debug from django.core.handlers.wsgi import WSGIHandler def null_technical_500_response(request, exc_type, exc_value, tb): raise exc_type, exc_value, tb debug.technical_500_response = null_technical_500_response os.environ['DJANGO_SETTINGS_MODULE'] = 'settings' path = os.path.abspath(dirname(dirname(abspath(__file__)))) sys.path.append(path) if __name__ == '__main__': run_simple('localhost', 8080, DebuggedApplication(WSGIHandler(), True), True)</pre>SQAAAAJTAAAABGJvZHlSUwAAADZvbmx5IHRoaXMgbW9kaWZpZWQgdmVyc2lvbiB3b3JrZWQgZm9y IG1lIGluIFdpbmRvd3M6CgpMAAFFUwAAAANwcmVMAABNAABTAAACZSMhL3Vzci9iaW4vZW52IHB5 dGhvbgppbXBvcnQgb3MsIHN5cwpmcm9tIG9zLnBhdGggaW1wb3J0IGFic3BhdGgsIGRpcm5hbWUK CmZyb20gd2Vya3pldWcgaW1wb3J0IHJ1bl9zaW1wbGUsIERlYnVnZ2VkQXBwbGljYXRpb24KZnJv bSBkamFuZ28udmlld3MgaW1wb3J0IGRlYnVnCmZyb20gZGphbmdvLmNvcmUuaGFuZGxlcnMud3Nn aSBpbXBvcnQgV1NHSUhhbmRsZXIKCmRlZiBudWxsX3RlY2huaWNhbF81MDBfcmVzcG9uc2UocmVx dWVzdCwgZXhjX3R5cGUsIGV4Y192YWx1ZSwgdGIpOgogICAgcmFpc2UgZXhjX3R5cGUsIGV4Y192 YWx1ZSwgdGIKZGVidWcudGVjaG5pY2FsXzUwMF9yZXNwb25zZSA9IG51bGxfdGVjaG5pY2FsXzUw MF9yZXNwb25zZQoKb3MuZW52aXJvblsnREpBTkdPX1NFVFRJTkdTX01PRFVMRSddID0gJ3NldHRp bmdzJwoKcGF0aCA9IG9zLnBhdGguYWJzcGF0aChkaXJuYW1lKGRpcm5hbWUoYWJzcGF0aChfX2Zp bGVfXykpKSkKc3lzLnBhdGguYXBwZW5kKHBhdGgpCgppZiBfX25hbWVfXyA9PSAnX19tYWluX18n OgogICAgcnVuX3NpbXBsZSgnbG9jYWxob3N0JywgODA4MCwgRGVidWdnZWRBcHBsaWNhdGlvbihX U0dJSGFuZGxlcigpLCBUcnVlKSwgVHJ1ZSlTAAAAAFMAAAAGcGFyc2VyUwAAAARodG1s We don’t need namespaces…http://lucumr.pocoo.org/cogitations/2007/12/10/we-dont-need-namespaces%e2%80%a6/2007-12-10T14:07:17Z2007-12-10T14:07:17ZArmin Ronacherwe-dont-need-namespaces%e2%80%a6yesyes2…because we use prefixes: <!-- PYGMENTS_CACHE><div class="highlight"><pre><span class="cp">&lt;?php</span> <span class="k">class</span> <span class="nc">Zend_Search_Lucene_Analysis_Analyzer_Common_TextNum_CaseInsensitive</span> <span class="k">extends</span> <span class="nx">Zend_Search_Lucene_Analysis_Analyzer_Common_TextNum</span> </pre></div> <PYGMENTS_CACHE --><!-- PYGMENTS_RAW(php)><?php class Zend_Search_Lucene_Analysis_Analyzer_Common_TextNum_CaseInsensitive extends Zend_Search_Lucene_Analysis_Analyzer_Common_TextNum<PYGMENTS_RAW --> Found in the Zend framework :-)…because we use prefixes: Found in the Zend framework :-)SQAAAANTAAAABGJvZHlSUwAAAD7igKZiZWNhdXNlIHdlIHVzZSBwcmVmaXhlczoKCgoKRm91bmQg aW4gdGhlIFplbmQgZnJhbWV3b3JrIDotKUwAAFMAAAAGcGFyc2VyUwAAAARodG1sUwAAAAVpbnRy b1JTAAAAAEwAAA== Alex Jonesalex@weej.comhttp://alex.weej.com/2007-12-10T18:06:13Znono0Just count yourself lucky there aren't any FactoryFactoryFactoryFactory's in there.Just count yourself lucky there aren't any FactoryFactoryFactoryFactory's in there.SQAAAAJTAAAABGJvZHlSUwAAAFNKdXN0IGNvdW50IHlvdXJzZWxmIGx1Y2t5IHRoZXJlIGFyZW4n dCBhbnkgRmFjdG9yeUZhY3RvcnlGYWN0b3J5RmFjdG9yeSdzIGluIHRoZXJlLkwAAFMAAAAGcGFy c2VyUwAAAARodG1s EvildeadEvildead@gmail.com2007-12-10T18:22:20Znono0OMG, I would rather die than doing this.OMG, I would rather die than doing this.SQAAAAJTAAAABGJvZHlSUwAAAChPTUcsIEkgd291bGQgcmF0aGVyIGRpZSB0aGFuIGRvaW5nIHRo aXMuTAAAUwAAAAZwYXJzZXJTAAAABGh0bWw= Adeel Khanpyninja@gmail.comhttp://umbc.edu/~adeel2/2007-12-10T18:49:38Znono0The Zend framework is horrible.The Zend framework is horrible.SQAAAAJTAAAABGJvZHlSUwAAAB9UaGUgWmVuZCBmcmFtZXdvcmsgaXMgaG9ycmlibGUuTAAAUwAA AAZwYXJzZXJTAAAABGh0bWw= Brianbrian.cassidy@gmail.com2007-12-10T20:42:39Znono0Oddly enough, today i saw a post linking to this: http://news.php.net/php.internals/33694 (RFC: Dropping Namespace)Oddly enough, today i saw a post linking to this: http://news.php.net/php.internals/33694 (RFC: Dropping Namespace)SQAAAAJTAAAABGJvZHlSUwAAAHNPZGRseSBlbm91Z2gsIHRvZGF5IGkgc2F3IGEgcG9zdCBsaW5r aW5nIHRvIHRoaXM6IGh0dHA6Ly9uZXdzLnBocC5uZXQvcGhwLmludGVybmFscy8zMzY5NCAoUkZD OiBEcm9wcGluZyBOYW1lc3BhY2UpTAAAUwAAAAZwYXJzZXJTAAAABGh0bWw= Werkzeug 0.1 Releasedhttp://lucumr.pocoo.org/cogitations/2007/12/09/werkzeug-01-released/2007-12-09T18:58:22Z2007-12-09T18:58:22ZArmin Ronacherwerkzeug-01-releasedyesyes2Finally (sorry for the long delay) <a href="http://werkzeug.pocoo.org/">Werkzeug</a> 0.1 is out. Here parts of the current featurelist: <ul> <li>Provides Request and Response objects for WSGI</li> <li>Handles file uploads by using temporary files for incoming data.</li> <li>Provides a middleware for static data for development purposes</li> <li>Tiny wrapper around wsgiref for easier development (autoreload, optional multithreaded enviornment)</li> <li>Unicode aware data processing. Just use unicode everywhere, werkzeug handles that for you.</li> <li>Mini template engine. Sometimes string formattings just are not enough and real template engines are too big for that tiny task.</li> <li>Context locals. Don't pass request/user/database connections and other objects around. Put them on a global context local object and werkzeug makes sure that everyting is cleaned up end delivered well.</li> <li>Test utilities. Create fake WSGI environments and requests to test your application.</li> <li>Interactive debugger. Application dies with an error? Hook the debugger in and inspect every frame.</li> </ul> Here a screenshot of the debugger in action: <img class="standalone" src="http://werkzeug.pocoo.org/static/debugger.png" alt="screenshot of the debugger"> Small werkzeug example applications can be found <a href="http://dev.pocoo.org/projects/werkzeug/browser/examples">in the trac</a>. In the werkzeug.contrib package are also some pieces of code that can be useful for django developers. For example there is a stream wrapper that limits incoming form data to a given number of bytes. This is useful for django because django streams into the memory and not to the file system. Have fun and report bugs / feature wishes in the trac :-) Get it while it's hot from the <a href="http://cheeseshop.python.org/pypi/Werkzeug/0.1">Cheeseshop</a>.Finally (sorry for the long delay) <a href="http://werkzeug.pocoo.org/">Werkzeug</a> 0.1 is out. Here parts of the current featurelist: <ul> <li>Provides Request and Response objects for WSGI</li> <li>Handles file uploads by using temporary files for incoming data.</li> <li>Provides a middleware for static data for development purposes</li> <li>Tiny wrapper around wsgiref for easier development (autoreload, optional multithreaded enviornment)</li> <li>Unicode aware data processing. Just use unicode everywhere, werkzeug handles that for you.</li> <li>Mini template engine. Sometimes string formattings just are not enough and real template engines are too big for that tiny task.</li> <li>Context locals. Don't pass request/user/database connections and other objects around. Put them on a global context local object and werkzeug makes sure that everyting is cleaned up end delivered well.</li> <li>Test utilities. Create fake WSGI environments and requests to test your application.</li> <li>Interactive debugger. Application dies with an error? Hook the debugger in and inspect every frame.</li> </ul> Here a screenshot of the debugger in action: <img src="http://werkzeug.pocoo.org/static/debugger.png" alt="screenshot of the debugger" class="standalone"> Small werkzeug example applications can be found <a href="http://dev.pocoo.org/projects/werkzeug/browser/examples">in the trac</a>. In the werkzeug.contrib package are also some pieces of code that can be useful for django developers. For example there is a stream wrapper that limits incoming form data to a given number of bytes. This is useful for django because django streams into the memory and not to the file system. Have fun and report bugs / feature wishes in the trac :-) Get it while it's hot from the <a href="http://cheeseshop.python.org/pypi/Werkzeug/0.1">Cheeseshop</a>.SQAAAANTAAAABGJvZHlSUwAAACNGaW5hbGx5IChzb3JyeSBmb3IgdGhlIGxvbmcgZGVsYXkpIEwA BUVTAAAAAWFMAABNAAFTAAAABGhyZWZTAAAAGmh0dHA6Ly93ZXJremV1Zy5wb2Nvby5vcmcvUwAA AAhXZXJremV1Z1MAAAA0IDAuMSBpcyBvdXQuIEhlcmUgcGFydHMgb2YgdGhlIGN1cnJlbnQgZmVh dHVyZWxpc3Q6CkVTAAAAAnVsTAAJRVMAAAACbGlMAABNAABTAAAALlByb3ZpZGVzIFJlcXVlc3Qg YW5kIFJlc3BvbnNlIG9iamVjdHMgZm9yIFdTR0lTAAAABQogICAgRVMAAAACbGlMAABNAABTAAAA QEhhbmRsZXMgZmlsZSB1cGxvYWRzIGJ5IHVzaW5nIHRlbXBvcmFyeSBmaWxlcyBmb3IgaW5jb21p bmcgZGF0YS5TAAAABgoKICAgIEVTAAAAAmxpTAAATQAAUwAAAD5Qcm92aWRlcyBhIG1pZGRsZXdh cmUgZm9yIHN0YXRpYyBkYXRhIGZvciBkZXZlbG9wbWVudCBwdXJwb3Nlc1MAAAAFCiAgICBFUwAA AAJsaUwAAE0AAFMAAABrVGlueSB3cmFwcGVyIGFyb3VuZCB3c2dpcmVmIGZvciBlYXNpZXIgZGV2 ZWxvcG1lbnQgKGF1dG9yZWxvYWQsIG9wdGlvbmFsCiAgICAgICAgbXVsdGl0aHJlYWRlZCBlbnZp b3JubWVudClTAAAABQogICAgRVMAAAACbGlMAABNAABTAAAAYlVuaWNvZGUgYXdhcmUgZGF0YSBw cm9jZXNzaW5nLiBKdXN0IHVzZSB1bmljb2RlIGV2ZXJ5d2hlcmUsIHdlcmt6ZXVnCiAgICAgICAg aGFuZGxlcyB0aGF0IGZvciB5b3UuUwAAAAUKICAgIEVTAAAAAmxpTAAATQAAUwAAAIhNaW5pIHRl bXBsYXRlIGVuZ2luZS4gU29tZXRpbWVzIHN0cmluZyBmb3JtYXR0aW5ncyBqdXN0IGFyZSBub3Qg ZW5vdWdoCiAgICAgICAgYW5kIHJlYWwgdGVtcGxhdGUgZW5naW5lcyBhcmUgdG9vIGJpZyBmb3Ig dGhhdCB0aW55IHRhc2suUwAAAAUKICAgIEVTAAAAAmxpTAAATQAAUwAAANtDb250ZXh0IGxvY2Fs cy4gIERvbid0IHBhc3MgcmVxdWVzdC91c2VyL2RhdGFiYXNlIGNvbm5lY3Rpb25zIGFuZAogICAg ICAgIG90aGVyIG9iamVjdHMgYXJvdW5kLiAgUHV0IHRoZW0gb24gYSBnbG9iYWwgY29udGV4dCBs b2NhbCBvYmplY3QgYW5kCiAgICAgICAgd2Vya3pldWcgbWFrZXMgc3VyZSB0aGF0IGV2ZXJ5dGlu ZyBpcyBjbGVhbmVkIHVwIGVuZCBkZWxpdmVyZWQgd2VsbC5TAAAABQogICAgRVMAAAACbGlMAABN AABTAAAAXVRlc3QgdXRpbGl0aWVzLiAgQ3JlYXRlIGZha2UgV1NHSSBlbnZpcm9ubWVudHMgYW5k IHJlcXVlc3RzIHRvIHRlc3QKICAgICAgICB5b3VyIGFwcGxpY2F0aW9uLlMAAAAFCiAgICBFUwAA AAJsaUwAAE0AAFMAAABsSW50ZXJhY3RpdmUgZGVidWdnZXIuICBBcHBsaWNhdGlvbiBkaWVzIHdp dGggYW4gZXJyb3I/IEhvb2sgdGhlIGRlYnVnZ2VyCiAgICAgICAgaW4gYW5kIGluc3BlY3QgZXZl cnkgZnJhbWUuUwAAAAEKTQAAUwAAAAUKICAgIFMAAAAvCgpIZXJlIGEgc2NyZWVuc2hvdCBvZiB0 aGUgZGVidWdnZXIgaW4gYWN0aW9uOgpFUwAAAANpbWdMAABNAANTAAAAA3NyY1MAAAAtaHR0cDov L3dlcmt6ZXVnLnBvY29vLm9yZy9zdGF0aWMvZGVidWdnZXIucG5nUwAAAANhbHRTAAAAGnNjcmVl bnNob3Qgb2YgdGhlIGRlYnVnZ2VyUwAAAAVjbGFzc1MAAAAKc3RhbmRhbG9uZVMAAAAAUwAAADMK ClNtYWxsIHdlcmt6ZXVnIGV4YW1wbGUgYXBwbGljYXRpb25zIGNhbiBiZSBmb3VuZCBFUwAAAAFh TAAATQABUwAAAARocmVmUwAAADdodHRwOi8vZGV2LnBvY29vLm9yZy9wcm9qZWN0cy93ZXJremV1 Zy9icm93c2VyL2V4YW1wbGVzUwAAAAtpbiB0aGUgdHJhY1MAAAGCLiBJbiB0aGUgd2Vya3pldWcu Y29udHJpYiBwYWNrYWdlIGFyZSBhbHNvIHNvbWUgcGllY2VzIG9mIGNvZGUgdGhhdCBjYW4gYmUg dXNlZnVsIGZvciBkamFuZ28gZGV2ZWxvcGVycy4gRm9yIGV4YW1wbGUgdGhlcmUgaXMgYSBzdHJl YW0gd3JhcHBlciB0aGF0IGxpbWl0cyBpbmNvbWluZyBmb3JtIGRhdGEgdG8gYSBnaXZlbiBudW1i ZXIgb2YgYnl0ZXMuICBUaGlzIGlzIHVzZWZ1bCBmb3IgZGphbmdvIGJlY2F1c2UgZGphbmdvIHN0 cmVhbXMgaW50byB0aGUgbWVtb3J5IGFuZCBub3QgdG8gdGhlIGZpbGUgc3lzdGVtLgoKSGF2ZSBm dW4gYW5kIHJlcG9ydCBidWdzIC8gZmVhdHVyZSB3aXNoZXMgaW4gdGhlIHRyYWMgOi0pIEdldCBp dCB3aGlsZSBpdCdzIGhvdCBmcm9tIHRoZSBFUwAAAAFhTAAATQABUwAAAARocmVmUwAAAC5odHRw Oi8vY2hlZXNlc2hvcC5weXRob24ub3JnL3B5cGkvV2Vya3pldWcvMC4xUwAAAApDaGVlc2VzaG9w UwAAAAEuUwAAAAZwYXJzZXJTAAAABGh0bWxTAAAABWludHJvUlMAAAAATAAA Rafaelrafaelw@gmx.net2007-12-09T19:03:38Znono0Congratulations! This is a really nice lib, thanks for it. I'm using it with pleasure.Congratulations! This is a really nice lib, thanks for it. I'm using it with pleasure.SQAAAAJTAAAABGJvZHlSUwAAAFdDb25ncmF0dWxhdGlvbnMhClRoaXMgaXMgYSByZWFsbHkgbmlj ZSBsaWIsIHRoYW5rcyBmb3IgaXQuCgpJJ20gdXNpbmcgaXQgd2l0aCBwbGVhc3VyZS5MAABTAAAA BnBhcnNlclMAAAAEaHRtbA== Eric Florenzanofloguy@gmail.comhttp://www.eflorenzano.com/2007-12-09T23:12:51Znono0We really could use this web-based console debugger as an option on Django's debug pages. How difficult was it for you to implement?We really could use this web-based console debugger as an option on Django's debug pages. How difficult was it for you to implement?SQAAAAJTAAAABGJvZHlSUwAAAIVXZSByZWFsbHkgY291bGQgdXNlIHRoaXMgd2ViLWJhc2VkIGNv bnNvbGUgZGVidWdnZXIgYXMgYW4gb3B0aW9uIG9uIERqYW5nbydzIGRlYnVnIHBhZ2VzLiAgSG93 IGRpZmZpY3VsdCB3YXMgaXQgZm9yIHlvdSB0byBpbXBsZW1lbnQ/TAAAUwAAAAZwYXJzZXJTAAAA BGh0bWw= Armin Ronacherarmin.ronacher@active-4.comhttp://lucumr.pocoo.org/2007-12-10T07:31:48Znono0There are ways to get that debugger running in django but it's not that easy because django keeps on catching exceptions in the core. That means they are never forwarded to the WSGI layer where the werkzeug debugger operates. If one adds a way to disable the internal debug view and hook in WSGI middlewares, adding werkzeug.debug should be a simple task. Regards, ArminThere are ways to get that debugger running in django but it's not that easy because django keeps on catching exceptions in the core. That means they are never forwarded to the WSGI layer where the werkzeug debugger operates. If one adds a way to disable the internal debug view and hook in WSGI middlewares, adding werkzeug.debug should be a simple task. Regards, ArminSQAAAAJTAAAABGJvZHlSUwAAAXVUaGVyZSBhcmUgd2F5cyB0byBnZXQgdGhhdCBkZWJ1Z2dlciBy dW5uaW5nIGluIGRqYW5nbyBidXQgaXQncyBub3QgdGhhdCBlYXN5IGJlY2F1c2UgZGphbmdvIGtl ZXBzIG9uIGNhdGNoaW5nIGV4Y2VwdGlvbnMgaW4gdGhlIGNvcmUuICBUaGF0IG1lYW5zIHRoZXkg YXJlIG5ldmVyIGZvcndhcmRlZCB0byB0aGUgV1NHSSBsYXllciB3aGVyZSB0aGUgd2Vya3pldWcg ZGVidWdnZXIgb3BlcmF0ZXMuCgpJZiBvbmUgYWRkcyBhIHdheSB0byBkaXNhYmxlIHRoZSBpbnRl cm5hbCBkZWJ1ZyB2aWV3IGFuZCBob29rIGluIFdTR0kgbWlkZGxld2FyZXMsIGFkZGluZyB3ZXJr emV1Zy5kZWJ1ZyBzaG91bGQgYmUgYSBzaW1wbGUgdGFzay4KClJlZ2FyZHMsCkFybWluTAAAUwAA AAZwYXJzZXJTAAAABGh0bWw= Dannadako@gmail.com2007-12-10T07:53:42Znono0Your debugger is very nice. It even looks nicier that Paste's one. Do you have plans on releasing it as a separate package so every WSGI applications developers could use it? It would be great to have such a package. For example, we currently use Paste's evalexception debugger in our Zope3 development, but werkzeug's one looks so great, I'm going to try it with Zope3... :)Your debugger is very nice. It even looks nicier that Paste's one. Do you have plans on releasing it as a separate package so every WSGI applications developers could use it? It would be great to have such a package. For example, we currently use Paste's evalexception debugger in our Zope3 development, but werkzeug's one looks so great, I'm going to try it with Zope3... :)SQAAAAJTAAAABGJvZHlSUwAAAXdZb3VyIGRlYnVnZ2VyIGlzIHZlcnkgbmljZS4gSXQgZXZlbiBs b29rcyBuaWNpZXIgdGhhdCBQYXN0ZSdzIG9uZS4gRG8geW91IGhhdmUgcGxhbnMgb24gcmVsZWFz aW5nIGl0IGFzIGEgc2VwYXJhdGUgcGFja2FnZSBzbyBldmVyeSBXU0dJIGFwcGxpY2F0aW9ucyBk ZXZlbG9wZXJzIGNvdWxkIHVzZSBpdD8gSXQgd291bGQgYmUgZ3JlYXQgdG8gaGF2ZSBzdWNoIGEg cGFja2FnZS4gRm9yIGV4YW1wbGUsIHdlIGN1cnJlbnRseSB1c2UgUGFzdGUncyBldmFsZXhjZXB0 aW9uIGRlYnVnZ2VyIGluIG91ciBab3BlMyBkZXZlbG9wbWVudCwgYnV0IHdlcmt6ZXVnJ3Mgb25l IGxvb2tzIHNvIGdyZWF0LCBJJ20gZ29pbmcgdG8gdHJ5IGl0IHdpdGggWm9wZTMuLi4gOilMAABT AAAABnBhcnNlclMAAAAEaHRtbA== Armin Ronacherarmin.ronacher@active-4.comhttp://lucumr.pocoo.org/2007-12-10T08:11:22Znono0I already did that. That package is called werkzeug ;-) Seriously. Werkzeug plays very well with other packages and it's a very small package, about 3000 lines in total. So no real need to further unbundle the debugger. Regards, ArminI already did that. That package is called werkzeug ;-) Seriously. Werkzeug plays very well with other packages and it's a very small package, about 3000 lines in total. So no real need to further unbundle the debugger. Regards, ArminSQAAAAJTAAAABGJvZHlSUwAAAOtJIGFscmVhZHkgZGlkIHRoYXQuIFRoYXQgcGFja2FnZSBpcyBj YWxsZWQgd2Vya3pldWcgOy0pIFNlcmlvdXNseS4gV2Vya3pldWcgcGxheXMgdmVyeSB3ZWxsIHdp dGggb3RoZXIgcGFja2FnZXMgYW5kIGl0J3MgYSB2ZXJ5IHNtYWxsIHBhY2thZ2UsIGFib3V0IDMw MDAgbGluZXMgaW4gdG90YWwuIFNvIG5vIHJlYWwgbmVlZCB0byBmdXJ0aGVyIHVuYnVuZGxlIHRo ZSBkZWJ1Z2dlci4KClJlZ2FyZHMsCkFybWluTAAAUwAAAAZwYXJzZXJTAAAABGh0bWw= Ali Afsharaafshar@gmail.comhttp://pida.co.uk/2007-12-10T13:57:23Znono0Excellent work! I have been using Werkzeug for a good while now, and I can strongly recommend it to any web developer.Excellent work! I have been using Werkzeug for a good while now, and I can strongly recommend it to any web developer.SQAAAAJTAAAABGJvZHlSUwAAAHZFeGNlbGxlbnQgd29yayEgSSBoYXZlIGJlZW4gdXNpbmcgV2Vy a3pldWcgZm9yIGEgZ29vZCB3aGlsZSBub3csIGFuZCBJIGNhbiBzdHJvbmdseSByZWNvbW1lbmQg aXQgdG8gYW55IHdlYiBkZXZlbG9wZXIuTAAAUwAAAAZwYXJzZXJTAAAABGh0bWw= Ian Bickingianb@colorstudy.comhttp://blog.ianbicking.org2007-12-10T18:39:43Znono0Werkzeug always leaves me a little... baffled. The feature list is so closely matched to Paste and its related libraries. For instance: request/response: paste.wsgiwrappers, and now webob file uploads: well, the cgi module automatically does that static files: paste.fileapp and paste.urlparser.StaticURLParser wsgiref wrapper: paste.httpserver and paster serve unicode: paste.wsgiwrappers/webob mini template engine: tempita context locals: paste.registry test utilities: paste.fixture.TestApp and now webtest interactive debugger: paste.evalexception and now weberror I don't particularly mind this duplication, but I'm confused by it. Why reimplement everything? (And you aren't even the only one, Luke Arno's libraries have the same pattern of reimplementation.)Werkzeug always leaves me a little... baffled. The feature list is so closely matched to Paste and its related libraries. For instance: request/response: paste.wsgiwrappers, and now webob file uploads: well, the cgi module automatically does that static files: paste.fileapp and paste.urlparser.StaticURLParser wsgiref wrapper: paste.httpserver and paster serve unicode: paste.wsgiwrappers/webob mini template engine: tempita context locals: paste.registry test utilities: paste.fixture.TestApp and now webtest interactive debugger: paste.evalexception and now weberror I don't particularly mind this duplication, but I'm confused by it. Why reimplement everything? (And you aren't even the only one, Luke Arno's libraries have the same pattern of reimplementation.)SQAAAAJTAAAABGJvZHlSUwAAAwVXZXJremV1ZyBhbHdheXMgbGVhdmVzIG1lIGEgbGl0dGxlLi4u IGJhZmZsZWQuICBUaGUgZmVhdHVyZSBsaXN0IGlzIHNvIGNsb3NlbHkgbWF0Y2hlZCB0byBQYXN0 ZSBhbmQgaXRzIHJlbGF0ZWQgbGlicmFyaWVzLgoKRm9yIGluc3RhbmNlOiAKCnJlcXVlc3QvcmVz cG9uc2U6IHBhc3RlLndzZ2l3cmFwcGVycywgYW5kIG5vdyB3ZWJvYgpmaWxlIHVwbG9hZHM6IHdl bGwsIHRoZSBjZ2kgbW9kdWxlIGF1dG9tYXRpY2FsbHkgZG9lcyB0aGF0CnN0YXRpYyBmaWxlczog cGFzdGUuZmlsZWFwcCBhbmQgcGFzdGUudXJscGFyc2VyLlN0YXRpY1VSTFBhcnNlcgp3c2dpcmVm IHdyYXBwZXI6IHBhc3RlLmh0dHBzZXJ2ZXIgYW5kIHBhc3RlciBzZXJ2ZQp1bmljb2RlOiBwYXN0 ZS53c2dpd3JhcHBlcnMvd2Vib2IKbWluaSB0ZW1wbGF0ZSBlbmdpbmU6IHRlbXBpdGEKY29udGV4 dCBsb2NhbHM6IHBhc3RlLnJlZ2lzdHJ5CnRlc3QgdXRpbGl0aWVzOiBwYXN0ZS5maXh0dXJlLlRl c3RBcHAgYW5kIG5vdyB3ZWJ0ZXN0CmludGVyYWN0aXZlIGRlYnVnZ2VyOiBwYXN0ZS5ldmFsZXhj ZXB0aW9uIGFuZCBub3cgd2ViZXJyb3IKCkkgZG9uJ3QgcGFydGljdWxhcmx5IG1pbmQgdGhpcyBk dXBsaWNhdGlvbiwgYnV0IEknbSBjb25mdXNlZCBieSBpdC4gIFdoeSByZWltcGxlbWVudCBldmVy eXRoaW5nPyAgKEFuZCB5b3UgYXJlbid0IGV2ZW4gdGhlIG9ubHkgb25lLCBMdWtlIEFybm8ncyBs aWJyYXJpZXMgaGF2ZSB0aGUgc2FtZSBwYXR0ZXJuIG9mIHJlaW1wbGVtZW50YXRpb24uKUwAAFMA AAAGcGFyc2VyUwAAAARodG1s Armin Ronacherarmin.ronacher@active-4.comhttp://lucumr.pocoo.org/2007-12-10T19:10:24Znono0Ian: Well. Unfortunately some project evolved next to each other. Colubrid started long ago and some parts of it are either bad implemented and/or silly. However it was still one of the smallest libraries so I thought about uncoupling the request and response objects, the debugger and some other functions there. I also wanted a slightly improved version of string.Template so that was that template engine thing. However I missed for some time that you started a very similar thing namely webob and tempita. I guess if those projects would have existed for a little longer some parts of werkzeug would probably not exist as such. One of the reasons why I never really felt that happy with paste was that it brings a lot of stuff I personally don't want to use and lacks things I need every day. There are exceptions for every status code, how many of those do you actually use? There are request objects but the file handling feels a lot like the cgi module thanks to the FieldStorage. Long time ago I had big problems with unicode because paste was lacking unicode support everywhere. Paste comes with interesting stuff but most of them I don't use (like paste deploy, SCGI, paste config, transactions) which make 20.000 lines of code and lack things I would actually use (like URL routing, the Werkzeug debugger [yes, there is evalexception, however my sense for aesthetics and usability prefers the Werkzeug one, sorry for that], a simple way to generate custom management scripts without installing PasteScript). At the end of the day Werkzeug is a very small library bundling everything you need to bootstrap your own WSGI application in no time and I'm very happy with the feature/lines of code ratio. And even if I was the only person using Werkzeug the work of the last half year was worth the effort. And unlike Colubrid it's predecessor you can mix it with any other library out there which makes it a good addition to existing libraries. Hope I could defend my POV :-) Regards, ArminIan: Well. Unfortunately some project evolved next to each other. Colubrid started long ago and some parts of it are either bad implemented and/or silly. However it was still one of the smallest libraries so I thought about uncoupling the request and response objects, the debugger and some other functions there. I also wanted a slightly improved version of string.Template so that was that template engine thing. However I missed for some time that you started a very similar thing namely webob and tempita. I guess if those projects would have existed for a little longer some parts of werkzeug would probably not exist as such. One of the reasons why I never really felt that happy with paste was that it brings a lot of stuff I personally don't want to use and lacks things I need every day. There are exceptions for every status code, how many of those do you actually use? There are request objects but the file handling feels a lot like the cgi module thanks to the FieldStorage. Long time ago I had big problems with unicode because paste was lacking unicode support everywhere. Paste comes with interesting stuff but most of them I don't use (like paste deploy, SCGI, paste config, transactions) which make 20.000 lines of code and lack things I would actually use (like URL routing, the Werkzeug debugger [yes, there is evalexception, however my sense for aesthetics and usability prefers the Werkzeug one, sorry for that], a simple way to generate custom management scripts without installing PasteScript). At the end of the day Werkzeug is a very small library bundling everything you need to bootstrap your own WSGI application in no time and I'm very happy with the feature/lines of code ratio. And even if I was the only person using Werkzeug the work of the last half year was worth the effort. And unlike Colubrid it's predecessor you can mix it with any other library out there which makes it a good addition to existing libraries. Hope I could defend my POV :-) Regards, ArminSQAAAAJTAAAABGJvZHlSUwAAB9FJYW46IFdlbGwuIFVuZm9ydHVuYXRlbHkgc29tZSBwcm9qZWN0 IGV2b2x2ZWQgbmV4dCB0byBlYWNoIG90aGVyLiBDb2x1YnJpZCBzdGFydGVkIGxvbmcgYWdvIGFu ZCBzb21lIHBhcnRzIG9mIGl0IGFyZSBlaXRoZXIgYmFkIGltcGxlbWVudGVkIGFuZC9vciBzaWxs eS4gSG93ZXZlciBpdCB3YXMgc3RpbGwgb25lIG9mIHRoZSBzbWFsbGVzdCBsaWJyYXJpZXMgc28g SSB0aG91Z2h0IGFib3V0IHVuY291cGxpbmcgdGhlIHJlcXVlc3QgYW5kIHJlc3BvbnNlIG9iamVj dHMsIHRoZSBkZWJ1Z2dlciBhbmQgc29tZSBvdGhlciBmdW5jdGlvbnMgdGhlcmUuIEkgYWxzbyB3 YW50ZWQgYSBzbGlnaHRseSBpbXByb3ZlZCB2ZXJzaW9uIG9mIHN0cmluZy5UZW1wbGF0ZSBzbyB0 aGF0IHdhcyB0aGF0IHRlbXBsYXRlIGVuZ2luZSB0aGluZy4KCkhvd2V2ZXIgSSBtaXNzZWQgZm9y IHNvbWUgdGltZSB0aGF0IHlvdSBzdGFydGVkIGEgdmVyeSBzaW1pbGFyIHRoaW5nIG5hbWVseSB3 ZWJvYiBhbmQgdGVtcGl0YS4gSSBndWVzcyBpZiB0aG9zZSBwcm9qZWN0cyB3b3VsZCBoYXZlIGV4 aXN0ZWQgZm9yIGEgbGl0dGxlIGxvbmdlciBzb21lIHBhcnRzIG9mIHdlcmt6ZXVnIHdvdWxkIHBy b2JhYmx5IG5vdCBleGlzdCBhcyBzdWNoLgoKT25lIG9mIHRoZSByZWFzb25zIHdoeSBJIG5ldmVy IHJlYWxseSBmZWx0IHRoYXQgaGFwcHkgd2l0aCBwYXN0ZSB3YXMgdGhhdCBpdCBicmluZ3MgYSBs b3Qgb2Ygc3R1ZmYgSSBwZXJzb25hbGx5IGRvbid0IHdhbnQgdG8gdXNlIGFuZCBsYWNrcyB0aGlu Z3MgSSBuZWVkIGV2ZXJ5IGRheS4gVGhlcmUgYXJlIGV4Y2VwdGlvbnMgZm9yIGV2ZXJ5IHN0YXR1 cyBjb2RlLCBob3cgbWFueSBvZiB0aG9zZSBkbyB5b3UgYWN0dWFsbHkgdXNlPyBUaGVyZSBhcmUg cmVxdWVzdCBvYmplY3RzIGJ1dCB0aGUgZmlsZSBoYW5kbGluZyBmZWVscyBhIGxvdCBsaWtlIHRo ZSBjZ2kgbW9kdWxlIHRoYW5rcyB0byB0aGUgRmllbGRTdG9yYWdlLiBMb25nIHRpbWUgYWdvIEkg aGFkIGJpZyBwcm9ibGVtcyB3aXRoIHVuaWNvZGUgYmVjYXVzZSBwYXN0ZSB3YXMgbGFja2luZyB1 bmljb2RlIHN1cHBvcnQgZXZlcnl3aGVyZS4gUGFzdGUgY29tZXMgd2l0aCBpbnRlcmVzdGluZyBz dHVmZiBidXQgbW9zdCBvZiB0aGVtIEkgZG9uJ3QgdXNlIChsaWtlIHBhc3RlIGRlcGxveSwgU0NH SSwgcGFzdGUgY29uZmlnLCB0cmFuc2FjdGlvbnMpIHdoaWNoIG1ha2UgMjAuMDAwIGxpbmVzIG9m IGNvZGUgYW5kIGxhY2sgdGhpbmdzIEkgd291bGQgYWN0dWFsbHkgdXNlIChsaWtlIFVSTCByb3V0 aW5nLCB0aGUgV2Vya3pldWcgZGVidWdnZXIgW3llcywgdGhlcmUgaXMgZXZhbGV4Y2VwdGlvbiwg aG93ZXZlciBteSBzZW5zZSBmb3IgYWVzdGhldGljcyBhbmQgdXNhYmlsaXR5IHByZWZlcnMgdGhl IFdlcmt6ZXVnIG9uZSwgc29ycnkgZm9yIHRoYXRdLCBhIHNpbXBsZSB3YXkgdG8gZ2VuZXJhdGUg Y3VzdG9tIG1hbmFnZW1lbnQgc2NyaXB0cyB3aXRob3V0IGluc3RhbGxpbmcgUGFzdGVTY3JpcHQp LgoKQXQgdGhlIGVuZCBvZiB0aGUgZGF5IFdlcmt6ZXVnIGlzIGEgdmVyeSBzbWFsbCBsaWJyYXJ5 IGJ1bmRsaW5nIGV2ZXJ5dGhpbmcgeW91IG5lZWQgdG8gYm9vdHN0cmFwIHlvdXIgb3duIFdTR0kg YXBwbGljYXRpb24gaW4gbm8gdGltZSBhbmQgSSdtIHZlcnkgaGFwcHkgd2l0aCB0aGUgZmVhdHVy ZS9saW5lcyBvZiBjb2RlIHJhdGlvLiBBbmQgZXZlbiBpZiBJIHdhcyB0aGUgb25seSBwZXJzb24g dXNpbmcgV2Vya3pldWcgdGhlIHdvcmsgb2YgdGhlIGxhc3QgaGFsZiB5ZWFyIHdhcyB3b3J0aCB0 aGUgZWZmb3J0LiBBbmQgdW5saWtlIENvbHVicmlkIGl0J3MgcHJlZGVjZXNzb3IgeW91IGNhbiBt aXggaXQgd2l0aCBhbnkgb3RoZXIgbGlicmFyeSBvdXQgdGhlcmUgd2hpY2ggbWFrZXMgaXQgYSBn b29kIGFkZGl0aW9uIHRvIGV4aXN0aW5nIGxpYnJhcmllcy4KCkhvcGUgSSBjb3VsZCBkZWZlbmQg bXkgUE9WIDotKQoKUmVnYXJkcywKQXJtaW5MAABTAAAABnBhcnNlclMAAAAEaHRtbA== Graham DumpletonGraham.Dumpleton@gmail.comhttp://blog.dscpl.com.au2007-12-11T02:19:13Znono0FWIW, I personally feel that choice is good. I do not buy in to this argument that in Python there should always be only one way of doing things. If one were to pursue that ideal to the end then you will just end up with a monopolistic mono culture that would more than likely stagnate. When different parties do implement similar things they are never really the same anyway, as each will incorporate different ideas as to how to go about solving the problem. This is important and any decent programmer would look at what other people are doing in the Python community and learn from others successes, as well as their failures. It is only through this cross fertilisation of ideas and learning from others that as a whole the quality and utility of code will move forward. The other thing with competing solutions is that they usually have different trade offs, and as such, which one is better for a particular scenario will depend on the sort of application or environment it is used in. No one solution will always be the best at everything. As such I feel that trying to suppress people from doing their own thing and trying to make them use a specific package is in the end run counter productive. If a solution is not good it will die its own death. If it is a good solution and for good reason, it could well become so successful as to replace all other existing solutions, even if only for a time. So, empires will come and go, this will never change and we shouldn't try and stop it.FWIW, I personally feel that choice is good. I do not buy in to this argument that in Python there should always be only one way of doing things. If one were to pursue that ideal to the end then you will just end up with a monopolistic mono culture that would more than likely stagnate. When different parties do implement similar things they are never really the same anyway, as each will incorporate different ideas as to how to go about solving the problem. This is important and any decent programmer would look at what other people are doing in the Python community and learn from others successes, as well as their failures. It is only through this cross fertilisation of ideas and learning from others that as a whole the quality and utility of code will move forward. The other thing with competing solutions is that they usually have different trade offs, and as such, which one is better for a particular scenario will depend on the sort of application or environment it is used in. No one solution will always be the best at everything. As such I feel that trying to suppress people from doing their own thing and trying to make them use a specific package is in the end run counter productive. If a solution is not good it will die its own death. If it is a good solution and for good reason, it could well become so successful as to replace all other existing solutions, even if only for a time. So, empires will come and go, this will never change and we shouldn't try and stop it.SQAAAAJTAAAABGJvZHlSUwAABdtGV0lXLCBJIHBlcnNvbmFsbHkgZmVlbCB0aGF0IGNob2ljZSBp cyBnb29kLiBJIGRvIG5vdCBidXkgaW4gdG8gdGhpcyBhcmd1bWVudCB0aGF0IGluIFB5dGhvbiB0 aGVyZSBzaG91bGQgYWx3YXlzIGJlIG9ubHkgb25lIHdheSBvZiBkb2luZyB0aGluZ3MuIElmIG9u ZSB3ZXJlIHRvIHB1cnN1ZSB0aGF0IGlkZWFsIHRvIHRoZSBlbmQgdGhlbiB5b3Ugd2lsbCBqdXN0 IGVuZCB1cCB3aXRoIGEgbW9ub3BvbGlzdGljIG1vbm8gY3VsdHVyZSB0aGF0IHdvdWxkIG1vcmUg dGhhbiBsaWtlbHkgc3RhZ25hdGUuCgpXaGVuIGRpZmZlcmVudCBwYXJ0aWVzIGRvIGltcGxlbWVu dCBzaW1pbGFyIHRoaW5ncyB0aGV5IGFyZSBuZXZlciByZWFsbHkgdGhlIHNhbWUgYW55d2F5LCBh cyBlYWNoIHdpbGwgaW5jb3Jwb3JhdGUgZGlmZmVyZW50IGlkZWFzIGFzIHRvIGhvdyB0byBnbyBh Ym91dCBzb2x2aW5nIHRoZSBwcm9ibGVtLiBUaGlzIGlzIGltcG9ydGFudCBhbmQgYW55IGRlY2Vu dCBwcm9ncmFtbWVyIHdvdWxkIGxvb2sgYXQgd2hhdCBvdGhlciBwZW9wbGUgYXJlIGRvaW5nIGlu IHRoZSBQeXRob24gY29tbXVuaXR5IGFuZCBsZWFybiBmcm9tIG90aGVycyBzdWNjZXNzZXMsIGFz IHdlbGwgYXMgdGhlaXIgZmFpbHVyZXMuIEl0IGlzIG9ubHkgdGhyb3VnaCB0aGlzIGNyb3NzIGZl cnRpbGlzYXRpb24gb2YgaWRlYXMgYW5kIGxlYXJuaW5nIGZyb20gb3RoZXJzIHRoYXQgYXMgYSB3 aG9sZSB0aGUgcXVhbGl0eSBhbmQgdXRpbGl0eSBvZiBjb2RlIHdpbGwgbW92ZSBmb3J3YXJkLgoK VGhlIG90aGVyIHRoaW5nIHdpdGggY29tcGV0aW5nIHNvbHV0aW9ucyBpcyB0aGF0IHRoZXkgdXN1 YWxseSBoYXZlIGRpZmZlcmVudCB0cmFkZSBvZmZzLCBhbmQgYXMgc3VjaCwgd2hpY2ggb25lIGlz IGJldHRlciBmb3IgYSBwYXJ0aWN1bGFyIHNjZW5hcmlvIHdpbGwgZGVwZW5kIG9uIHRoZSBzb3J0 IG9mIGFwcGxpY2F0aW9uIG9yIGVudmlyb25tZW50IGl0IGlzIHVzZWQgaW4uIE5vIG9uZSBzb2x1 dGlvbiB3aWxsIGFsd2F5cyBiZSB0aGUgYmVzdCBhdCBldmVyeXRoaW5nLgoKQXMgc3VjaCBJIGZl ZWwgdGhhdCB0cnlpbmcgdG8gc3VwcHJlc3MgcGVvcGxlIGZyb20gZG9pbmcgdGhlaXIgb3duIHRo aW5nIGFuZCB0cnlpbmcgdG8gbWFrZSB0aGVtIHVzZSBhIHNwZWNpZmljIHBhY2thZ2UgaXMgaW4g dGhlIGVuZCBydW4gY291bnRlciBwcm9kdWN0aXZlLiBJZiBhIHNvbHV0aW9uIGlzIG5vdCBnb29k IGl0IHdpbGwgZGllIGl0cyBvd24gZGVhdGguIElmIGl0IGlzIGEgZ29vZCBzb2x1dGlvbiBhbmQg Zm9yIGdvb2QgcmVhc29uLCBpdCBjb3VsZCB3ZWxsIGJlY29tZSBzbyBzdWNjZXNzZnVsIGFzIHRv IHJlcGxhY2UgYWxsIG90aGVyIGV4aXN0aW5nIHNvbHV0aW9ucywgZXZlbiBpZiBvbmx5IGZvciBh IHRpbWUuCgpTbywgZW1waXJlcyB3aWxsIGNvbWUgYW5kIGdvLCB0aGlzIHdpbGwgbmV2ZXIgY2hh bmdlIGFuZCB3ZSBzaG91bGRuJ3QgdHJ5IGFuZCBzdG9wIGl0LkwAAFMAAAAGcGFyc2VyUwAAAARo dG1s Adam Hindsadam@b-ooks.co.ukhttp://www.b-ooks.co.uk2007-12-19T10:00:37Znono0Thank you for releasing this, have looking for something lightweight like this for a while.Thank you for releasing this, have looking for something lightweight like this for a while.SQAAAAJTAAAABGJvZHlSUwAAAFtUaGFuayB5b3UgZm9yIHJlbGVhc2luZyB0aGlzLCBoYXZlIGxv b2tpbmcgZm9yIHNvbWV0aGluZyBsaWdodHdlaWdodCBsaWtlIHRoaXMgZm9yIGEgd2hpbGUuTAAA UwAAAAZwYXJzZXJTAAAABGh0bWw= In Nomine - The Lotus Land » Werkzeug 0.1 released - WSGI toolboxhttp://www.in-nomine.org/2007/12/21/werkzeug-01-released-wsgi-toolbox/2007-12-21T11:48:33Znoyes0[...] Ronacher has released Werkzeug 0.1 a little while ago. As the website for Werkzeug says: “Werkzeug is a collection of various utilities for WSGI [...][...] Ronacher has released Werkzeug 0.1 a little while ago. As the website for Werkzeug says: &#8220;Werkzeug is a collection of various utilities for WSGI [...]SQAAAAJTAAAABGJvZHlSUwAAAJ5bLi4uXSBSb25hY2hlciBoYXMgcmVsZWFzZWQgV2Vya3pldWcg MC4xIGEgbGl0dGxlIHdoaWxlIGFnby4gQXMgdGhlIHdlYnNpdGUgZm9yIFdlcmt6ZXVnIHNheXM6 IOKAnFdlcmt6ZXVnIGlzIGEgY29sbGVjdGlvbiBvZiB2YXJpb3VzIHV0aWxpdGllcyBmb3IgV1NH SSBbLi4uXUwAAFMAAAAGcGFyc2VyUwAAAARodG1s propanbutanpropanbutan@gmx.net2007-12-23T16:04:29Znono0Werkzeug is a gem, to the point, elegant, lean code. Luke Arno's libraries have a similar quality, the conventions are natural, the code is easy to follow, build upon and adapt to. Unlike Paste, where I first got turned off by StackedObjectProxy, after realizing it was just a glorious wrapper for threading.local. And while this generic header parser-composer is, well generic, I can deal with raw header strings just fine, hence I use Werkzeug. Thanks for sharing it. PS. Is pocoo dead or just hibernating?Werkzeug is a gem, to the point, elegant, lean code. Luke Arno's libraries have a similar quality, the conventions are natural, the code is easy to follow, build upon and adapt to. Unlike Paste, where I first got turned off by StackedObjectProxy, after realizing it was just a glorious wrapper for threading.local. And while this generic header parser-composer is, well generic, I can deal with raw header strings just fine, hence I use Werkzeug. Thanks for sharing it. PS. Is pocoo dead or just hibernating?SQAAAAJTAAAABGJvZHlSUwAAAfxXZXJremV1ZyBpcyBhIGdlbSwgdG8gdGhlIHBvaW50LCBlbGVn YW50LCBsZWFuIGNvZGUuIEx1a2UgQXJubydzIGxpYnJhcmllcyBoYXZlIGEgc2ltaWxhciBxdWFs aXR5LCB0aGUgY29udmVudGlvbnMgYXJlIG5hdHVyYWwsIHRoZSBjb2RlIGlzIGVhc3kgdG8gZm9s bG93LCBidWlsZCB1cG9uIGFuZCBhZGFwdCB0by4gVW5saWtlIFBhc3RlLCB3aGVyZSBJIGZpcnN0 IGdvdCB0dXJuZWQgb2ZmIGJ5IFN0YWNrZWRPYmplY3RQcm94eSwgYWZ0ZXIgcmVhbGl6aW5nIGl0 IHdhcyBqdXN0IGEgZ2xvcmlvdXMgd3JhcHBlciBmb3IgdGhyZWFkaW5nLmxvY2FsLiBBbmQgd2hp bGUgdGhpcyBnZW5lcmljIGhlYWRlciBwYXJzZXItY29tcG9zZXIgaXMsIHdlbGwgZ2VuZXJpYywg SSBjYW4gZGVhbCB3aXRoIHJhdyBoZWFkZXIgc3RyaW5ncyBqdXN0IGZpbmUsIGhlbmNlIEkgdXNl IFdlcmt6ZXVnLiBUaGFua3MgZm9yIHNoYXJpbmcgaXQuClBTLiBJcyBwb2NvbyBkZWFkIG9yIGp1 c3QgaGliZXJuYXRpbmc/TAAAUwAAAAZwYXJzZXJTAAAABGh0bWw= Emptymtrier@gmail.comhttp://blog.michaeltrier.com2007-12-24T17:59:01Znono0Wow, very impressive. I plan to dig through this code just for the learning value if nothing else. I too would like to see this type of web-based console debugger available in Django. Thanks again for your contribution.Wow, very impressive. I plan to dig through this code just for the learning value if nothing else. I too would like to see this type of web-based console debugger available in Django. Thanks again for your contribution.SQAAAAJTAAAABGJvZHlSUwAAAN5Xb3csIHZlcnkgaW1wcmVzc2l2ZS4gIEkgcGxhbiB0byBkaWcg dGhyb3VnaCB0aGlzIGNvZGUganVzdCBmb3IgdGhlIGxlYXJuaW5nIHZhbHVlIGlmIG5vdGhpbmcg ZWxzZS4gIEkgdG9vIHdvdWxkIGxpa2UgdG8gc2VlIHRoaXMgdHlwZSBvZiB3ZWItYmFzZWQgY29u c29sZSBkZWJ1Z2dlciBhdmFpbGFibGUgaW4gRGphbmdvLiAgVGhhbmtzIGFnYWluIGZvciB5b3Vy IGNvbnRyaWJ1dGlvbi5MAABTAAAABnBhcnNlclMAAAAEaHRtbA== German Django Communityhttp://lucumr.pocoo.org/cogitations/2007/12/08/german-django-community/2007-12-08T19:51:47Z2007-12-08T19:51:47ZArmin Ronachergerman-django-communityyesyes2Since yesterday a German community page for django exists: <a href="http://django-de.org/">django-de.org</a>. Good to see that people are working on that :-)Since yesterday a German community page for django exists: <a href="http://django-de.org/">django-de.org</a>. Good to see that people are working on that :-)SQAAAANTAAAABGJvZHlSUwAAADtTaW5jZSB5ZXN0ZXJkYXkgYSBHZXJtYW4gY29tbXVuaXR5IHBh Z2UgZm9yIGRqYW5nbyBleGlzdHM6IEwAAUVTAAAAAWFMAABNAAFTAAAABGhyZWZTAAAAFWh0dHA6 Ly9kamFuZ28tZGUub3JnL1MAAAANZGphbmdvLWRlLm9yZ1MAAAAxLiBHb29kIHRvIHNlZSB0aGF0 IHBlb3BsZSBhcmUgd29ya2luZyBvbiB0aGF0IDotKVMAAAAGcGFyc2VyUwAAAARodG1sUwAAAAVp bnRyb1JTAAAAAEwAAA== bgfullercourier@braydon.comhttp://braydon.com2007-12-08T22:01:24Znono0" Das Web Framework für Perfektionisten mit Deadlines." is kinda funny." Das Web Framework für Perfektionisten mit Deadlines." is kinda funny.SQAAAAJTAAAABGJvZHlSUwAAAEgiIERhcyBXZWIgRnJhbWV3b3JrIGbDvHIgUGVyZmVrdGlvbmlz dGVuIG1pdCBEZWFkbGluZXMuIiBpcyBraW5kYSBmdW5ueS5MAABTAAAABnBhcnNlclMAAAAEaHRt bA== Armin Ronacherarmin.ronacher@active-4.comhttp://lucumr.pocoo.org/2007-12-08T22:36:25Znono0A perfectly German version of that would be „Das Web-Rahmenwerk für Perfektionisten mit Stichtagen“, but that sounds awkward :-) Regards, ArminA perfectly German version of that would be „Das Web-Rahmenwerk für Perfektionisten mit Stichtagen“, but that sounds awkward :-) Regards, ArminSQAAAAJTAAAABGJvZHlSUwAAAJVBIHBlcmZlY3RseSBHZXJtYW4gdmVyc2lvbiBvZiB0aGF0IHdv dWxkIGJlIOKAnkRhcyBXZWItUmFobWVud2VyayBmw7xyIFBlcmZla3Rpb25pc3RlbiBtaXQgU3Rp Y2h0YWdlbuKAnCwgYnV0IHRoYXQgc291bmRzIGF3a3dhcmQgOi0pCgpSZWdhcmRzLApBcm1pbkwA AFMAAAAGcGFyc2VyUwAAAARodG1s jezdezjannis@leidel.infohttp://jannisleidel.com2007-12-08T23:28:53Znono0Hehe, stimmt klingt komisch, auf lange Sicht sollten wir uns da etwas passenderes ausdenken, also nicht einfach übersetzen :D Danke für das Post!Hehe, stimmt klingt komisch, auf lange Sicht sollten wir uns da etwas passenderes ausdenken, also nicht einfach übersetzen :D Danke für das Post!SQAAAAJTAAAABGJvZHlSUwAAAJRIZWhlLCBzdGltbXQga2xpbmd0IGtvbWlzY2gsIGF1ZiBsYW5n ZSBTaWNodCBzb2xsdGVuIHdpciB1bnMgZGEgZXR3YXMgcGFzc2VuZGVyZXMgYXVzZGVua2VuLCBh bHNvIG5pY2h0IGVpbmZhY2ggw7xiZXJzZXR6ZW4gOkQKCkRhbmtlIGbDvHIgZGFzIFBvc3QhTAAA UwAAAAZwYXJzZXJTAAAABGh0bWw= Listen to more…http://lucumr.pocoo.org/cogitations/2007/11/28/listen-to-more/2007-11-28T16:30:52Z2007-11-28T16:30:52ZArmin Ronacherlisten-to-moreyesyes2...<a href="http://ininagap.com/">Inina Gap</a>. Which you probably haven't heard by now. It's not rock, metal or any other stuff I normally listen to, in fact it's completely different, more like electronic fusion. And disclaimer: I a) saw them live, and b) a friend of mine is playing bass in that band :-) Nonetheless: Check it out....<a href="http://ininagap.com/">Inina Gap</a>. Which you probably haven't heard by now. It's not rock, metal or any other stuff I normally listen to, in fact it's completely different, more like electronic fusion. And disclaimer: I a) saw them live, and b) a friend of mine is playing bass in that band :-) Nonetheless: Check it out.SQAAAANTAAAABGJvZHlSUwAAAAMuLi5MAAFFUwAAAAFhTAAATQABUwAAAARocmVmUwAAABRodHRw Oi8vaW5pbmFnYXAuY29tL1MAAAAJSW5pbmEgR2FwUwAAASEuIFdoaWNoIHlvdSBwcm9iYWJseSBo YXZlbid0IGhlYXJkIGJ5IG5vdy4gSXQncyBub3Qgcm9jaywgbWV0YWwgb3IgYW55IG90aGVyIHN0 dWZmIEkgbm9ybWFsbHkgbGlzdGVuIHRvLCBpbiBmYWN0IGl0J3MgY29tcGxldGVseSBkaWZmZXJl bnQsIG1vcmUgbGlrZSBlbGVjdHJvbmljIGZ1c2lvbi4gQW5kIGRpc2NsYWltZXI6IEkgYSkgc2F3 IHRoZW0gbGl2ZSwgYW5kIGIpIGEgZnJpZW5kIG9mIG1pbmUgaXMgcGxheWluZyBiYXNzIGluIHRo YXQgYmFuZCA6LSkKCk5vbmV0aGVsZXNzOiBDaGVjayBpdCBvdXQuUwAAAAZwYXJzZXJTAAAABGh0 bWxTAAAABWludHJvUlMAAAAATAAA 220…http://lucumr.pocoo.org/cogitations/2007/11/26/220/2007-11-26T18:36:40Z2007-11-26T18:36:40ZArmin Ronacher220yesyes2<big><a href="http://www.amnestyusa.org/document.php?lang=e&id=ENGUSA20070108001">...dead</a></big>. And that's a non lethal weapon? <strong>update:</strong> Georg points out that it's called a "less lethal" weapon.<big><a href="http://www.amnestyusa.org/document.php?lang=e&amp;id=ENGUSA20070108001">...dead</a></big>. And that's a non lethal weapon? <strong>update:</strong> Georg points out that it's called a "less lethal" weapon.SQAAAANTAAAABGJvZHlSUwAAAABMAAJFUwAAAANiaWdMAAFFUwAAAAFhTAAATQABUwAAAARocmVm UwAAAEJodHRwOi8vd3d3LmFtbmVzdHl1c2Eub3JnL2RvY3VtZW50LnBocD9sYW5nPWUmaWQ9RU5H VVNBMjAwNzAxMDgwMDFTAAAABy4uLmRlYWRTAAAAAE0AAFMAAAAAUwAAACMuIEFuZCB0aGF0J3Mg YSBub24gbGV0aGFsIHdlYXBvbj8KCkVTAAAABnN0cm9uZ0wAAE0AAFMAAAAHdXBkYXRlOlMAAAA6 IEdlb3JnIHBvaW50cyBvdXQgdGhhdCBpdCdzIGNhbGxlZCBhICJsZXNzIGxldGhhbCIgd2VhcG9u LlMAAAAGcGFyc2VyUwAAAARodG1sUwAAAAVpbnRyb1JTAAAAAEwAAA== Wiki Models with SQLAlchemyhttp://lucumr.pocoo.org/cogitations/2007/11/22/wiki-models-with-sqlalchemy/2007-11-22T00:34:28Z2007-11-22T00:34:28ZArmin Ronacherwiki-models-with-sqlalchemyyesyes2I was working on an <a href="http://dev.pocoo.org/projects/werkzeug/browser/examples/simplewiki">example application</a> for the upcoming <a href="http://werkzeug.pocoo.org/">Werkzeug</a> release and decided to make a wiki for that purpose. (The main reason is that I found the <a href="http://pypi.python.org/pypi/Creoleparser">Creoleparser</a> on the pypi index and thought that it would integrate into a genshi powered wiki well) Now wikis have an interesting data structure. Basically you have pages and revisions, where a revision is bound to exactly one page. Simple to model and my database definition looks like that: <!-- PYGMENTS_CACHE><div class="highlight"><pre><span class="n">page_table</span> <span class="o">=</span> <span class="n">Table</span><span class="p">(</span><span class="s">&#39;pages&#39;</span><span class="p">,</span> <span class="n">metadata</span><span class="p">,</span> <span class="n">Column</span><span class="p">(</span><span class="s">&#39;page_id&#39;</span><span class="p">,</span> <span class="n">Integer</span><span class="p">,</span> <span class="n">primary_key</span><span class="o">=</span><span class="bp">True</span><span class="p">),</span> <span class="n">Column</span><span class="p">(</span><span class="s">&#39;name&#39;</span><span class="p">,</span> <span class="n">String</span><span class="p">(</span><span class="mf">60</span><span class="p">),</span> <span class="n">unique</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span> <span class="p">)</span> <span class="n">revision_table</span> <span class="o">=</span> <span class="n">Table</span><span class="p">(</span><span class="s">&#39;revisions&#39;</span><span class="p">,</span> <span class="n">metadata</span><span class="p">,</span> <span class="n">Column</span><span class="p">(</span><span class="s">&#39;revision_id&#39;</span><span class="p">,</span> <span class="n">Integer</span><span class="p">,</span> <span class="n">primary_key</span><span class="o">=</span><span class="bp">True</span><span class="p">),</span> <span class="n">Column</span><span class="p">(</span><span class="s">&#39;page_id&#39;</span><span class="p">,</span> <span class="n">Integer</span><span class="p">,</span> <span class="n">ForeignKey</span><span class="p">(</span><span class="s">&#39;pages.page_id&#39;</span><span class="p">)),</span> <span class="n">Column</span><span class="p">(</span><span class="s">&#39;timestamp&#39;</span><span class="p">,</span> <span class="n">DateTime</span><span class="p">),</span> <span class="n">Column</span><span class="p">(</span><span class="s">&#39;text&#39;</span><span class="p">,</span> <span class="n">String</span><span class="p">),</span> <span class="n">Column</span><span class="p">(</span><span class="s">&#39;change_note&#39;</span><span class="p">,</span> <span class="n">String</span><span class="p">(</span><span class="mf">200</span><span class="p">))</span> <span class="p">)</span> </pre></div> <PYGMENTS_CACHE --><!-- PYGMENTS_RAW(python)>page_table = Table('pages', metadata, Column('page_id', Integer, primary_key=True), Column('name', String(60), unique=True) ) revision_table = Table('revisions', metadata, Column('revision_id', Integer, primary_key=True), Column('page_id', Integer, ForeignKey('pages.page_id')), Column('timestamp', DateTime), Column('text', String), Column('change_note', String(200)) )<PYGMENTS_RAW --> Very simple schema and you can easily bind it to two classes: <!-- PYGMENTS_CACHE><div class="highlight"><pre><span class="k">class</span> <span class="nc">Revision</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span> <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">page</span><span class="p">,</span> <span class="n">text</span><span class="p">,</span> <span class="n">change_note</span><span class="o">=</span><span class="s">&#39;&#39;</span><span class="p">,</span> <span class="n">timestamp</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">page</span><span class="p">,</span> <span class="p">(</span><span class="nb">int</span><span class="p">,</span> <span class="nb">long</span><span class="p">)):</span> <span class="bp">self</span><span class="o">.</span><span class="n">page_id</span> <span class="o">=</span> <span class="n">page</span> <span class="k">else</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">page</span> <span class="o">=</span> <span class="n">page</span> <span class="bp">self</span><span class="o">.</span><span class="n">text</span> <span class="o">=</span> <span class="n">text</span> <span class="bp">self</span><span class="o">.</span><span class="n">change_note</span> <span class="o">=</span> <span class="n">change_note</span> <span class="bp">self</span><span class="o">.</span><span class="n">timestamp</span> <span class="o">=</span> <span class="n">timestamp</span> <span class="ow">or</span> <span class="n">datetime</span><span class="o">.</span><span class="n">utcnow</span><span class="p">()</span> <span class="k">def</span> <span class="nf">render</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">request</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span> <span class="sd">&quot;&quot;&quot;Render the page text into a genshi stream.&quot;&quot;&quot;</span> <span class="k">if</span> <span class="n">request</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span> <span class="n">request</span> <span class="o">=</span> <span class="n">get_request</span><span class="p">()</span> <span class="k">if</span> <span class="n">request</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span> <span class="k">raise</span> <span class="ne">RuntimeError</span><span class="p">(</span><span class="s">&#39;rendering requires request context&#39;</span><span class="p">)</span> <span class="k">return</span> <span class="n">parse_creole</span><span class="p">(</span><span class="n">request</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">text</span><span class="p">)</span> <span class="k">class</span> <span class="nc">Page</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span> <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">):</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">name</span> <span class="nd">@property</span> <span class="k">def</span> <span class="nf">title</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s">&#39;_&#39;</span><span class="p">,</span> <span class="s">&#39; &#39;</span><span class="p">)</span> <span class="n">Session</span><span class="o">.</span><span class="n">mapper</span><span class="p">(</span><span class="n">Revision</span><span class="p">,</span> <span class="n">revision_table</span><span class="p">)</span> <span class="n">Session</span><span class="o">.</span><span class="n">mapper</span><span class="p">(</span><span class="n">Page</span><span class="p">,</span> <span class="n">page_table</span><span class="p">,</span> <span class="n">properties</span><span class="o">=</span><span class="nb">dict</span><span class="p">(</span> <span class="n">revisions</span><span class="o">=</span><span class="n">relation</span><span class="p">(</span><span class="n">Revision</span><span class="p">,</span> <span class="n">backref</span><span class="o">=</span><span class="s">&#39;page&#39;</span><span class="p">,</span> <span class="n">order_by</span><span class="o">=</span><span class="p">[</span><span class="n">desc</span><span class="p">(</span><span class="n">Revision</span><span class="o">.</span><span class="n">revision_id</span><span class="p">)])</span> <span class="p">))</span> </pre></div> <PYGMENTS_CACHE --><!-- PYGMENTS_RAW(python)>class Revision(object): def __init__(self, page, text, change_note='', timestamp=None): if isinstance(page, (int, long)): self.page_id = page else: self.page = page self.text = text self.change_note = change_note self.timestamp = timestamp or datetime.utcnow() def render(self, request=None): """Render the page text into a genshi stream.""" if request is None: request = get_request() if request is None: raise RuntimeError('rendering requires request context') return parse_creole(request, self.text) class Page(object): def __init__(self, name): self.name = name @property def title(self): return self.name.replace('_', ' ') Session.mapper(Revision, revision_table) Session.mapper(Page, page_table, properties=dict( revisions=relation(Revision, backref='page', order_by=[desc(Revision.revision_id)]) ))<PYGMENTS_RAW --> Works pretty well but as soon as you start putting your stuff into the template it feels unpythonic :-) You basically have to provide always two objects, the revision and the page. Why not combine that into one model? First I removed my database tables again and combined that into one table but then I found out that you can map joins to classes in SQLAlchemy. That and Python's ability to do multiple inheritance gives me the ability to combine both tables into one class: <!-- PYGMENTS_CACHE><div class="highlight"><pre><span class="k">class</span> <span class="nc">RevisionedPage</span><span class="p">(</span><span class="n">Page</span><span class="p">,</span> <span class="n">Revision</span><span class="p">):</span> <span class="k">pass</span> <span class="n">Session</span><span class="o">.</span><span class="n">mapper</span><span class="p">(</span><span class="n">RevisionedPage</span><span class="p">,</span> <span class="n">join</span><span class="p">(</span><span class="n">page_table</span><span class="p">,</span> <span class="n">revision_table</span><span class="p">),</span> <span class="n">properties</span><span class="o">=</span><span class="nb">dict</span><span class="p">(</span> <span class="n">page_id</span><span class="o">=</span><span class="p">[</span><span class="n">page_table</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">page_id</span><span class="p">,</span> <span class="n">revision_table</span><span class="o">.</span><span class="n">c</span><span class="o">.</span><span class="n">page_id</span><span class="p">],</span> <span class="p">))</span> </pre></div> <PYGMENTS_CACHE --><!-- PYGMENTS_RAW(python)>class RevisionedPage(Page, Revision): pass Session.mapper(RevisionedPage, join(page_table, revision_table), properties=dict( page_id=[page_table.c.page_id, revision_table.c.page_id], ))<PYGMENTS_RAW --> Very nice for the templates and also easy to query. It looks like a normal python class. I haven't tried if that also works for write access, but I doubt it. Because of that I have added an exception to the __init__ method to avoid creating pages and revisions via the RevisionedPage object. The full example can be found <a href="http://dev.pocoo.org/projects/werkzeug/browser/examples/simplewiki/database.py">in the simplewiki sources</a>.I was working on an <a href="http://dev.pocoo.org/projects/werkzeug/browser/examples/simplewiki">example application</a> for the upcoming <a href="http://werkzeug.pocoo.org/">Werkzeug</a> release and decided to make a wiki for that purpose. (The main reason is that I found the <a href="http://pypi.python.org/pypi/Creoleparser">Creoleparser</a> on the pypi index and thought that it would integrate into a genshi powered wiki well) Now wikis have an interesting data structure. Basically you have pages and revisions, where a revision is bound to exactly one page. Simple to model and my database definition looks like that: Very simple schema and you can easily bind it to two classes: Works pretty well but as soon as you start putting your stuff into the template it feels unpythonic :-) You basically have to provide always two objects, the revision and the page. Why not combine that into one model? First I removed my database tables again and combined that into one table but then I found out that you can map joins to classes in SQLAlchemy. That and Python's ability to do multiple inheritance gives me the ability to combine both tables into one class: Very nice for the templates and also easy to query. It looks like a normal python class. I haven't tried if that also works for write access, but I doubt it. Because of that I have added an exception to the __init__ method to avoid creating pages and revisions via the RevisionedPage object. The full example can be found <a href="http://dev.pocoo.org/projects/werkzeug/browser/examples/simplewiki/database.py">in the simplewiki sources</a>.SQAAAANTAAAABGJvZHlSUwAAABRJIHdhcyB3b3JraW5nIG9uIGFuIEwABEVTAAAAAWFMAABNAAFT AAAABGhyZWZTAAAAQmh0dHA6Ly9kZXYucG9jb28ub3JnL3Byb2plY3RzL3dlcmt6ZXVnL2Jyb3dz ZXIvZXhhbXBsZXMvc2ltcGxld2lraVMAAAATZXhhbXBsZSBhcHBsaWNhdGlvblMAAAASIGZvciB0 aGUgdXBjb21pbmcgRVMAAAABYUwAAE0AAVMAAAAEaHJlZlMAAAAaaHR0cDovL3dlcmt6ZXVnLnBv Y29vLm9yZy9TAAAACFdlcmt6ZXVnUwAAAFsgcmVsZWFzZSBhbmQgZGVjaWRlZCB0byBtYWtlIGEg d2lraSBmb3IgdGhhdCBwdXJwb3NlLiAoVGhlIG1haW4gcmVhc29uIGlzIHRoYXQgSSBmb3VuZCB0 aGUgRVMAAAABYUwAAE0AAVMAAAAEaHJlZlMAAAAoaHR0cDovL3B5cGkucHl0aG9uLm9yZy9weXBp L0NyZW9sZXBhcnNlclMAAAAMQ3Jlb2xlcGFyc2VyUwAABHkgb24gdGhlIHB5cGkgaW5kZXggYW5k IHRob3VnaHQgdGhhdCBpdCB3b3VsZCBpbnRlZ3JhdGUgaW50byBhIGdlbnNoaSBwb3dlcmVkIHdp a2kgd2VsbCkKCk5vdyB3aWtpcyBoYXZlIGFuIGludGVyZXN0aW5nIGRhdGEgc3RydWN0dXJlLiBC YXNpY2FsbHkgeW91IGhhdmUgcGFnZXMgYW5kIHJldmlzaW9ucywgd2hlcmUgYSByZXZpc2lvbiBp cyBib3VuZCB0byBleGFjdGx5IG9uZSBwYWdlLiBTaW1wbGUgdG8gbW9kZWwgYW5kIG15IGRhdGFi YXNlIGRlZmluaXRpb24gbG9va3MgbGlrZSB0aGF0OgoKVmVyeSBzaW1wbGUgc2NoZW1hIGFuZCB5 b3UgY2FuIGVhc2lseSBiaW5kIGl0IHRvIHR3byBjbGFzc2VzOgoKV29ya3MgcHJldHR5IHdlbGwg YnV0IGFzIHNvb24gYXMgeW91IHN0YXJ0IHB1dHRpbmcgeW91ciBzdHVmZiBpbnRvIHRoZSB0ZW1w bGF0ZSBpdCBmZWVscyB1bnB5dGhvbmljIDotKSBZb3UgYmFzaWNhbGx5IGhhdmUgdG8gcHJvdmlk ZSBhbHdheXMgdHdvIG9iamVjdHMsIHRoZSByZXZpc2lvbiBhbmQgdGhlIHBhZ2UuIFdoeSBub3Qg Y29tYmluZSB0aGF0IGludG8gb25lIG1vZGVsPyBGaXJzdCBJIHJlbW92ZWQgbXkgZGF0YWJhc2Ug dGFibGVzIGFnYWluIGFuZCBjb21iaW5lZCB0aGF0IGludG8gb25lIHRhYmxlIGJ1dCB0aGVuIEkg Zm91bmQgb3V0IHRoYXQgeW91IGNhbiBtYXAgam9pbnMgdG8gY2xhc3NlcyBpbiBTUUxBbGNoZW15 LiBUaGF0IGFuZCBQeXRob24ncyBhYmlsaXR5IHRvIGRvIG11bHRpcGxlIGluaGVyaXRhbmNlIGdp dmVzIG1lIHRoZSBhYmlsaXR5IHRvIGNvbWJpbmUgYm90aCB0YWJsZXMgaW50byBvbmUgY2xhc3M6 CgpWZXJ5IG5pY2UgZm9yIHRoZSB0ZW1wbGF0ZXMgYW5kIGFsc28gZWFzeSB0byBxdWVyeS4gSXQg bG9va3MgbGlrZSBhIG5vcm1hbCBweXRob24gY2xhc3MuIEkgaGF2ZW4ndCB0cmllZCBpZiB0aGF0 IGFsc28gd29ya3MgZm9yIHdyaXRlIGFjY2VzcywgYnV0IEkgZG91YnQgaXQuIEJlY2F1c2Ugb2Yg dGhhdCBJIGhhdmUgYWRkZWQgYW4gZXhjZXB0aW9uIHRvIHRoZSBfX2luaXRfXyBtZXRob2QgdG8g YXZvaWQgY3JlYXRpbmcgcGFnZXMgYW5kIHJldmlzaW9ucyB2aWEgdGhlIFJldmlzaW9uZWRQYWdl IG9iamVjdC4KClRoZSBmdWxsIGV4YW1wbGUgY2FuIGJlIGZvdW5kIEVTAAAAAWFMAABNAAFTAAAA BGhyZWZTAAAATmh0dHA6Ly9kZXYucG9jb28ub3JnL3Byb2plY3RzL3dlcmt6ZXVnL2Jyb3dzZXIv ZXhhbXBsZXMvc2ltcGxld2lraS9kYXRhYmFzZS5weVMAAAAZaW4gdGhlIHNpbXBsZXdpa2kgc291 cmNlc1MAAAABLlMAAAAGcGFyc2VyUwAAAARodG1sUwAAAAVpbnRyb1JTAAAAAEwAAA== k4mlkamal@smach.nethttp://www.k4ml.com/2007-11-24T06:20:00Znono0Hi, any special reason not to use Jinja for the templates in this example ?Hi, any special reason not to use Jinja for the templates in this example ?SQAAAAJTAAAABGJvZHlSUwAAAEtIaSwgYW55IHNwZWNpYWwgcmVhc29uIG5vdCB0byB1c2UgSmlu amEgZm9yIHRoZSB0ZW1wbGF0ZXMgaW4gdGhpcyBleGFtcGxlID9MAABTAAAABnBhcnNlclMAAAAE aHRtbA== Armin Ronacherarmin.ronacher@active-4.comhttp://lucumr.pocoo.org/2007-11-24T19:01:10Znono0First of all creoleparser uses genshi internally so it plays nice with genshi itself of course. On the other hand I want to show that you can combine werkzeug with any library out there not just the pocoo libraries. :-) Regards, ArminFirst of all creoleparser uses genshi internally so it plays nice with genshi itself of course. On the other hand I want to show that you can combine werkzeug with any library out there not just the pocoo libraries. :-) Regards, ArminSQAAAAJTAAAABGJvZHlSUwAAAOtGaXJzdCBvZiBhbGwgY3Jlb2xlcGFyc2VyIHVzZXMgZ2Vuc2hp IGludGVybmFsbHkgc28gaXQgcGxheXMgbmljZSB3aXRoIGdlbnNoaSBpdHNlbGYgb2YgY291cnNl LiBPbiB0aGUgb3RoZXIgaGFuZCBJIHdhbnQgdG8gc2hvdyB0aGF0IHlvdSBjYW4gY29tYmluZSB3 ZXJremV1ZyB3aXRoIGFueSBsaWJyYXJ5IG91dCB0aGVyZSBub3QganVzdCB0aGUgcG9jb28gbGli cmFyaWVzLiA6LSkKClJlZ2FyZHMsCkFybWluTAAAUwAAAAZwYXJzZXJTAAAABGh0bWw= Wokdave.null@example.org2008-01-05T06:32:28Znono0Thank you for writing this bit, it does help conceptualising the thing. I saw how Django does that, I read the definitions of Active Record and Data Mapper, and your piece gives a clear Python example on how to do the second with SQLAlchemy. Don’t want to say a word on Wikicreole. Rather writing reStructuredText alone than struggling with brackets! End of sarcasm :) Best regards, WokThank you for writing this bit, it does help conceptualising the thing. I saw how Django does that, I read the definitions of Active Record and Data Mapper, and your piece gives a clear Python example on how to do the second with SQLAlchemy. Don’t want to say a word on Wikicreole. Rather writing reStructuredText alone than struggling with brackets! End of sarcasm :) Best regards, WokSQAAAAJTAAAABGJvZHlSUwAAAYVUaGFuayB5b3UgZm9yIHdyaXRpbmcgdGhpcyBiaXQsIGl0IGRv ZXMgaGVscCBjb25jZXB0dWFsaXNpbmcgdGhlIHRoaW5nLiBJIHNhdyBob3cgRGphbmdvIGRvZXMg dGhhdCwgSSByZWFkIHRoZSBkZWZpbml0aW9ucyBvZiBBY3RpdmUgUmVjb3JkIGFuZCBEYXRhIE1h cHBlciwgYW5kIHlvdXIgcGllY2UgZ2l2ZXMgYSBjbGVhciBQeXRob24gZXhhbXBsZSBvbiBob3cg dG8gZG8gdGhlIHNlY29uZCB3aXRoIFNRTEFsY2hlbXkuCgpEb27igJl0IHdhbnQgdG8gc2F5IGEg d29yZCBvbiBXaWtpY3Jlb2xlLiBSYXRoZXIgd3JpdGluZyByZVN0cnVjdHVyZWRUZXh0IGFsb25l IHRoYW4gc3RydWdnbGluZyB3aXRoIGJyYWNrZXRzISBFbmQgb2Ygc2FyY2FzbSA6KSBCZXN0IHJl Z2FyZHMsIFdva0wAAFMAAAAGcGFyc2VyUwAAAARodG1s Convert an internal iterator into an external in Pythonhttp://lucumr.pocoo.org/cogitations/2007/11/18/convert-an-internal-iterator-into-an-external-in-python/2007-11-18T21:42:47Z2007-11-18T21:42:47ZArmin Ronacherconvert-an-internal-iterator-into-an-external-in-pythonyesyes2<!-- PYGMENTS_CACHE><div class="highlight"><pre><span class="k">from</span> <span class="nn">py.magic</span> <span class="k">import</span> <span class="n">greenlet</span> <span class="k">def</span> <span class="nf">make_iterator</span><span class="p">(</span><span class="n">func</span><span class="p">):</span> <span class="n">g1</span> <span class="o">=</span> <span class="n">greenlet</span><span class="o">.</span><span class="n">getcurrent</span><span class="p">()</span> <span class="n">g2</span> <span class="o">=</span> <span class="n">greenlet</span><span class="p">(</span><span class="k">lambda</span><span class="p">:</span> <span class="n">func</span><span class="p">(</span><span class="k">lambda</span> <span class="n">item</span><span class="p">:</span> <span class="n">g1</span><span class="o">.</span><span class="n">switch</span><span class="p">((</span><span class="n">item</span><span class="p">,))),</span> <span class="n">g1</span><span class="p">)</span> <span class="k">while</span> <span class="mf">1</span><span class="p">:</span> <span class="n">rv</span> <span class="o">=</span> <span class="n">g2</span><span class="o">.</span><span class="n">switch</span><span class="p">()</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">rv</span><span class="p">:</span> <span class="k">return</span> <span class="k">yield</span> <span class="n">rv</span><span class="p">[</span><span class="mf">0</span><span class="p">]</span> </pre></div> <PYGMENTS_CACHE --><!-- PYGMENTS_RAW(python)>from py.magic import greenlet def make_iterator(func): g1 = greenlet.getcurrent() g2 = greenlet(lambda: func(lambda item: g1.switch((item,))), g1) while 1: rv = g2.switch() if not rv: return yield rv[0]<PYGMENTS_RAW --> Example usage: <!-- PYGMENTS_CACHE><div class="highlight"><pre><span class="k">def</span> <span class="nf">my_internal_iterator</span><span class="p">(</span><span class="n">f</span><span class="p">):</span> <span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="nb">xrange</span><span class="p">(</span><span class="mf">10</span><span class="p">):</span> <span class="n">f</span><span class="p">(</span><span class="n">item</span><span class="p">)</span> <span class="n">iterator</span> <span class="o">=</span> <span class="n">make_iterator</span><span class="p">(</span><span class="n">my_internal_iterator</span><span class="p">)</span> <span class="n">iterator</span><span class="o">.</span><span class="n">next</span><span class="p">()</span> <span class="c"># yields 0</span> <span class="n">iterator</span><span class="o">.</span><span class="n">next</span><span class="p">()</span> <span class="c"># yields 1</span> </pre></div> <PYGMENTS_CACHE --><!-- PYGMENTS_RAW(python)>def my_internal_iterator(f): for item in xrange(10): f(item) iterator = make_iterator(my_internal_iterator) iterator.next() # yields 0 iterator.next() # yields 1<PYGMENTS_RAW --> Example usage: SQAAAANTAAAABGJvZHlSUwAAABAKRXhhbXBsZSB1c2FnZToKTAAAUwAAAAZwYXJzZXJTAAAABGh0 bWxTAAAABWludHJvUlMAAAAATAAA convert a Request.write() into a WSGI yieldhttp://lucumr.pocoo.org/cogitations/2007/11/18/convert-a-requestwrite-into-a-wsgi-yield/2007-11-18T21:20:07Z2007-11-18T21:20:07ZArmin Ronacherconvert-a-requestwrite-into-a-wsgi-yieldyesyes2I tried that for a long time now using python generators with yield and send threads and much more. But I never got anything that looked easy to understand and worked at the same time. The problem basically occurs if you have an old python web application that has some sort of request object with a write method that directly writes to the output stream of the server interface (sys.stdout or some sort of fastcgi/mod_python output stream object) and you want to convert the application to WSGI. Take the following piece of code from an imaginary legacy application: <!-- PYGMENTS_CACHE><div class="highlight"><pre><span class="k">def</span> <span class="nf">old_application</span><span class="p">(</span><span class="n">request</span><span class="p">):</span> <span class="k">from</span> <span class="nn">time</span> <span class="k">import</span> <span class="n">sleep</span> <span class="n">request</span><span class="o">.</span><span class="n">header</span><span class="p">(</span><span class="s">&#39;Content-Type: text/html&#39;</span><span class="p">)</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="nb">xrange</span><span class="p">(</span><span class="mf">10</span><span class="p">):</span> <span class="n">request</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">x</span><span class="p">)</span> <span class="o">+</span> <span class="s">&#39; &#39;</span><span class="p">)</span> <span class="n">request</span><span class="o">.</span><span class="n">flush</span><span class="p">()</span> <span class="n">request</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s">&#39;&lt;br&gt;And the next flush takes another second&lt;br&gt;&#39;</span><span class="p">)</span> <span class="n">request</span><span class="o">.</span><span class="n">flush</span><span class="p">()</span> <span class="n">sleep</span><span class="p">(</span><span class="mf">1</span><span class="p">)</span> <span class="n">request</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s">&#39;And done!&#39;</span><span class="p">)</span> </pre></div> <PYGMENTS_CACHE --><!-- PYGMENTS_RAW(python)>def old_application(request): from time import sleep request.header('Content-Type: text/html') for x in xrange(10): request.write(str(x) + ' ') request.flush() request.write('<br>And the next flush takes another second<br>') request.flush() sleep(1) request.write('And done!')<PYGMENTS_RAW --> Say we want to convert that into a WSGI application with those semantics: <!-- PYGMENTS_CACHE><div class="highlight"><pre><span class="k">def</span> <span class="nf">wsgi_application</span><span class="p">(</span><span class="n">environ</span><span class="p">,</span> <span class="n">start_response</span><span class="p">):</span> <span class="k">from</span> <span class="nn">time</span> <span class="k">import</span> <span class="n">sleep</span> <span class="n">start_response</span><span class="p">(</span><span class="s">&#39;200 OK&#39;</span><span class="p">,</span> <span class="p">[(</span><span class="s">&#39;Content-Type&#39;</span><span class="p">,</span> <span class="s">&#39;text/html&#39;</span><span class="p">])</span> <span class="k">yield</span> <span class="s">&#39; &#39;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">x</span><span class="p">)</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="nb">xrange</span><span class="p">(</span><span class="mf">10</span><span class="p">))</span> <span class="o">+</span> <span class="s">&#39; &#39;</span> <span class="k">yield</span> <span class="s">&#39;&lt;br&gt;And the next flush takes another second&lt;br&gt;&#39;</span> <span class="n">time</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="mf">1</span><span class="p">)</span> <span class="k">yield</span> <span class="s">&#39;And Done!&#39;</span> </pre></div> <PYGMENTS_CACHE --><!-- PYGMENTS_RAW(python)>def wsgi_application(environ, start_response): from time import sleep start_response('200 OK', [('Content-Type', 'text/html']) yield ' '.join(str(x) for x in xrange(10)) + ' ' yield '<br>And the next flush takes another second<br>' time.sleep(1) yield 'And Done!'<PYGMENTS_RAW --> The main problem is the time.sleep and all those flush calls. That means we cannot just buffer the contents but convert the into a generator on the fly. What we need to get that done are either coroutines, greenlets or two threads that communicate with each other. The easiest and I guess also fastest approach are <a href="http://codespeak.net/py/dist/greenlet.html">greenlets</a>. Here a function that converts an old legacy application like above into a WSGI application with the same semantics: <!-- PYGMENTS_CACHE><div class="highlight"><pre><span class="k">from</span> <span class="nn">py.magic</span> <span class="k">import</span> <span class="n">greenlet</span> <span class="k">class</span> <span class="nc">Request</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span> <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">environ</span><span class="p">):</span> <span class="bp">self</span><span class="o">.</span><span class="n">_parent</span> <span class="o">=</span> <span class="n">greenlet</span><span class="o">.</span><span class="n">getcurrent</span><span class="p">()</span> <span class="bp">self</span><span class="o">.</span><span class="n">environ</span> <span class="o">=</span> <span class="n">environ</span> <span class="bp">self</span><span class="o">.</span><span class="n">status</span> <span class="o">=</span> <span class="s">&#39;200 OK&#39;</span> <span class="bp">self</span><span class="o">.</span><span class="n">headers</span> <span class="o">=</span> <span class="p">[]</span> <span class="k">def</span> <span class="nf">header</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">item</span><span class="p">):</span> <span class="bp">self</span><span class="o">.</span><span class="n">headers</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="nb">tuple</span><span class="p">(</span><span class="n">item</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">&#39;:&#39;</span><span class="p">,</span> <span class="mf">1</span><span class="p">)))</span> <span class="k">def</span> <span class="nf">write</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">text</span><span class="p">):</span> <span class="bp">self</span><span class="o">.</span><span class="n">_parent</span><span class="o">.</span><span class="n">switch</span><span class="p">((</span><span class="s">&#39;write&#39;</span><span class="p">,</span> <span class="n">text</span><span class="p">))</span> <span class="k">def</span> <span class="nf">flush</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="bp">self</span><span class="o">.</span><span class="n">_parent</span><span class="o">.</span><span class="n">switch</span><span class="p">((</span><span class="s">&#39;flush&#39;</span><span class="p">,</span> <span class="bp">None</span><span class="p">))</span> <span class="k">def</span> <span class="nf">convert_app</span><span class="p">(</span><span class="n">application</span><span class="p">):</span> <span class="k">def</span> <span class="nf">wsgi_app</span><span class="p">(</span><span class="n">environ</span><span class="p">,</span> <span class="n">start_response</span><span class="p">):</span> <span class="n">request</span> <span class="o">=</span> <span class="n">Request</span><span class="p">(</span><span class="n">environ</span><span class="p">)</span> <span class="nb">buffer</span> <span class="o">=</span> <span class="p">[]</span> <span class="n">headers_sent</span> <span class="o">=</span> <span class="p">[]</span> <span class="k">def</span> <span class="nf">flush</span><span class="p">():</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">headers_sent</span><span class="p">:</span> <span class="n">start_response</span><span class="p">(</span><span class="n">request</span><span class="o">.</span><span class="n">status</span><span class="p">,</span> <span class="n">request</span><span class="o">.</span><span class="n">headers</span><span class="p">)</span> <span class="n">headers_sent</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="bp">True</span><span class="p">)</span> <span class="n">data</span> <span class="o">=</span> <span class="s">&#39;&#39;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="nb">buffer</span><span class="p">)</span> <span class="k">if</span> <span class="n">data</span><span class="p">:</span> <span class="k">yield</span> <span class="n">data</span> <span class="k">del</span> <span class="nb">buffer</span><span class="p">[:]</span> <span class="k">def</span> <span class="nf">run</span><span class="p">():</span> <span class="n">application</span><span class="p">(</span><span class="n">request</span><span class="p">)</span> <span class="n">request</span><span class="o">.</span><span class="n">flush</span><span class="p">()</span> <span class="n">g</span> <span class="o">=</span> <span class="n">greenlet</span><span class="p">(</span><span class="n">run</span><span class="p">,</span> <span class="n">request</span><span class="o">.</span><span class="n">_parent</span><span class="p">)</span> <span class="k">while</span> <span class="mf">1</span><span class="p">:</span> <span class="n">rv</span> <span class="o">=</span> <span class="n">g</span><span class="o">.</span><span class="n">switch</span><span class="p">()</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">rv</span><span class="p">:</span> <span class="k">break</span> <span class="n">signal</span><span class="p">,</span> <span class="n">value</span> <span class="o">=</span> <span class="n">rv</span> <span class="k">if</span> <span class="n">signal</span> <span class="o">==</span> <span class="s">&#39;flush&#39;</span><span class="p">:</span> <span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="n">flush</span><span class="p">():</span> <span class="k">yield</span> <span class="n">item</span> <span class="k">elif</span> <span class="n">signal</span> <span class="o">==</span> <span class="s">&#39;write&#39;</span><span class="p">:</span> <span class="nb">buffer</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">value</span><span class="p">)</span> <span class="k">return</span> <span class="n">wsgi_app</span> </pre></div> <PYGMENTS_CACHE --><!-- PYGMENTS_RAW(python)>from py.magic import greenlet class Request(object): def __init__(self, environ): self._parent = greenlet.getcurrent() self.environ = environ self.status = '200 OK' self.headers = [] def header(self, item): self.headers.append(tuple(item.split(':', 1))) def write(self, text): self._parent.switch(('write', text)) def flush(self): self._parent.switch(('flush', None)) def convert_app(application): def wsgi_app(environ, start_response): request = Request(environ) buffer = [] headers_sent = [] def flush(): if not headers_sent: start_response(request.status, request.headers) headers_sent.append(True) data = ''.join(buffer) if data: yield data del buffer[:] def run(): application(request) request.flush() g = greenlet(run, request._parent) while 1: rv = g.switch() if not rv: break signal, value = rv if signal == 'flush': for item in flush(): yield item elif signal == 'write': buffer.append(value) return wsgi_app<PYGMENTS_RAW --> Now that's a bunch of code. Let's go step by step through it. The first thing we do is creating a request class. This class should resemble the old request object as much as possible. All methods can work like they did before, the only differences are the write and flush methods. Those switch back to the parent greenlet (which is the greenlet that generated the request object, usually the main greenlet) and send some data to it (namely the name of the method and the argument). Whenever python encounters this statement it stops the execution and goes back to the point that switched into this greenlet. This point is in our example in a loop that generates a generator for our WSGI application. That leads us to the convert_app function that is passed and old legacy application and returns a new WSGI application. Inside this new WSGI application we create a new request object, pass it the WSGI environment and create some objects and functions we need so that we can process the data from the greenlets and convert it into a valid WSGI response: A buffer for unsent data, a list we use a sentinel for sent data, a flush method that returns a generator with the data from the buffer, starts the response and cleans the buffer, and a run method that invokes the old application and calls request.flush() after the application has finished so that we don't have to do that in the application itself. The mainloop after that basically switches between application greenlet and main greenlet until the return value of switch is None (that is the case if the application closed or someone switched into the main greenlet without arguments, which we don't do). If that is the case we return, otherwise we check if it's a flush or write call and handle that. To launch the converted application with wsgiref all we have to do are those three lines of code: <!-- PYGMENTS_CACHE><div class="highlight"><pre><span class="k">from</span> <span class="nn">wsgiref.simple_server</span> <span class="k">import</span> <span class="n">make_server</span> <span class="n">srv</span> <span class="o">=</span> <span class="n">make_server</span><span class="p">(</span><span class="s">&#39;localhost&#39;</span><span class="p">,</span> <span class="mf">5000</span><span class="p">,</span> <span class="n">convert_app</span><span class="p">(</span><span class="n">old_application</span><span class="p">))</span> <span class="n">srv</span><span class="o">.</span><span class="n">serve_forever</span><span class="p">()</span> </pre></div> <PYGMENTS_CACHE --><!-- PYGMENTS_RAW(python)>from wsgiref.simple_server import make_server srv = make_server('localhost', 5000, convert_app(old_application)) srv.serve_forever()<PYGMENTS_RAW --> Basically greenlets would make it possible to host mod_python applications inside arbitrary WSGI servers. Maybe in the future someone writes a module that allows us to convert some of the mod_python applications into WSGI applications without touching existing application code.I tried that for a long time now using python generators with yield and send threads and much more. But I never got anything that looked easy to understand and worked at the same time. The problem basically occurs if you have an old python web application that has some sort of request object with a write method that directly writes to the output stream of the server interface (sys.stdout or some sort of fastcgi/mod_python output stream object) and you want to convert the application to WSGI. Take the following piece of code from an imaginary legacy application: Say we want to convert that into a WSGI application with those semantics: The main problem is the time.sleep and all those flush calls. That means we cannot just buffer the contents but convert the into a generator on the fly. What we need to get that done are either coroutines, greenlets or two threads that communicate with each other. The easiest and I guess also fastest approach are <a href="http://codespeak.net/py/dist/greenlet.html">greenlets</a>. Here a function that converts an old legacy application like above into a WSGI application with the same semantics: Now that's a bunch of code. Let's go step by step through it. The first thing we do is creating a request class. This class should resemble the old request object as much as possible. All methods can work like they did before, the only differences are the write and flush methods. Those switch back to the parent greenlet (which is the greenlet that generated the request object, usually the main greenlet) and send some data to it (namely the name of the method and the argument). Whenever python encounters this statement it stops the execution and goes back to the point that switched into this greenlet. This point is in our example in a loop that generates a generator for our WSGI application. That leads us to the convert_app function that is passed and old legacy application and returns a new WSGI application. Inside this new WSGI application we create a new request object, pass it the WSGI environment and create some objects and functions we need so that we can process the data from the greenlets and convert it into a valid WSGI response: A buffer for unsent data, a list we use a sentinel for sent data, a flush method that returns a generator with the data from the buffer, starts the response and cleans the buffer, and a run method that invokes the old application and calls request.flush() after the application has finished so that we don't have to do that in the application itself. The mainloop after that basically switches between application greenlet and main greenlet until the return value of switch is None (that is the case if the application closed or someone switched into the main greenlet without arguments, which we don't do). If that is the case we return, otherwise we check if it's a flush or write call and handle that. To launch the converted application with wsgiref all we have to do are those three lines of code: Basically greenlets would make it possible to host mod_python applications inside arbitrary WSGI servers. Maybe in the future someone writes a module that allows us to convert some of the mod_python applications into WSGI applications without touching existing application code.SQAAAANTAAAABGJvZHlSUwAAA8BJIHRyaWVkIHRoYXQgZm9yIGEgbG9uZyB0aW1lIG5vdyB1c2lu ZyBweXRob24gZ2VuZXJhdG9ycyB3aXRoIHlpZWxkIGFuZCBzZW5kIHRocmVhZHMgYW5kIG11Y2gg bW9yZS4gQnV0IEkgbmV2ZXIgZ290IGFueXRoaW5nIHRoYXQgbG9va2VkIGVhc3kgdG8gdW5kZXJz dGFuZCBhbmQgd29ya2VkIGF0IHRoZSBzYW1lIHRpbWUuIFRoZSBwcm9ibGVtIGJhc2ljYWxseSBv Y2N1cnMgaWYgeW91IGhhdmUgYW4gb2xkIHB5dGhvbiB3ZWIgYXBwbGljYXRpb24gdGhhdCBoYXMg c29tZSBzb3J0IG9mIHJlcXVlc3Qgb2JqZWN0IHdpdGggYSB3cml0ZSBtZXRob2QgdGhhdCBkaXJl Y3RseSB3cml0ZXMgdG8gdGhlIG91dHB1dCBzdHJlYW0gb2YgdGhlIHNlcnZlciBpbnRlcmZhY2Ug KHN5cy5zdGRvdXQgb3Igc29tZSBzb3J0IG9mIGZhc3RjZ2kvbW9kX3B5dGhvbiBvdXRwdXQgc3Ry ZWFtIG9iamVjdCkgYW5kIHlvdSB3YW50IHRvIGNvbnZlcnQgdGhlIGFwcGxpY2F0aW9uIHRvIFdT R0kuIFRha2UgdGhlIGZvbGxvd2luZyBwaWVjZSBvZiBjb2RlIGZyb20gYW4gaW1hZ2luYXJ5IGxl Z2FjeSBhcHBsaWNhdGlvbjoKCgpTYXkgd2Ugd2FudCB0byBjb252ZXJ0IHRoYXQgaW50byBhIFdT R0kgYXBwbGljYXRpb24gd2l0aCB0aG9zZSBzZW1hbnRpY3M6CgpUaGUgbWFpbiBwcm9ibGVtIGlz IHRoZSB0aW1lLnNsZWVwIGFuZCBhbGwgdGhvc2UgZmx1c2ggY2FsbHMuIFRoYXQgbWVhbnMgd2Ug Y2Fubm90IGp1c3QgYnVmZmVyIHRoZSBjb250ZW50cyBidXQgY29udmVydCB0aGUgaW50byBhIGdl bmVyYXRvciBvbiB0aGUgZmx5LiBXaGF0IHdlIG5lZWQgdG8gZ2V0IHRoYXQgZG9uZSBhcmUgZWl0 aGVyIGNvcm91dGluZXMsIGdyZWVubGV0cyBvciB0d28gdGhyZWFkcyB0aGF0IGNvbW11bmljYXRl IHdpdGggZWFjaCBvdGhlci4gVGhlIGVhc2llc3QgYW5kIEkgZ3Vlc3MgYWxzbyBmYXN0ZXN0IGFw cHJvYWNoIGFyZSBMAAFFUwAAAAFhTAAATQABUwAAAARocmVmUwAAACpodHRwOi8vY29kZXNwZWFr Lm5ldC9weS9kaXN0L2dyZWVubGV0Lmh0bWxTAAAACWdyZWVubGV0c1MAAAjULgoKSGVyZSBhIGZ1 bmN0aW9uIHRoYXQgY29udmVydHMgYW4gb2xkIGxlZ2FjeSBhcHBsaWNhdGlvbiBsaWtlIGFib3Zl IGludG8gYSBXU0dJIGFwcGxpY2F0aW9uIHdpdGggdGhlIHNhbWUgc2VtYW50aWNzOgoKTm93IHRo YXQncyBhIGJ1bmNoIG9mIGNvZGUuIExldCdzIGdvIHN0ZXAgYnkgc3RlcCB0aHJvdWdoIGl0LiBU aGUgZmlyc3QgdGhpbmcgd2UgZG8gaXMgY3JlYXRpbmcgYSByZXF1ZXN0IGNsYXNzLiBUaGlzIGNs YXNzIHNob3VsZCByZXNlbWJsZSB0aGUgb2xkIHJlcXVlc3Qgb2JqZWN0IGFzIG11Y2ggYXMgcG9z c2libGUuIEFsbCBtZXRob2RzIGNhbiB3b3JrIGxpa2UgdGhleSBkaWQgYmVmb3JlLCB0aGUgb25s eSBkaWZmZXJlbmNlcyBhcmUgdGhlIHdyaXRlIGFuZCBmbHVzaCBtZXRob2RzLiBUaG9zZSBzd2l0 Y2ggYmFjayB0byB0aGUgcGFyZW50IGdyZWVubGV0ICh3aGljaCBpcyB0aGUgZ3JlZW5sZXQgdGhh dCBnZW5lcmF0ZWQgdGhlIHJlcXVlc3Qgb2JqZWN0LCB1c3VhbGx5IHRoZSBtYWluIGdyZWVubGV0 KSBhbmQgc2VuZCBzb21lIGRhdGEgdG8gaXQgKG5hbWVseSB0aGUgbmFtZSBvZiB0aGUgbWV0aG9k IGFuZCB0aGUgYXJndW1lbnQpLiBXaGVuZXZlciBweXRob24gZW5jb3VudGVycyB0aGlzIHN0YXRl bWVudCBpdCBzdG9wcyB0aGUgZXhlY3V0aW9uIGFuZCBnb2VzIGJhY2sgdG8gdGhlIHBvaW50IHRo YXQgc3dpdGNoZWQgaW50byB0aGlzIGdyZWVubGV0LiBUaGlzIHBvaW50IGlzIGluIG91ciBleGFt cGxlIGluIGEgbG9vcCB0aGF0IGdlbmVyYXRlcyBhIGdlbmVyYXRvciBmb3Igb3VyIFdTR0kgYXBw bGljYXRpb24uCgpUaGF0IGxlYWRzIHVzIHRvIHRoZSBjb252ZXJ0X2FwcCBmdW5jdGlvbiB0aGF0 IGlzIHBhc3NlZCBhbmQgb2xkIGxlZ2FjeSBhcHBsaWNhdGlvbiBhbmQgcmV0dXJucyBhIG5ldyBX U0dJIGFwcGxpY2F0aW9uLiBJbnNpZGUgdGhpcyBuZXcgV1NHSSBhcHBsaWNhdGlvbiB3ZSBjcmVh dGUgYSBuZXcgcmVxdWVzdCBvYmplY3QsIHBhc3MgaXQgdGhlIFdTR0kgZW52aXJvbm1lbnQgYW5k IGNyZWF0ZSBzb21lIG9iamVjdHMgYW5kIGZ1bmN0aW9ucyB3ZSBuZWVkIHNvIHRoYXQgd2UgY2Fu IHByb2Nlc3MgdGhlIGRhdGEgZnJvbSB0aGUgZ3JlZW5sZXRzIGFuZCBjb252ZXJ0IGl0IGludG8g YSB2YWxpZCBXU0dJIHJlc3BvbnNlOiBBIGJ1ZmZlciBmb3IgdW5zZW50IGRhdGEsIGEgbGlzdCB3 ZSB1c2UgYSBzZW50aW5lbCBmb3Igc2VudCBkYXRhLCBhIGZsdXNoIG1ldGhvZCB0aGF0IHJldHVy bnMgYSBnZW5lcmF0b3Igd2l0aCB0aGUgZGF0YSBmcm9tIHRoZSBidWZmZXIsIHN0YXJ0cyB0aGUg cmVzcG9uc2UgYW5kIGNsZWFucyB0aGUgYnVmZmVyLCBhbmQgYSBydW4gbWV0a