Sunday 31 March 2013

Django-webtest

When testing my views in a Django application, I always use django-webtest. This is a Django binding for a library from paste, which simply talks to a web application using wsgi, and acts like a browser in a very basic manner.

For example: submitting forms works as expected and sends the data contained in the inputs inside such form, in the method defined in <form method=""> and to the url defined in <form action="">, click()ing links takes you to the url in their href attribute, etc.

These are tests which will actually tell you if your templates are broken. So you are not simply testing your views. You are testing the template html as well. If you forget to add that {÷ csrf_token ÷} to your form, the test will fail. If one of the designers accidentally removes your "edit profile" link, you will know that.

An obviously missing feature is JavaScript support. So, if your app doesn't work without it, you won't be able to use this to the fullest.

Your view testing code with WebTest will look like this:

    def test_delete_object(self):
        object = construct_model_instance_somehow()
        owner = object.owner

        # go to the object's page, logged in as the owner
        details_page = self.app.get(object.get_absolute_url(), user=owner)

        # click delete link
        delete_page = details_page.click('delete')

        form = delete_page.form

        form.submit().follow()

        self.assertFalse(Object.objects.filter(
            some_data='you know').exists())

Every .click() call is an assertion that the page loads with no errors, and returns the response. You can actually chain click calls, even though I don't find it so useful myself. If you want a BeautifulSoup to check that your HTML response contains the correct links, just install BeautifulSoup (3.x for now) in your environment and access response.html to get a soup. Not to mention .showbrowser(), which fires up your browser to show you the HTML directly. A huge time saver for debugging.

In conclusion, very useful stuff. You should use it.

Monday 25 March 2013

Pip requirements.txt tip

Good guy requirements.txt

Everybody loves requirements.txt files, right? You can list your dependencies, and then together with pip and virtualenv reproduce your application's environment complete with all dependencies in several machines.

This file is also known as pipscript.txt. in case you don't know, requirements.txt is a file containing a list of packages in this format:

    Django==1.4.4
    Fabric>=1.0
    OtherPackage==6.0
    -e git://some.git/repo/containing/package

It's very simple to use. You just have to use the command pip install -r <requirements file>. For this reason, it makes it very easy to automate a deployment step.

Splitting your requirements

In case your application needs to split requirement files for some reason, you can do that! Just add this line in a pip file:

    -r some/requirements.txt

To include another requirements file.

The requirements listed in the included file will get installed too.

I found out about this trick in this heroku doc page . It makes a lot of sense, seeing that requirements.txt represents a pip install command for each line. We get -e, why not -r?

This is very useful for Django, where you need a different package set in production and development.

Monday 18 March 2013

Launching Q&A Website

In the next few weeks, I will be deploying and starting a new website. It's a Q&A website with focus on bureaucracy. It is localized in Portugal, so I won't be writing much about it on this blog.

I'll be using question2answer, which is a PHP-based open-source QA website. I will customize it and open-source that customization on github as well as a few fabric scripts I will use to test and deploy the website.

There is no kind of business plan yet. I don't really intend to make more money from it more than the amount needed to pay for the hosting, but this could change if I saw this really taking off.

As for marketing and getting people on this, I have started a Facebook page last week, with not too many people on it so far. I'm guessing I will need a lot of people to be there before I get to launch day.

Nobody wants to use an empty website. I have looked into how stackexchange launches a new website, and it's very interesting. They have the area 52 site, which is a staging zone where ideas are tested. People can commit to proposed sites and example questions are added. If a site is deemed good enough to launch, it goes into beta, and then becomes a full-fledged website.

I have to learn a bit more about stackexchange's process. I'm not too clear on the specifics.

Anyway, a simple "this is coming soon" + FAQ single web page is up in its future domain, papelada.pt

I never started any kind of website before, so this will be a great learning opportunity. I am looking forward to it!

Saturday 16 March 2013

I plead insanity!

I don't know what I was thinking when I wrote this, but...


I'm dressing up. I'm currently solely wearing a skullcap and a pair of soles. They stay in the ground as I take a step towards the watch, doubt and terror haunting me. In time, I shall know the time.

I catch a glimpse of myself in the mirror, and quickly avert my eyes. This naked figure is an enemy of mine. For quite a few reasons. Fortunately, our eye contact was broken just in time for me not to get existential. It would be disastrous to not be able to lay my left foot on the wooden floor and instead lay the rest of my body on it, in a ridiculous pose, twitching and wondering how many years of life I have left, and what is it that I'm supposed to do in them.

Anyway foot meets wooden floor. It is the third instance of this mundane contact ocurring today. First it was my two feet finding the cold-ish floor at nearly the same time, and then I resolved to know the correct time and ventured forth, nearly becoming existential. Phew! Today has been quite an ordeal. I finally check my watch.

It's 7:32! I should be down the street right now! But I can't just go. As I run for the bus, countless little kids would appear from miles away just to enjoy the scene of my helplessly running almost naked and they would all in unison endlessly mock my flaccid flapping cheeks and weak, powerless, dandling arms.

Sometimes I wish I wasn't made fun of in elementary school. My fantasies could be starred by beautiful porn stars with beautiful hair and dirty mouths.

I have to get dressed before I can run for the bus. But that would be at least 64 seconds. Oh god. That would make the minute part of my watch NOT be a power of two! This must be corrected. I set the watch backwards one full minute.

The watch now reads 7:31. It's not so bad. I relax and take my time to dress up. Eventually I notice that it's 7:32 again, but then again I am almost dressed up.

I put on my coat with that ridiculous spin I started doing recently. It makes my arms swiftly and smoothly slide into the coat. It is very practical and saves me some time and frustration. It's good that indoors I'm safe from all those elementary school kids.

I face my terror, the dark impenetrable corridor to the heavy front door of my scary, scary apartment. I brave the 10 meters like a real grown man, mostly because I am so late.

I grab the trash which lied stinking by the door and dart down the stairs to the front door of the building. In time, I will know. Fuck the past tense.

Running to catch the bus, I see nobody in the street. It's creepy. There should be quite a few irritable people on the street. It's Monday, damn it. Give me some entertainment!

There are no cars around either. My power-walk to the bus is so silent I can hear every piece of dirt my boots crush as I go.

By now, my boots have met the ground many, many times.

The number of times I hit the floor was equal to the number of times I hit the floor and that hit was not equal to any of the steps I had taken up to that.

O(Tn)? O(n^2)? I don't think that's fast enough for the reader to understand.

There were as many different steps as the total amount of steps I have taken.

That's a bit more humane.

Each of my steps was unique.

Still not right.

Each of my steps is a different step (that's better) in which I mercilessly stomp the floor in order to move forth just a bit more. I have failed to narrate them all. But right now such details are of no importance.

As I walk down the street, it's so silent that the walls scream back at me every sound of my boots' fight with the ground.

It's been raining. And it's been cloudy. And it's been cold. Or so I have been told. I have been lied to. I have been led to believe things which were not real. The weather hasn't been nice. Not even outside.

I seem to be alone in these streets. Although they are the same streets I trod each day, they are very much different on this particular day. Who knows if there's even a bus? Who knows anything at all? I'll know. Given time. I just have to believe in my self. Or this. It doesn't matter, though the latter is not good practice.

Given time, self knows.

The Street Where The Bus Comes is close. Many steps are to be taken, and yet, many steps were taken already. I check my watch. I forgot it in my bedroom. It reads 7:40. It's not a power of two. I don't feel pumped up at all anymore. I lay in the nearest bench until the time is right again.

The ground is not so friendly. It seems unreasonably cold and wet. It's a good thing I'm laying down on the bench. It's not clear what my watch reads. I know I will know.

The time comes. A new power of two. It's 7:64, which can mean one of two things. Either time has gone crazy and allowed this to happen, or I am infinitely late. I don't know who to blame. Do I blame Time? Or myself, for wasting nearly twenty-four minutes?

It's much too late. At the bus stop, a 10 seconds' walk away from the bus, there is no sign of people waiting for the bus. I'm late. I'm screwed. Shit.

However, a large vehicle right in front of the bus stop quickly gets my full attention. It's much bigger than an elephant, but not as yellow as the real thing. No, this is not gray at all.

It's the bus.

I enter the bus and look at the driver in the eye. Either I am looking at a very invisible driver or my line of sight merely passes through the gas I am swimming in, the driver's window, more of that invisible gas, and ends up crashing helplessly outside the bus.

Being a much simpler explanation, my common sense screams for me to accept my first theory as to why I can't see this driver. Of course he is invisible! It may be that my brain is just complaining about the complexity of the second explanation, refusing to even process that load of crap. Who knows?

A lot of questions start popping up. How did this simpleton become invisible? I know quite a few drivers. Which one is he? How do I greet him if I don't know where his eye level is?

Faced with all these terrible questions, I run away from the terrible bus, not even noticing it is full of invisible people. The less I know, the better.

This is insane. Am I dreaming? My cell phone is ringing. It's on my pocket, and it's not the alarm clock application.

I can sense which applications are active because I hacked my phone and my brain, and plugged a wireless dongle in the latter. I can also tell the rings apart, but that is just too simple of an explanation. I don't remember ever having any brain surgery but it sure is fun to believe I did this.

I take the call. I am going to be given a ride. I remember something like that being spoken yesterday. I run to the rendezvous location with a sparkle in my eyes and a wag on my tail. My invisible tail is adorable, I tell you.

I run into a dark car with a purple-haired girl as its captain, and my white-haired friend as the remaining crew. Both have no names today.

They tell me stories of their own waking up. I listen, to the wonderful tales of normality and boredom. I wish my life was like theirs.

The purple-haired girl tells me of how she could only be awake if the minute part of the time was a number in the Fibonacci sequence. But only if it's seven.

"Good thing it's almost nine", she says.

"Nine! Shit! I am going to be late!", I say.

"Nah", she says. I sure hate it when people refute simple logic like this.

But there is something I'm not aware of. She takes one of her many hands and rests it on a huge button. The button reads "hyperdrive". I just read it out aloud, and looked like an idiot. I see an ant. I'm sure that ant is laughing at me. I strike it with my index finger, but she judo throws me out of the car window.

Damn ants.

Back in the car, hyperdrive is still starting up. I take my seat, carefully observing the black body of the black hearted, black belted judo ant.

I wait. Hyperdrive is a few minutes away.

I wait. My white-haired friend chews gum. I ask for some of it. He punches me. I thank him. He was so fucking smart.

I wait. I am bored.

I wait. The sounds of hyperdrive are loud and unbearable.

I wait.

It's ready.

Defying the speed of light and taking like 2 years' life from all the occupants, the dark vehicle speeds forward. Its captain proudly steers it by barking orders at the slaves.

The damn paint of the car threatens to fall off. I see the car's true colors.

Orange and green.

How lame.

The glass windows and windshield start cracking.

And the dashboard.

The dashboard melted, but we still had the radio.

That said, we were there. I dropped from the car, weak-legged, heartbroken and heavy.

The judo ant didn't really throw me off. Its Elvis haircut did.

I reach for my watch again. I forgot it at home. It reads 8:50.

Damn hyperdrive. We went back in time a bit. Now I have to wait.

I wait forever. Forever minutes later, my batshit insane boss comes with his batshit insane ideas. He only speaks buzzwords. Leadershit, proactiveness, success, key, concept. He knows no punctuation. So you can't really talk to him because you will soon be drowned in bullshit. He is also incredibly thin and dazzlingly beautiful. I have no idea why I am still heterosexual with him around. Any other dude would bone the intended recipient or a few days in the intended recipient. You get the idea.

I take my seat.

It asks that my ass be more lightweight today. I ask him to go fuck himself.

The end.

Friday 8 March 2013

It turns out...

That you really need to set your MIME types when serving your static media. Every nginx-as-a-reverse-proxy configuration file example for Django I have seen missed this point and made me waste hours figuring out why static media is loaded from the server (with http status 200 OK) but ignored by browsers.

Apparently browsers will ignore media files with the wrong Content-Type header.

The consequences of this when a server is misconfigured aren't always immediately evident; for example, consider an HTML page (sent out correctly as text/html) which calls out a stylesheet and a number of in-lined images: if the server sends these out with a wrong Content-type, then the browser might be displaying the HTML page's main content, but the browser has every right to ignore the offending stylesheet, or to omit the offending image(s) from the display: indeed a strict interpretation of the rules would say that it must behave that way. Faking the wrong Content-type from the server is potentially a way of compromising security, so there's a genuine reason for this rule being the way that it is.

So take care, and keep this in mind.