Today, I wanted to improve our blog-title-to-permalink function, so that (French) accentuated characters are not simply stripped but rather converted to their non accentuated version. For example, "é" would be converted to "e".
After some googling and (slightly) tweaking what I found, here is the function I use:
noaccents_table = ''.join(map(chr, range(192))) + \
"AAAAAAACEEEEIIIIDNOOOOOxOUUUUYTsaaaaaaaceeeeiiiidnooooo/ouuuuyty"
def latin1_to_ascii(u_str):
return u_str.encode('latin1', 'replace').translate(noaccents_table)
As you can see, it takes a unicode string as argument. Here how you use it:
>>> latin1_to_ascii(u'évidemment')
'evidemment'
Note for later: if I ever need to do it in a more generalized way (not only for latin1), the iconv module (http://pypi.python.org/pypi/iconv) might (or might not) be useful.
Today, somebody asked me if Relatorio could generate sheets (aka tabs) dynamically. We had never done so and I did not know if it would work. It turns out it works nicely out of the box. The trick is to create a sheet with a <relatorio://for each="xxx"> link, then the sheet(s) you want repeated, then an empty sheet with only a <relatorio:///for> link.
Unfortunately, the name of the sheets created this way cannot be set dynamically so far. Instead, the first sheet so create will have the name of the repeated sheet and subsequent sheets will be named automatically by OpenOffice: TableXX
If anybody want to try it for himself, I've added a demo of sheet looping to the examples directory of Relatorio...
Here is a post I have started to write a long time ago but always postponed its completion...
Reading Elixir's mailing list and some comments about Elixir on various blogs, I came to realize that many people don't get what the real goal of Elixir is. To be honest, I didn't realize it myself until a couple months ago.
Sure, it abstracts some of the little details, but this has never been a goal in itself and is only a consequence of the goal. The initial goal was only to provide a declarative syntax. This goal is now also filled by the SQLAlchemy built-in declarative extension.
But what differentiate Elixir from declarative is its ability to generate columns (and other structures) and thus save people from repetitive declarations, both by providing built-in constructs for common patterns as well as providing a way to define their own patterns. For example, if you declare a many-to-one relation between a source entity and a target entity, you nearly always want to add a column in the source entity table with a foreign key constraint to the primary key column of the target entity table. When using pure SQLAlchemy, you have to declare the relationship and the column separately as in:
class Address(Base):
__tablename__ = 'addresses'
id = Column(Integer, primary_key=True)
email_address = Column(String, nullable=False)
user_id = Column(Integer, ForeignKey('users.id'))
user = relation(User, backref=backref('addresses', order_by=id))
while in Elixir, this is done in one step, as in:
class Address(Entity):
email_address = Field(String, required=True)
user = ManyToOne('User')
So, yes, Elixir generates columns for you, but it is not (and never was) meant to hide them from you. It is just meant to save you the trouble to explicitly declare them over and over again. In short, Elixir is a sort of templating system for SQLAlchemy, but to best benefit from Elixir, you should know what it generates for you, and thus you should understand how "raw SQLAlchemy" works.
Ok, now that I said that I hear people coming with the complaint that in our documentation we don't explain clearly nor prominently what gets generated for all constructs. You would be right. I wonder why nobody ever complained about this... For what it's worth, I consider those issues bugs and I am committed to fix them in time. Of course, I would gladly accept patches adding such documentation.
As to better clarify my "vision" of Elixir's future, here are the "abstract" goals I have for Elixir:
- Implement more useful patterns,
- provide ways to customize all the provided patterns the exact way you want them,
- and do not get in the way when you do not want to use them at all.
The only limitation Elixir should add is the inherent declarative limitation, which is that you can't map the same class to different tables/selectables.
Incidentally, these are roughly the release criteria for Elixir 1.0, whenever that will happen.
Creating a collection manager with Elixir in January issue of Python Magazine
Written on 2009-01-27 14:38.After being in the pipeline for a while, my article about Elixir was published in the January issue of Python Magazine. To my surprise, it even made the cover. Maybe, the editors meant it as a little present for my birthday (which is today), who knows... ;-)
Within the article, I build a simple collection manager using Elixir, SQLAlchemy, CherryPy and Genshi. This is the first time I write an article for a technical magazine, and I would really love to hear what people think about it.
Update: As I have been given access to the PDF version of the issue, I noticed the "Useful/Related Links" of my article are not the ones I put there (and are completely unrelated -- I wonder where they come from?). For what it's worth here are the links that should have been included:
- Source code for the program built within the article - http://www.openhex.com/products/elixir/pymag
- Data Mapper Pattern - http://www.martinfowler.com/eaaCatalog/dataMapper.html
- Active Record Pattern - http://www.martinfowler.com/eaaCatalog/activeRecord.html
- REST - http://en.wikipedia.org/wiki/Representational_State_Transfer
Now I understand why there was not any hit on the page holding the application source code...
Update: The version they distribute now has been corrected.
If programming languages were religions...
- Lisp would be Zen Buddhism - There is no syntax, there is no centralization of dogma, there are no deities to worship. The entire universe is there at your reach - if only you are enlightened enough to grasp it. Some say that it's not a language at all; others say that it's the only language that makes sense.
- Perl would be Voodoo - An incomprehensible series of arcane incantations that involve the blood of goats and permanently corrupt your soul. Often used when your boss requires you to do an urgent task at 21:00 on friday night.
- Python would be Humanism - It's simple, unrestrictive, and all you need to follow it is common sense.
For the full list, see: http://www.aegisub.net/2008/12/if-programming-languages-were-religions.html
A few weeks ago, I finally upgraded my laptop to Ubuntu Hardy (8.04). I had already upgraded my Desktop computer on the day of the release but given the numerous issues I had with the new version, I didn't switch my laptop (on which I work) yet. In my opinion, this was one the single most problematic release of Ubuntu ever (and I've been an Ubuntu user since its very first release). Since I had not seen any issue with my desktop computer for a while, and that I wanted firefox 3 (mainly for its increased javascript execution speed), I've given the current version a spin.
The upgrade went quite smoothly. I only wish the upgrade manager asked all questions (mostly about changes in system config files, most of them I didn't even do myself) at the beginning then work in the background without interrupting me.
Now with the actual title of this post... So, after the switch to Firefox 3, I soon discovered that one javascript application I'm working on (the client for OpenHexperience) didn't work anymore. I had a blank page, that's it. No error whatsoever. I soon found out that my javascript code wasn't called at all. Inline javascript worked fine but any code included in an external file was just silently ignored. After 3 hours of hair-pulling debugging, I finally understood the issue. It turns out it was Firefox 3's new pickiness at closing tags. It didn't like the way my script tag was closed in my simple html (not xhtml) bootstrap page.
<script type="text/javascript" src="/script/ohxp.js"/>
It wants an explicit closing tag, as in:
<script type="text/javascript" src="/script/ohxp.js"></script>
I'm all for respecting standards, and I've often bitched at IE for accepting totally invalid markup, but hell, introducing such a change without any error anywhere is almost a crime to humanity.
Now, what made this issue especially hard to debug was that I tried the correct version in my template very early in my debugging process, but it didn't fix my problem, leading me to search elsewhere. The culprit here was my memory... I completely forgot Genshi serialized to xml by default, and diligently replaced the empty script tag (with the explicit closing tag) by the shortcut syntax for empty tags... Exactly what Firefox doesn't want. As is often the case, once understood, fixing this issue was dead simple. One of the possible solutions is simply to tell Genshi to serialize to html, by changing:
return tmpl.generate(**data).render(doctype="html")
to
return tmpl.generate(**data).render("html", doctype="html")
- 1
