Listening for DOM events

December 2nd, 2016 by Alex No comments »

Lately, there haven’t been a nice way to track DOM changes, like a listener for a class change, or when the actual content of the item changes. There were some trial APIs in DOM3 Events specification called Mutation events, which basically allowed binding events to any element based on your needs (could be DOMNodeInserted or DOMAttrModified or others).

But now, there’s a better way. Behold, the MutationObserverhttps://developer.mozilla.org/en/docs/Web/API/MutationObserver

What is it

MutationObserver is a special class for creating DOM mutation observers (who would’ve thought..). To use it, we need to instantiate a new observer, and then run the observe method. Here is a full working example.

MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
 
function process() {
	// do something here
}
var tick = null;
var observer = new MutationObserver(function(mutations, observer) {
	// fired when a mutation occurs
	clearTimeout(tick);
	tick = setTimeout(process, 100);
});
observer.observe(document.body, {
	childList: true,
	subtree: true
});

As you might see, we first check if there is a stable API or WebKitMutationObserver, then initialize the actual observer and run its observe method passing the DOM node to listen on, and the actual conditions for observing. There are several different combinations you could use. For example, to listen to a class attribute change on a single node, you can do:

observer.observe(document.getElementById('someelement', {
	attributes: true,
	attributeFilter: ['class']
});

There is a debate where you should fire the event instantly, or apply some setTimeout, because you don’t want to trash your CPU in case the DOM changes too fast during the small amount of time. That’s why we have a simple trick with setTimeout(process, 100); which delays any action by 100ms, but still makes sure it runs only once.

When and why to use

MutationObserver can be used in environment where you don’t have much control over the generated DOM, but still want to post-process it. External domain script, a Chrome Extension, plugins for compiled and/or obscured scripts are to name a few.

Making the most basic MySQL insert in Python 2.*

November 27th, 2016 by Alex No comments »

This is a very simple example, but it might confuse you sometimes.

There are some differences from other languages like PHP or Node.js, particularly in the need to download a separate MySQL connector available on the official MySQL pages https://dev.mysql.com/downloads/connector/python/2.1.html

import mysql.connector
 
mysql_host='127.0.0.1'
mysql_port='3306'
mysql_user='user'
mysql_pass='pass'
mysql_db='test'
 
cnx = mysql.connector.connect(user=mysql_user, password=mysql_pass,
                              host=mysql_host,
                              port=mysql_port,
                              database=mysql_db)
cursor = cnx.cursor()
query = "INSERT INTO mytable SET `field1` = %s, `field2` = %s"
cursor.execute(query, ("value1", "value2"))
cnx.commit()

The main difference here is that we need to initialize a cursor, and that query arguments are all %s, there’s no support for %d or %f. That’s it.

Converting date between formats in Python

November 27th, 2016 by Alex No comments »

Python is very versatile when it comes to processing data. Dates are of no exclusion, here’s a simple example.

Let’s say we have a date in a human-friendly format like

time_created="Tue, 14 Jun 2016 10:35:05 GMT"

While this is a nicely formatted date, it is a no-go if we need to insert it into a database of some sort (for example, MySQL). Let’s convert it

import datetime
 
datetime_parsed = datetime.datetime.strptime(time_created, "%a, %d %b %Y %H:%M:%S GMT")
time_created_db = datetime_parsed.strftime('%Y-%m-%d %H:%M:%S')    ### 2016-06-14 10:35:05

What we did here is used the datetime class method strptime, and provided it the format of our datetime string. The full list of available formats is available in python docs https://docs.python.org/2/library/datetime.html#strftime-strptime-behavior

That was easy.

Send simple HTTP request with wget, curl, telnet and netcat

November 24th, 2016 by Alex No comments »

I won’t say much, sometimes you just need to trigger a remote script or test if it works.

Here’s how to do that in command line.

1. wget

wget is a “a non-interactive network retriever” as described in the docs.

wget -q 'http://graphicmaniacs.com' > /dev/null

2. curl

curl is a “command line tool and library for transferring data with URLs”

curl -s 'http://graphicmaniacs.com' > /dev/null

And of course, if you want the commands to not output anything in case of error, append 2>&1 to the end of command

3. telnet

Telnet is another interesting approach in case you don’t have wget or curl, or you are on a limited system.

telnet graphicmaniacs.com 80
GET / HTTP/1.1
Host: graphicmaniacs.com
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.98 Safari/537.36

Finish the telnet command with additional newline (hit enter again).

4. netcat or nc

This is another way to do it. Depending on the release, you could have “netcat” or “nc”, so check your system which one you have

printf "GET / HTTP/1.0\r\nHost: graphicmaniacs.com\r\n\r\n" | nc graphicmaniacs.com 80

Preparing a complete Docker container with Python app

November 12th, 2016 by Alex No comments »

So you made a complex Python application (for example, a web server). You want to make sure it runs on any Linux distribution, and doesn’t interfere with existing applications running on the server. This is where you can pack your app into a Docker container.

For simplicity, let’s assume you have a very simple application with only main.py and a pip requirements.txt. To make our app docker-ready, we need to only add one new file called Dockerfile with no extension. The file will contain a base image requirement for our application and a command to run:

FROM python:3.5.2-onbuild
CMD [ "python", "./main.py" ]

I’ve put a simple print("Hello from main.py") inside the main.py. You can use other python version if your script depends on older 2.*. As usual, all the available versions on are available on docker hub https://hub.docker.com/_/python/. Plus, the Dockerfile can have additional installation steps for your application. Say, you require an external video processing library, or a PDF generation library. In that case you can extend Dockerfile by adding RUN .. commands:

FROM python:3.5.2-onbuild
# for simplicity, just check some main applications versions 
RUN git --version
RUN cpp --version
CMD [ "python", "./main.py" ]

Now let’s run the build.

docker build -t python-app:1.0.0 .

This will build the current folder (hence the .), and -tag it with the name python-app version 1.0.0.

In this case we will see the build running, and we will also see the version of Git and C++ compiler. The result will look something like:

Step 2 : RUN git --version
 ---> Running in 31b703447adc
git version 2.1.4
 ---> 79cc684f89e5
Removing intermediate container 31b703447adc
Step 3 : RUN cpp --version
 ---> Running in 223979db4455
cpp (Debian 4.9.2-10) 4.9.2
Copyright (C) 2014 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

This means they are there and running fine and you can use them. Now let’s run our script:

docker run -it --rm --name my-app python-app:1.0.0

If everything was fine (which it should be) then you should see:

Hello from main.py

That’s it, you now have made a Dockerfile with your app, which everyone can run on any system.