Tuesday, 9 December 2014

Web Intents/Activities are dead, but they could bring more life to the web

If you are creating an awesome e-mail app, you have a big problem. When meeting e-mails show up in your users' inboxes from their bosses and colleagues' calendars, they will expect some kind of integration with a calendar. You'd better integrate with a calendar, or create your own!

And integrating with only one calendar app is not enough. Oh no. You will alienate most of your users by doing that. Do you know how many calendar apps are out there? I sure don't, but OMG there must be a shitload of them!

Any.do Cal? You cannot simply afford to waste even half a week's time to improve the experience of 20 users instead of working on the loading animation. So you don't even consider supporting it.

In the end you'll only support the big guys.

This effect ends unbalancing the popularity of apps in the internet (by making the most popular apps be integrated with more stuff, which in turn makes them more popular). It also increases vendor lock-in and software duplication because it's just easier, more secure, and less trouble-prone to just develop an entire suite of related apps so they integrate well together than to integrate with dozens of third-party apps.

And you'd better pray that nobody new comes along and makes an app that becomes really popular.

This is the problem which Web Intents / Web Activities attempt to fix.

This is something which needs to have a universal browser support so web app developers can start registering their intents/activities. Unfortunately, the standardization effort seems to have been dropped by both Mozilla and Google, experimental support was removed from Chrome, and isn't even available on Firefox other than for the Firefox OS platform and Firefox for Android powered apps. A sad outcome for such wonderful tech.

Intents or Activities?

Did you notice I keep referring to this as "Intents/Activities"? The reason for that is that there are two competing defunct specs.

Google was working on standardizing Web Intents through the Web Intents Task Force, and even had (it's been removed) an experimental, prefixed WebKitIntent in their Chrome browser.

Mozilla needed something like Android's Intent on their Firefox OS platform, so they started standardizing Web Activities. They now provide a prefixed MozActivity in that same platform, and it's the standard way of doing Intents there. However, no support is present on the Firefox browser on the desktop.

A look at the dead APIs: Google's Web Intents

The Web Intents spec defines the relationship between a "Client" and a "Service". The client is the page which "Invokes" other webapps' Services, and the Service is a page which is "Registered" as capable to do some actions to some MIME types.

When the Client Invokes the service, the browser allows the user to Select what app they want to use to perform the action (which is something like "edit", "view" or "crop" but in URL form) on their data. There are a bunch of action URLs you can use, based on "http://webintents.org". It smells weird to me to use URLs as names for things, but it could be a good idea.

When The Service is Invoked, its page will be loaded up just like any other page, but have a window.intent Intent object available so they can look at what action, type and data the Client has passed him in this Invocation, and provide an adequate Response to send the Client when the user is done.

These examples are taken from the spec.

Below is an example which shows you how to register a Web Intents service for other apps to use:

[...]
<intent action="http://webintents.org/edit" type="text/uri-list image/*"></intent>
<script>
  window.addEventListener("load", function() {
    if (window.intent) {
      setImageContentURI(window.intent.data);
    }
  }, false);

  document.getElementById('save-button').addEventListener("click", function() {
    window.intent.postResult(getImageDataURI(...));
  }, false);
</script>

It's simple really, you only need to add one or more <intent> tags to your HTML describing the services you provide, and some Java Scripts to handle the case where the page is loaded as a service, and talk back to the intent user.

Here is how you use a Web Intent on some other page to allow the user to edit a photo you have somewhere.

document.getElementById('edit-photo').addEventListener("click", function() {
  var intent = new Intent({"action":"http://webintents.org/edit",
                           "type":"image/jpeg",
                           "data":getImageDataBlob(...)});
  navigator.startActivity(intent, imageEdited);
}, false);

function imageEdited(data) {
  document.getElementById('image').src = data;
}

As you can see, the intent type is a URL referring to the kind of action the intent is supposed to achieve. I can see this being unhelpful in many ways (by encouraging companies to create their own taxonomies of actions, for example).

All in all, it seems like a good proposal API, and I see no good reason it stopped being specified. I literally could not find it why it stopped, nor whether it stopped permanently.

A look at the dead APIs: Mozilla's Web Activities

Mozilla has developed Web Activities for their Firefox OS platform, and it shows.

An Activity is handled by a Handler, which is an App (mostly a Firefox OS concept) which Registers in its manifest which kinds of Activities it can handle, and what pages handle them.

When registering a handler, you can specify filters (an example of this is the type filter, which filters by mime type), and also a disposition (which defines how the application is displayed) and a returnValue boolean, which indicates if this activity handler will return a value or not.

They used a field in Firefox OS's app manifest file to announce what kind of activities your application can handle and where are the HTML files where these activities are handled.

The examples below were taken from MDN.

Here is how you can register your app as an activity handler in your app manifest:

{
  // Other App Manifest related stuff

  // Activity registration
  "activities": {

    // The name of the activity to handle (here "pick")
    "pick": {
      "href": "./pick.html",
      "disposition": "inline",
      "filters": {
        "type": ["image/*","image/jpeg","image/png"]
      },
      "returnValue": true
    }
  }
}

Here is how you handle an activity. You listen to a message (which is like an event, but is buffered for you so you can't miss it by adding a handler only after it was sent).

navigator.mozSetMessageHandler('activity', function(activityRequest) {
  var option = activityRequest.source;

  if (option.name === "pick") {
    // Do something to handle the activity
  }
});

And here is how you ask the Browser to somehow give you a JPEG. Pretty clean, no?

var activity = new MozActivity({
  // Ask for the "pick" activity
  name: "pick",

  // Provide the data required by the filters of the activity
  data: {
    type: "image/jpeg"
  }
});

activity.onsuccess = function() {
  var picture = this.result;
  console.log("A picture has been retrieved");
};

activity.onerror = function() {
  console.log(this.error);
};

A look at the dead APIs: comparison

I like how the Mozilla spec limits the activity types to a manageable count and how it lets you define if you wish to open a new window or open an overlay.

I also prefer Mozilla's client API. It seems much more familiar to just create an Activity and listen to events on that instance, like we do with XmlHTTPRequest and Web Workers.

On the other hand, I like how the Google spec allows a much, much simpler implementation of the Service.

Both have their pros and cons, and I hope they merge the two specs together somehow, and create an amazing shiny unicorn of love and butterflies!

Closing thoughts

Intents/Activities are already present in the mobile app world, and connect our mobile apps seamlessly and beautifully. In the desktop, it seems like fans of putting files somewhere and use them later have taken over everything and barf at gorgeous and intuitive workflows.

These APIs are seriously cool and extremely beneficial for both developers and users. Unfortunately it's not good businesses which want users to only use their stuff. It's definitely not good for Google, Apple nor Microsoft who have a lot of apps and want them integrated together in a closed ecosystem to increase vendor lock-in. And this means that 3 out of the 4 significant browser vendors are simply not interested in pushing this forward. They'd best snuff this out.

We already have closed walled-garden versions of Intents in Microsoft Office/Outlook, Adobe Creative Suite, and on Google apps (like the cool integration between Gmail and Google Drive). These weren't created to benefit the users, but instead to increase vendor lock-in.

This would make the web a significantly better place by giving a chance to smaller independent developers. They will do their integration more easily and concentrate on what their app does best, while easily connecting their app to a web-sized ecosystem of shite they could never dream of supporting otherwise.

If one of these specs was released, implemented and used by webdevs worldwide it would make the web a lot better, but it's pretty much dead. I would very much like them to be alive. I would very much like browser vendors to bridge Web Intents / Web Activities with similar APIs like Elementary OS's Contractor or Android's Intents so everyone can finally work seamlessly with web apps and native apps. I want to upload my e-mail attachments on Dropbox or to Google Keep all the time, and it's a bother. It doesn't have to be.

Wednesday, 19 June 2013

Learn to encode, please!

As a software developer, you should be aware of character encodings and avoiding several problems with encoded strings.

Thanks to many software developers' issues in understanding that (and Windows) (and paths with spaces), I have four home folders in my system.

Thank you for your understanding. Or should I say, please start understanding?

Friday, 17 May 2013

Undercutting - a personal rambling

My underpaid self has been thinking about his own life and actions. It turns out I am doing the wrong thing by sitting in the same place.

I have spoken to a friend about my salary and what I do at work, and she scolded me for helping undercut other people's well deserved salaries. She is quite right. She told me of how she and her group had lost a web and graphic design project to some company who promised to do the same for much less. They obviously ended up doing a terrible job, and screwed up someone else's opportunity in the process.

My current employer does do the same thing, but this post is not about companies undercutting each other. It is about workers undercutting other workers in the same sector. By allowing myself to be underpaid for my work, I am not just being a fool. I am undercutting other IT professionals who live around my area and have skill sets similar to mine.

When I started working at my current job, I was told that my pay would increase as soon as I had proven myself a valuable addition to my company.

I should have known it wasn't true as soon as I had learned that a colleague and old friend, who is a skilled programmer and most defenitely a valuable addition to the company, has worked for nearly three years in the company and earns little more (less than 1%) than I. It should have been blatantly obvious when I knew that another colleague, an IT tech and nerdy nice guy on whose shoulders the company runs a lot of its profit and stability (he runs the actual maintenance operations for the company's maintenance clients), is in a worse situation, since he actually deserves more than both of us, but earns the same amount we do.

And as time passed and I created websites, applications and whatnot, it was obvious that that "valuable addition to the company" line was just crap.

I feel like a sucker. Now my country is in a crisis. Prices going up, a higher tax on my salary. My boss is saying that if we ever get a raise we will only waste the extra money in luxuries. I guess that's how he sleeps at night. This shit revolts me deeply.

But I never stopped to think that I was actually harming someone else.

Sometimes people are not too picky about their jobs. People at the start of their carreer or people who have just lost a job are often happy to take whatever they get. Some companies (like my own) are opportunists and will use this instead of hiring qualified personel for a proper value. Some companies use excuses like "gathering experience", "prove oneself as valuable to the company", or "finantial issues" to postpone expectations of better pay for another day. Empty promises that I am sure have made many boost their dedication and productivity for nothing. Actually they ended up undercutting a lot of people and yet deserved better pay themselves. It happened to me. I have seen it happen to a dear colleague who was hired after me.

This snowball of bullshit has to stop, and not just for me and my company. If you are in a similar situation, you should at least consider trying to end it if you can afford losing your job for a few months. If everyone accepts crappy jobs and bullshit, someday we all will only have crappy jobs and bullshit, and nobody will be able to do anything about it.

Tuesday, 14 May 2013

Python's new Enum class

I used to wish to have an enumeration in Python, like you have in other languages.

On May 10th, GvR accepted PEP 435, which proposes the addition of an Enum type to the standard library.

Before this, us python coders would need to use plain classes for enums, which doesn't work so well. We can't get enum names by value, for example.

It follows that it's not possible to create a list of 2-tuples for use with Django models. We'd need to have a class mapping our choice names to their values, but you can't create the good old "choices" structure, so that's pretty useless. However, since our new enums are iterable we can:

    class ChoiceClass(IntEnum):
        foo = 1
        bar = 2
        baz = 3

    CHOICES = [(e.value, e.name) for e in ChoiceClass]

Creating your enumerations

By inheriting from Enum, you can create your own enumerations. If all your enumeration values are supposed to be of the same type, you should inherit Enum as well as that type.

    class Numbers(int, Enum):  # you can also use IntEnum
        one = 1
        two = 2
        three = 3

    class Text(str, Enum):
        one = 'one'
        two = 'two'
        three = 'three'

Using your enumerations

By iterating over your enum class, you get the enumeration members, which can be queried for their name or value.

    print(' '.join(['{}: {}'.format(number.name, number.value) for number in Numbers]))

Internally, there is some metaclass magic going on, to allow us to succintly declare these enums. The class comes with a few facilities, like __iter__ as I showed above, __call__ which gets enumeration items by value, and __getitem__ which gets them by name.

You should understand that enumeration items are actually instances of your enumeration class. Which allows us to say isinstance(Text.one, Text).

You can get your enumeration items in several ways.

  • As an attribute: Numbers.one, the Java way
  • By name: Numbers['one'], a tad prettier than using getattr
  • By value: Numbers(1), as a constructor

In a way, the third syntax reminds me of how we convert values using their constructors in python, for instance, using str or int to convert existing objects to string or integer values.

You can start using these enums right away. There was talk of porting this back to python 2 on the python-dev mailing list, but right now the code is for python 3 only. I'm going to convert some Django code to use these enums later, because I have three declarations for each Choice I need (SOMETHING_CHOICES, SOMETHING_DICT, SOMETHING_REVERSE), which is just backwards.

You can grab a copy of this module at bitbucket. Beware, because this was only put up for PEP evaluation. You'll want to wear a helmet and keep in mind that this is not stable or supposed to be used in production code. Although Guido has accepted it at the time of writing, it may still be subject to change, since the PEP is not in the "final" status.

That said, grab the "ref435" module from that package and try it out.

    >>> from ref435 import Enum
    >>> class Enumeration(int, Enum):
    ...     potatoes = 1
    ...     apples = oranges = 2
    ... 
    >>> Enumeration.apples is Enumeration.oranges
    True

You can look for reference in the PEP.

See you next time!

Tuesday, 7 May 2013

PHP

Yesterday I have had the joy of writing some php code. It was marvelous. minutes later a syntax error popped from a regular function taking a string. I called my colleague, who had experience with php. We were both stumped. It used eval. I guess we are both dumb.

Php is so simplistic and easy to understand, it's painful. If I pass an undeclared constant off to a function, php goes all the way to interpret it as its own name for me. I guess that would make some code more readable. Why mix foo with "bar"? This syntax allows us to just go all the way and use constant name syntax everywhere. Then we just don't declare the constants supposed to be those strings. Such advanced magic.

They say that the best technology is indistinguishable from magic. I say the best technology goes ahead and makes my code run more easily, even if it has bugs which will pop up later. It's so smart right? Who cares about tomorrow? Everybody knows code is written just once and doesn't need to be maintained or anything like that.

Code for today. Write no abstractions. Php allows the ultimate freedom. If you want to shoot yourself in the foot, just do it. It's not like there is anything stopping you at all. It's your job, not mine. You know what you are doing. We all know that php is a language for experts, everyone will know better than to carelessly use unsanitized user input to form SQL queries (and HTML too!) It all comes from $_GET clean and safe with your magic slashes right?

</sarcasm>

It's not a language problem as much as it is a cultural problem. Although the former appears to have caused the latter.

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.

Thursday, 28 February 2013

Media queries being ignored

Are all your media queries failing? You are probably just forgetting to add the meta tag. The code is as follows:

    <meta name="viewport" content="width=device-width">

Then you can use your media queries. They will work.

    @media (max-width: 800px) {
        .titleimg {
            width: 100%;
        }
        .wrapper {
            width: auto;
        }
    }

You will also want to keep in mind that tablet and smartphone vendors will lie about their device's resolution and physical size. This is because of display density differences among devices, and between these devices and the desktop.

You can read more about this on quirksmode.

Saturday, 23 February 2013

Python discovery: urlparse - parse URLs with ease

I had a problem during testing: I wanted to test the query part of an url generated by a function. I was getting my regex hat out, when I started to wonder if the Python standard library included something to do what I sought to do.

A quick google search for "python parse url" did the trick. I found out about the urlparse module, which was clearly made for this purpose.

Example of parsing urls with python using the urlparse module:

    >>> from urlparse import urlparse
    >>> urlparse('http://www.example.com/pth?q=123#frag') 
    ParseResult(scheme='http', netloc='www.example.com', path='/pth', params='', query='q=123', fragment='frag')
    >>> parse_result = _
    >>> parse_result.scheme
    'http'
    >>> parse_result.query
    'q=123'
    >>> parse_result.fragment
    'frag'
    >>>

Lesson learned: There are many more things in the Python standard library than one would dare imagine.

Saturday, 16 February 2013

A cute service

The guys at {placekitten} have made this simple, but cute, service. It's intended for developers like you and me, who don't have many pictures laying around on their hard drive.

When in need of a quick example image, you can hotlink to them and get a cute kitty as a placeholder :3

Here is 200x200:

I found this especially useful in jsfiddle, since you have nowhere to upload your images.

Just make an <img> tag and set src to the following:

    http://placekitten.com/{ width }/{ height }

And replace { width } and { height } by the width and height of the desired image.

Apparently a trailing slash makes your image a square, so if you get a square you know what's happening.

Their kitty pictures are really tasteful and cute. They vary according to the size of the image you requested.

Thursday, 31 January 2013

Python Discovery: Locals() and Globals()

Today I will mess with locals() and globals()

You may have encountered locals() and globals() before.

Here is what they do:

    >>> a = 3
    >>> def b():
    ...     c = 4
    ...     print 'locals', locals()
    ...     print 'globals', globals()
    ...
    >>> b()
    locals {'c': 4}
    globals {'a': 3, 'b': <function b at 0x021984B0>, '__builtins__': <module '__bui
    ltin__' (built-in)>, '__package__': None, '__name__': '__main__', '__doc__': Non
    e}
    >>>

They return a dictionary containing the local or the global scope.

According to this document, "scopes in Python do not nest!". At first it seemed like the python interpreter had an instance of the number two, but I think it actually counts as One local scope, and One extra scope to scan if the variable is not in this local scope.

It seems like manipulating globals() actually manipulates the names you have in your hands, directly. I liked this a lot, and was dumbfounded when I found out about it.

    >>> def b():
    ...     globals()['can_i_inject_a_name_plz'] = 'yes lol'
    ...     print can_i_inject_a_name_plz
    ...
    >>> b()
    yes lol

Yes, I was dumbfounded. I was fascinated. And then I found this:

    >>> def b():
    ...     locals()['injecting'] = 'yes'
    ...     print injecting
    ...
    >>> b()
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "<stdin>", line 3, in b
    NameError: global name 'injecting' is not defined

So I can't inject a name into the local scope. Well, I still have the global scope to play with. I also found that I can do this in the global scope of the interactive interpreter:

    >>> locals()['a'] = 4
    >>> a
    4

It seems like the Python interpreter still has his own secrets.

I decided to try to override variables below the current call stack. Manipulating the variables within other scopes granted me the ultimate power, and made my brain flesh out hundreds of ideas reeking of bad code practise and stuff which very few people, if any, had even used before in python:

    >>> globals()['name'] = 3
    >>> def g():
    ...     name = 6
    ...     print name
    ...
    >>> g()
    6

But no. My ideas crumbled. I can't access or change arbitrary names inside the functions I call. A small disappointment, followed by an "Eureka!" moment:

What if the function asked for it using the global keyword?

    >>> def g():
    ...     global locally_defined
    ...     try:
    ...         locally_defined
    ...     except NameError:
    ...         locally_defined = 'Local value'
    ...     print locally_defined
    ...
    >>> g()
    Local value
    >>>
    >>> globals()['locally_defined'] = 'Crazy value' # monkey patch!
    >>>
    >>> g()
    Crazy value
    >>>
    >>> del globals()['locally_defined'] # unpatch!

Or, even better, with the same effect.

    >>> def f():
    ...     global a
    ...     try:
    ...         a
    ...     except NameError:
    ...         a = 'local_value'
    ...     print a
    ...
    >>>

This is all nice, but what I achieved looks a lot like the intrincate and dark techniques of "argument passing" and "default arguments". I really don't want to lurk there.

Today's discovery was a failure. I learned much, but none of it is actually usable in real code. Sometime later, I will learn something better.

Thursday, 10 January 2013

3D Balls

Just because I haven't done any 3D work lately, and because it's too cold to type code, I decided to turn on blender 3D and see what I could do.


This is from old blender 2.60. I heard that blender's rendering engine was changed, but I used the old one anyways.

I used a negative point light below, a spotlight for the shadows and specularity, and an area light working only on diffuse for some soft lighting.

In the scene, there is a reflective plane with a shadeless white material, so it can bounce off the balls with a bit more shine.

The ball material includes reflection and a toon specular shader (I like it because it makes a larger and sharper reflection than other shaders). I also used nodes, to create the slight DOF effect.

Wednesday, 19 December 2012

Bookmarklet compiler

I think I should bookmark this one.

It's a very useful compiler for creating bookmarklets.

I could roll my own, but it's good that there is one already available.

Here is the link. It has source on github.

Unfortunately, it has some problems. It does little or nothing to reduce your script in size, which is a major issue in IE browsers. It apparently should remove comments, but that does not seem to work.

I think I will check out its license, and fork it. I have created good comment-matching regexes for my interesting-c project.

Monday, 17 December 2012

Add christmas to any page

I have devised a simple manner to get christmas on any page! Isn't jQuery animation awesome?

You can look at it here: http://jsfiddle.net/fabiosantoscode/Jw7Hs/

Saturday, 15 December 2012

Python interpreter: Underscore

I noticed that I used this trick in a previous post, and I feel like I should post about it since it's so unspoken of, and useful at the same time.
When in a CPython interpreter session (your plain old python session), the value given to "_" is always the last value automatically printed by the interpreter as the result of an expression.
    >>> 1+1
    2
    >>> _
    2
    >>> x = 3+5
    >>> _
    2
    >>> print "another value"
    another value
    >>> _
    2
As you can see, "_" is always the value that the interpreter automatically prints. If you use variable assignment, you can prevent the shortcut from gaining a value when you want to preserve it for later.
This can be very useful when you don't want to type again the full expression you used to obtain a certain value when you want to perform operations on such value. For example, in a Django shell, performing regex searches, testing generators and lists( list(_) ), etc.
Of course you can always use the Up arrow on your keyboard to repeat the last line of code and then edit it, if your shell supports history. But sometimes you really can't, and it's more practical to do it this way.
    >>> [1,2,3] + [4,5,6]
    [1, 2, 3, 4, 5, 6]
    >>> len([1,2,3] + [4,5,6])
    6
    >>> [1,2,3] + [4,5,6]
    [1, 2, 3, 4, 5, 6]
    >>> len(_)
    6
But don't worry about using "_" as a variable name inside the interpreter shell. It will simply override the behaviour described above.
    >>> _=100
    >>> _
    100
    >>> 4
    4
    >>> _
    100
    >>>
Trivia: the "underscore shortcut" doesn't show up in locals() or dir()
    >>> locals()
    {'__builtins__': , '__name__': '__main__', '__d
    oc__': None, '__package__': None}
    >>> dir()
    ['__builtins__', '__doc__', '__name__', '__package__']
    >>>

Thursday, 13 December 2012

A useful Django Template tag hidden

https://docs.djangoproject.com/en/dev/ref/templates/builtins/?from=olddocs#pprint

It seems to be really useful for debugging and creating those initial quick and dirty templates.

I often want to stay off my template code while programming view code. When I create templates, I make them minimal and just want visual confirmation of success and not creating a full template.

Thursday, 6 December 2012

Wildcards in python (the fnmatch module)

Filtering and matching against wildcard patterns is really easy in python, using the fnmatch module. I found this out while looking in an article by Dan Carrol for a solution to a Django problem of mine.

By using the fnmatch function, one can match strings against a case-insensitive pattern. Use fnmatchcase for case-sensitive matching).

    >>> import fnmatch
    >>> fnmatch.fnmatch('example', 'exampl*')
    True
    >>> fnmatch.fnmatch('example', '*e')
    True
    >>> fnmatch.fnmatch('example', '*es')
    False
    >>> fnmatch.fnmatch('examples', '*es')
    True

There's also a filter function, to filter a list against a pattern.

    >>> files = ['file.py', 'file.txt']
    >>> fnmatch.filter(files, '*.py')
    ['file.py']

Besides *, ? and [] are also available. And that's it. It's a very simple syntax. A moderately powerful syntax which everybody can use.

    >>> fnmatch.fnmatch('a', '?')
    True
    >>> fnmatch.fnmatch('1', '[13579]')
    True
    >>> fnmatch.fnmatch('4', '[13579]')
    False
    >>>

The wildcard characters cannot be escaped with slashes. You can only escape with square brackets. For example:

    >>> fnmatch.fnmatch('Here is a star: *', '*\*')
    False
    >>> fnmatch.fnmatch('Here is a star: *', '* [*]')
    True

At first I thought this way of escaping was impractical, but because of that, you can use unescaped user input without the user ever getting unexpected results. And, if you want to get the original regex (for reusing later) you can always use translate:

    >>> as_regex = fnmatch.translate('m[ae]tch th?is!')
    >>> as_regex
    'm[ae]tch\ th.is\!\Z(?ms)'

Because this module uses regular expressions internally and allows to get the actual regular expression, I can use it as a less error-prone re in some scenarios.

I think this module is great. It gives me a bit less matching power than regular expressions, but then I can empower the user by asking them what and how they want to search for. You could arguably do this with regular expressions, but you would end up wasting time and money in documentation and customer support because regex is error-prone and dangerous.

Check out the docs for more information on this module.