Django decorators

I am developing a page with Django and I had one interesting requirement: limit the number of users. The idea is to let a fixed number of users use the site and show a message telling the others to wait. I will like to share how I did it.

We need to check in every view used by a user. Instead of repeating the same code, the easiest way is to add a decorator for each function. Is really similar to AoP.

decorators.py:

from django.conf import settings
from django.shortcuts import redirect

MAX_NUMBERS_OF_USERS = getattr(settings, 'MAX_NUMBERS_OF_USERS', 100)

def check_user(view_function):
    def _wrapped_view_func(request, *args, **kwargs):
        auth_user = request.user
        
        if auth_user.id <= MAX_NUMBERS_OF_USERS:
            return view_function(request, *args, **kwargs)
        return redirect('coming_soon')
    return _wrapped_view_func

views.py:

from app.decorators import check_user
from django.contrib.auth.decorators import login_required
from django.shortcuts import render

@login_required
@check_user
def restricted_view(request):
    #Do stuff

def coming_soon(request):
    return render(request, 'coming_soon.html', {})

And that’s it ! Easy, clean and simple ! You can do more complex stuffs like logging.

Advertisements

Django + nginx + uWSGI

I had to deploy a web application I just created using Django. I will describe the steps I followed.

  1. Make sure you have you Django setted up correctly. I followed this guide.
  2. Install uWSGI into your virtualenv:
    pip install uwsgi
    
  3. Install nginx:
    sudo aptitude install nginx
    sudo service nginx start
    
  4. Edit nginx.conf file (it is in /etc/nginx if you are using ubuntu), it should be something like this:
    upstream django {
     server unix:///path/to/your/mysite/mysite.sock;
    }
    
    server {
     listen 80 default_server;
     listen [::]:80 default_server ipv6only=on;
    
     server_name mysite.com;
    
     charset utf-8;
    
     # max upload size
     client_max_body_size 5M; # adjust to taste
    
     location /robots.txt {
     alias /path/to/your/mysite/robots.txt;
     }
    
     # Django media
     location /files {
     alias /path/to/your/mysite/files; # your Django project's media files - amend as required
     }
    
     location /static {
     alias /path/to/your/mysite/static; # your Django project's static files - amend as required
     }
    
     # Finally, send all non-media requests to the Django server.
     location / {
     uwsgi_pass django;
     include /path/to/your/mysite/uwsgi_params; # the uwsgi_params file you installed
     }
    }
    

    Make sure it matches your Django app settings.py configuration:

    PROJECT_ROOT = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
    MEDIA_ROOT = os.path.join(PROJECT_ROOT, 'files')
    MEDIA_URL = '/files/'
    STATIC_ROOT = ''
    STATIC_URL = '/static/'
    
  5. Configure you uWSGI .ini file:
    # mysite_uwsgi.ini file
    [uwsgi]
    
    # Django-related settings
    # the base directory (full path)
    chdir = /path/to/your/mysite
    # Django's wsgi file
    module = mysite.wsgi
    # the virtualenv (full path) .virtualenvs at home folder
    home = /path/to/your/mysitevirtualenv  
    
    # process-related settings
    # master
    master = true
    # maximum number of worker processes
    processes = 10
    # the socket (use the full path to be safe
    socket = /path/to/your/mysite.sock
    # ... with appropriate permissions - may be needed
    chmod-socket = 666
    # clear environment on exit
    vacuum = true
    lgger = syslog
    
  6. Add uwsgi_params file to your project:
    uwsgi_param QUERY_STRING $query_string;
    uwsgi_param REQUEST_METHOD $request_method;
    uwsgi_param CONTENT_TYPE $content_type;
    uwsgi_param CONTENT_LENGTH $content_length;
    
    uwsgi_param REQUEST_URI $request_uri;
    uwsgi_param PATH_INFO $document_uri;
    uwsgi_param DOCUMENT_ROOT $document_root;
    uwsgi_param SERVER_PROTOCOL $server_protocol;
    uwsgi_param HTTPS $https if_not_empty;
    
    uwsgi_param REMOTE_ADDR $remote_addr;
    uwsgi_param REMOTE_PORT $remote_port;
    uwsgi_param SERVER_PORT $server_port;
    uwsgi_param SERVER_NAME $server_name;
    
  7. Run in emperor mode:
    # create a directory for the vassals
    sudo mkdir /etc/uwsgi
    sudo mkdir /etc/uwsgi/vassals
    # symlink from the default config directory to your config file
    sudo ln -s /path/to/your/mysite/mysite_uwsgi.ini /etc/uwsgi/vassals/
    /usr/local/bin/uwsgi --emperor /etc/uwsgi/vassals --uid www-data --gid www-data
    

    You can run the last command on screen or when the system starts.

And thats it, hope this can be helpful. You can find more info here.

Python expressiveness

Here i will post my solution of the first two problems in the qualifying round in the Google Code Jam. Both are easy problems.

The first one is:

https://code.google.com/codejam/contest/2974486/dashboard#s=p0

#!/usr/bin/python

def read_board(row_number):
    for i in xrange(4):
        if i + 1 == row_number:
            row = map(int, raw_input().split(' '))
        else:
            raw_input()
    return row 

ncases = int(raw_input())

for ncase in xrange(ncases):
    first_row_number = int(raw_input())
    first_row = read_board(first_row_number)

    second_row_number = int(raw_input())
    second_row = read_board(second_row_number)
    match_count = 0
    number = 0
    for i in first_row:
        for j in second_row:
            if i == j:
                number = i
                match_count += 1
                break

    answer = 'Case #' + str(ncase + 1) + ': '
    if match_count == 0:
        print answer + 'Volunteer cheated!'
    elif match_count == 1:
        print answer + str(number)
    else:
        print answer + 'Bad magician!'

And the other one was https://code.google.com/codejam/contest/2974486/dashboard#s=p1:

#!/usr/bin/python

ncases = int(raw_input())

for ncase in xrange(ncases):
    data = map(float, raw_input().split(' '))
    C, F, X = tuple(data)

    if X <= C:
        print 'Case #' + str(ncase + 1) + ': ' + str(X/2.0)
    else:
        house_times = [C/2.0]
        cookies_per_second = [2.0]
        min_time = X/2.0

        for i in xrange(int(X)/int(C)):
            new_cookies_per_second = cookies_per_second[i] + F
            new_time = house_times[i] + X/new_cookies_per_second
            house_times.append(house_times[i] + C/new_cookies_per_second)
            cookies_per_second.append(new_cookies_per_second)

            min_time = min(min_time, new_time)

        print 'Case #' + str(ncase + 1) + ': ' + str(min_time)

Python 🙂

Useful script i made some months ago

I am from Venezuela and some months ago we had presidential elections.

The opposition, which is in someway my tendency (I am tired of this goverment), called a fraud. So in order to check that my self i made a crawler for the web page (www.cne.gob.ve/resultado_presidencial_2013/r/1/reg_000000.html) with the results in order to gather and analyze them.

#!/usr/bin/python
# -*- coding: utf-8 -*-
import requests
import re
import threading

paths_re = re.compile('<s*li\s+class="region-nav-item"><a\s+id="region_ref"\s+href="(.*)"\s*>(.*)<\s*/a\s*>\s*<\s*/li\s*>', re.IGNORECASE)
values_re = re.compile('<tr\s+class="tbsubtotalrow"\s*>\s*<td\s+class="lightRowContent"\s+align="center"\s*>\s*<img\s+src=".+"\s+alt=""\s+width="50"\s+/>\s*
\s*<td\s+class="lightRowContent">\s*<table\s+width="100%">\s*<\s*tr\s*>\s*<\s*td\s+align="left"\s*>\s*<\s*a\s+href="javascript:showCandidateInfo\(\d\);"\s*>(.*)<\s*/a\s*>\s*<\s*/td\s*>\s*<\s*/tr\s*>(\s*<\s*tr\s*>\s*<\s*td\s*>\s*<\s*font\s+color="\#990000"\s*>\s*Adjudicado\s*<\s*/font\s*>\s*<\s*/td\s*>\s*<\s*/tr\s*>\s*|\s*)<\s*/table\s*>\s*<\s*/td\s*>\s*<\s*td\s+class="lightRowContent"\s+align="right"\s*>\s*<\s*span\s*>(.*)<\s*/span\s*>\s*<\s*/td>\s*<\s*td\s+class="lightRowContent"\s+align="right"\s*>\s*<\s*span\s*>(.*)<\s*/span\s*>\s*<\s*/td>\s*', re.IGNORECASE)
filter_re = re.compile('%|\.|\s')
main_url = 'http://www.cne.gob.ve/resultado_presidencial_2013/r/1/'
depth_map = ['All', 'State', 'Municipality', 'County', 'Center', 'Table']
separator = '\t'
outfiles = []
outfilename = 'electionsdata'
qttythread = 6
rthreads = []
generalfile = open(outfilename, 'w')
firstorder = dict()

def crawl_page(url, region, depth, file_to_write):
    page = requests.get(url)
    paths = paths_re.findall(page.text)
    values = values_re.findall(page.text)

    if region == separator:
        names = map(lambda v: v[0], values)
        counter = 0
        for name in names:
	        firstorder[name] = counter
	        counter += 1
		firstorder = map(lambda v: v[0], values)
        print_headers(file_to_write, names)

    print_info(file_to_write, region, values, depth)

    if region == separator:
        chunked_lists = chunk_list(paths, (len(paths) + (qttythread - len(paths) % qttythread)) / qttythread)
        threadn = 0
        for chunked_list in chunked_lists:
            t = threading.Thread(target=recursive_calls, args=(chunked_list, region, depth, outfiles[threadn], ))
            t.start()
            rthreads.append(t)
            threadn += 1
    else:
        recursive_calls(paths, region, depth, file_to_write)

def recursive_calls(paths, region, depth, file_to_write):
    savedregion = region
    for path in paths:
        pathsurl = path[0]
        pathsfor = path[1]
        region =  savedregion + separator + pathsfor
        print region
        crawl_page(main_url + pathsurl, region, depth + 1, file_to_write)

def chunk_list(l, chunksize):
    result = []
    for i in xrange(0, len(l), chunksize):
        result.append(l[i:i+chunksize])
    return result

def print_headers(file_to_write, names):
    result = 'Type'
    for region_type in depth_map:
        result += separator + region_type
    for name in names:
        result += separator + name + ' value\t' + name + ' %'
    file_to_write.write(result + '\n')

def print_info(file_to_write, region, values, depth):
	order_values(values)
    result = depth_map[depth] + region
    for i in xrange(len(depth_map) - depth - 1):
        result += separator
    for value in values:
        result += separator + clean_number_srt(value[2]) + separator + clean_number_srt(value[3])
    file_to_write.write(result + '\n')

def order_values(values):
    position = 0
    while position < len(values):
        needed_position = firstorder[values[position][0]]
	    if position == needed_position:
            position += 1
	    else:
            swap(values, position, needed_position)

def swap(l, i, j):
	aux = l[i]
	l[i] = l[j]
	l[j] = aux

def clean_number_srt(number_str):
    return filter_re.sub('', number_str).replace(',', '.')

if __name__ == "__main__":
    for i in xrange(qttythread):
        outfile = open(outfilename + str(i), 'w')
        outfiles.append(outfile)

    crawl_page(main_url + 'reg_000000.html', separator, 0, generalfile)

    for rthread in rthreads:
        rthread.join()

    for outfile in outfiles:
        outfile.close()
    generalfile.close()

In the end, i didn’t run it. I think this final version is pretty complete and can be used for another variety of things, thus I am sharing the code :). It use a number of threads and check the pages in a recursive way writing to different files. The regular expressions are pretty ugly, but i didn’t want to use a HTML parser or something like that.

Always learning !

As i wrote before, i did participate on Google Code Jam Qualification Round. I just did 3 problems and got 50 points.I’ll talk about one of the problems: Lawnmower.

#!/usr/bin/python
# -*- coding: utf-8 -*-

from sys import stdin

if __name__ == "__main__":
 ncases = int(stdin.readline())

 for ncase in xrange(ncases):
     n, m = map(int, stdin.readline().split(' '))

     lawn = [[] for j in xrange(n)]

     for row in xrange(n):
         lawn[row] = map(int, stdin.readline().split(' '))

         allle = True

         for row in xrange(n):
             for column in xrange(m):

                 hle = True
                 vle = True
             for frow in xrange(n):
                 if lawn[frow][column] > lawn[row][column]:
                     vle = False
             for fcolumn in xrange(m):
                 if lawn[row][fcolumn] > lawn[row][column]:
                     hle = False

             allle = hle or vle

             if not allle:
                 break
         if not allle:
             break

     result = 'YES' if allle else 'NO'
     print 'Case #' + str(ncase + 1) + ': ' + result

I got stuck for sometime, but in the end i found and coded quite elegant solution in python. We have a matrix and every element e[i,j] on it had to satisfy the following constraints:

  1. All elements e[i,k], with k != j must be e[i,k] <= e [i, j]
  2. All elements e[k,j], with k !=i must be e[k,j] <= e [i, j]

If both constraints are satisfied, then the answer is yes, else we can’t cut the lawn.

The interesting part is the next round i’ll like to talk about. I didn’t participate on Round A, but i did try round B. As i told before, i never practice for this, and after trying quite a bit the first problem i got frustrated and decided to stop. In like 30 minutes, there were already a lot of people with 2 or more problems completed.

I want to talk about the first problem: Osmos. The problem was easy to understand, my mistake was getting so stuck in thinking “efficiently” and trying to find the best solution. In the end i made a bad assumption and never passed the runs. I stopped and reminded to view the solution later.

I viewed the solution found my error and learned a lot from the code i saw.

I’ll show my fixed code:

#!/usr/bin/python
# -*- coding: utf-8 -*-

from sys import stdin

def dp(arminmote, motes):
    if len(motes) == 1:
        return 1 if arminmote <= motes[0] else 0 
    elif arminmote > motes[0]:
        steps = dp(arminmote + motes[0], motes[1:])
    else:
         steps = 1 + min(dp(2*arminmote - 1, motes), dp(arminmote, motes[1:]))
    return steps

if __name__ == "__main__":
    ncases = int(stdin.readline())

    for ncase in xrange(ncases):
        case = stdin.readline()
        arminmote, leftmotes = map(int, case.split(' '))

        case = stdin.readline()
        motes = map(int, case.split(' '))
        motes.sort()

        if arminmote > 1:
            steps = dp(arminmote, motes)
        else:
            steps = len(motes)

        print 'Case #' + str(ncase + 1) + ': ' + str(steps)

The Round B winner code:

# dolphinigle
# GCJ 2013 1B
# 4 May 2013

ntest = int(raw_input())
for itc in range(ntest):
  print 'Case #%d:' % (itc+1),
  my_mote, n = map(int, raw_input().split())
  motes = sorted(map(int, raw_input().split()))
  if my_mote == 1:
    print n
    continue
  best_answer = n
  my_answer = 0
  for index, i in enumerate(motes):
    if i < my_mote:
      my_mote += i
      continue
    # maybe stop here?
    best_answer = min([best_answer, my_answer + n - index])
    while my_mote <= i:
      my_mote += my_mote - 1
      my_answer += 1
    my_mote += i
  best_answer = min([best_answer, my_answer])
  print best_answer

Quite the difference? Yes. First i didn’t see any polynomial way of solving, i just though that it was needed in some cases to choose between 2 possibilities and didn’t use any memorization or dynamic programming technique. I did fail quite hard, but it is important to learn from mistakes.

I saw why the first place on round B is this guys. In just 7 minutes he came with this brilliant solution. With one cycle and using two variables: one to count the motes needed to eat and the other the best solution so far, starting with removing all the motes. I was amazed and learned a lot seeing this code. I had never use raw_input and enumerate. They are so useful.

Learning and sharing is so important, specially all regarding computers. One of the reason i made this post is that. Hope it is useful to someone.

Some programming problems

I am not a big fan of programming competions, but i do love good challenges and interesting problems. Google Code Jam (https://code.google.com/codejam/) is comming soon and i decide to participate in a normal way. I am not that hardcore programmer 24/7.

For practice I did two problems: File Fix-it and All Your Base. As i was so lazy, i used Python. I want to comment my reasoning for solving each of the problems.

  • File Fix-It: The problem consisted on on telling the minimum number of mkdirs (it creates folders one by one) to create the given directories. In each case was given the already done directories and the ones we needed to create. Creating directories can be viewed as building a tree. I simulated that using a dictonary.
#!/usr/bin/python
# -*- coding: utf-8 -*-

from sys import stdin

def add_directory(directory_hash, path, done):
    directory = ''
    created_directories = 0
    for node in path.split('/')[1:]:
        directory += '/' + node
        if not directory_hash.has_key(directory):
            directory_hash[directory] = True
            created_directories += 1
    return 0 if done else created_directories

if __name__ == "__main__":
    ncases = int(stdin.readline())

    for ncase in xrange(ncases):
        case = stdin.readline()
        done_nodes, left_nodes = map(int, case.split(' '))

        directory_hash = dict()

        for done_node in xrange(done_nodes):
            add_directory(directory_hash, stdin.readline().replace('\n',''), True)

        created_directories = 0

        for left_node in xrange(left_nodes):
            created_directories += add_directory(directory_hash, stdin.readline().replace('\n',''), False)

        print 'Case #' + str(ncase + 1) + ': ' +  str(created_directories)
  • All Your Base: A little more complicated problem. The input was an alphanumeric string and the output a mapping each symbol of it to de minimum number, in any base, expresed as a decimal. The minimum base was 2 and the first symbol can’t be 0. The solution was quite simple, map the first symbol to 1, after that, map from left to right each diferent symbol to 0, then 2, then 3 and so on. Finally change the number to base 10.
#!/usr/bin/python
# -*- coding: utf-8 -*-

from sys import stdin

if __name__ == "__main__":
    ncases = int(stdin.readline())

    for ncase in xrange(ncases):
        case = stdin.readline()

        mapped_number = 0
        symbol_number = dict()
        symbol_number[case[0]] = 1

        for symbol in case[1:-1]:
            if not symbol_number.has_key(symbol):
                symbol_number[symbol] = mapped_number
                mapped_number = 2 if mapped_number ==  0 else mapped_number + 1

        if mapped_number == 0:
            symbol_number[case[0]] = 1
            case.replace(case[0], '1')
            mapped_number = 2

        to_pow = len(case) - 3
        result_decimal = 1 * pow(mapped_number, to_pow + 1)

        for symbol in case[1:-1]:
            result_decimal += (pow(mapped_number, to_pow) * symbol_number[symbol])
            to_pow -= 1

        print 'Case #' + str(ncase + 1) + ': ' +  str(result_decimal)

Both handled the large inputs and are quite efficient. The teaching here is that before doing any code is important to reason how to solve the problem.
Lets see how i perform in the Code Jam :3.

Números primos

El fin estaba algo aburrido y venía de leer el siguiente artículo:

http://tech-queries.blogspot.com/2009/04/amazon-interview.html

Lo conseguí ya que me dio curiosidad como es el Fibonacci con eficiencia (n*log(n)) (http://tech-queries.blogspot.com/2010/09/nth-fibbonacci-number-in-ologn.html)

En eso me dio por hacer un problema en http://www.spoj.pl. Entre en mi cuenta, en la cual tengo como 7 problema hechos y vi cual hacer. Elegí uno de generar números primos( http://www.spoj.pl/problems/PRIME1/). Se da una serie de intervalos y hay que imprimir los números primos que hay en ellos.

Empece a programar en Python y yo ya conocía de la criba de Eratóstenes (http://es.wikipedia.org/wiki/Criba_de_Erat%C3%B3stenes) para generar números primos. Fui por una solución simple, buscaba el máximo número en el cual un intervalo terminaba y calculaba los primos hasta ahí y luego imprimía los que había en cada uno de los intervalos.

#!/usr/bin/python
# -*- coding: utf-8 -*-

from sys import stdin

def sieve(end):
    primes = range(2, end+1)
    for i in primes:
        j = 2
        while i * j <= primes[-1]:
            if i * j in primes:
	            primes.remove(i*j)
            j += 1
    return primes


if __name__ == "__main__":
    end = 0
    ncases = int(stdin.readline())
    cases = []

    for ncase in xrange(ncases):
        case = stdin.readline()
        case_start, case_end = map(int, case.split(' '))
        cases.append({'start' : case_start, 'end' : case_end})
        end = max(end, case_end)

    primes = sieve(end)

    count = 1

    for case in cases:
        for prime in primes:
            if prime < case['start']:
                continue
            elif prime <= case['end']:
                print prime
            else:
                break

        if count != ncases:
            print ''

        count += 1

No cumplió por problemas de memoria, ya que el arreglo de primos era muy grande, así que decido hacer lo mismo, pero en C++. Me encargue de hacerlo super eficiente en memoria, usando 1 bit por cada primo, en vez de 1 byte. Con mi computadora me tomó unos minutos sacar todos los primos hasta 1000000000. Me generó un archivo de 500 megas.

#include <iostream>
#include <fstream>
#include <vector>
#include <math.h>
#include <stdlib.h>
using namespace std;

const char masks [] = {-2, -3, -5, -9, -17, -33, -65, 127};

char *sieve(int max)
{
    int max_index = max/8 + 1;
    char *primes = new char[max_index];

    for(int i = 0; i < max_index; i++)
        primes [i] = 255;

    for(int i = 2; i <= max; i++)
    {
        int j = 2;
        int mult =  0;
        while((mult =  i * j) <= max)
        {
            int index = (mult - 1)/8;
            primes[index] &= masks[(mult - 1) % 8];
            j++;
        }

    }

    return primes;

}

int main()
{

    int ntest;
    int case_start, case_end;
    int max_end = 0, test = 1;
    vector<pair<int, int> > cases;

    cin >> ntest;

    for(; test <= ntest; test++)
    {
        cin >> case_start;
        cin >> case_end;

        pair<int, int> test_case(case_start, case_end);

        cases.push_back(test_case);

        max_end = (case_end > max_end ? case_end : max_end);

    }

    char *primes = sieve(max_end);

    vector<pair<int, int> >::iterator it;
    test = 1;

    for ( it=cases.begin() ; it != cases.end(); it++, test++ )
    {
        pair<int, int> test_case = *it;
        case_start = test_case.first;
        case_end = test_case.second;

        if(!(case_start & 1))
            case_start++;

        for(case_start; case_start <= case_end; case_start += 2)
        {
            if(case_start == 1) continue;
            int index = (case_start -1)/8;
            if(primes[index] & (1 << ((case_start -1) % 8)))
                cout << case_start << endl;
        }

        if(test != ntest)
            cout << endl;
    }

}

Esta vez se cayó por tiempo. Era claro que no use el modo correcto para calcular las cosas. Pensé un rato y leí un poco por Internet. Resulta que existe una versión segmentada de la criba de Eratóstenes.  Se calculan los primos hasta la raíz cuadrada del número (en este caso 32000) y luego con esos primos, se revisa en el intervalo si algo de esos es múltiplo de él, sino es un primo. Lo implemente y por tratar de programar de modo legible, entendible y bonito, se me cayo por tiempo. A la final elimine funciones e hice casi todo en la función principal y lo logre. Perdí un buen tiempo, pero fue interesante.

#include <iostream>
#include <fstream>
#include <vector>
#include <math.h>
#include <stdlib.h>
#include <string.h>
using namespace std;

#define MAX_FIRST_SIEVE_INDEX 32000
#define MAX_FIRST_SIEVE_PRIME 32000
#define MAX_PRIMES 4000

bool sieve[MAX_FIRST_SIEVE_INDEX];
int primes[MAX_PRIMES];

void gen_first()
{
    int i = 0, k = 0;

    memset(sieve, true, MAX_FIRST_SIEVE_INDEX);

    for(i = 2; i <= MAX_FIRST_SIEVE_PRIME; i++)
    {
        int j = 2;
        int mult =  0;
        if(sieve[i-1]) 
            primes[k++] = i;

        while((mult =  i * j) <= MAX_FIRST_SIEVE_PRIME)
        {
            sieve[mult-1] = false;
            j++;
        }

    }

}

int main()
{
    int ntest;

    cin >> ntest;
    gen_first();

    for(int test = 1; test <= ntest; test++)
    {
        int case_start, case_end;

        cin >> case_start;
        cin >> case_end;

        for(int i = (case_start > 2 ? case_start : 2); i <= case_end; i++)
        {
            bool print = true;

            for(int j = 0; primes[j]*primes[j] <= i; j++)
            {
                if(i % primes[j] == 0 )
                {
                    print = false;
                    break;
                }
            }
            if(print) cout << i << endl;

        }

        if(test != ntest)
            cout << endl;
    }


}

Big Data, mi opinión y varias cosas cool en Python

Big Data

Ayer revisando mi twitter, me encuentro con lo siguiente:

http://techcrunch.com/2012/10/27/big-data-right-now-five-trendy-open-source-technologies/

Varias de esas tecnología las he escuchado y usado: he usado un poco hadoop mediante pig y otros en el trabajo usan Kafka. Es increíble hacia donde esta yendo el mundo de la computación e información. Ciertamente las metaheurísticas que vi y use para hacer data clustering en mi tesis están en el rumbo correcto. Ya la programación normal no se de abasto. Pensar en paralelización y formas para manejar cantidades gigantes de datos es el futuro. Es la era de la información y hay que saber como explotar y sacar todo lo posible de los datos. Ya veremos como siguen las cosas, mientras a conocer un poco de estas cosas.

Python

En lo que estaba haciendo me vi en la necesidad de hacer request a MySQL, a páginas web, mandar correos, hacer gráficas, entre otras cosas. Todo lo hice mediante Python y ciertos bash para ayudarme.

Request a páginas web

Use lo siguiente: http://docs.python-requests.org/en/latest/. La libreria urllib2 es muy buena y es posible que no halla tenido que usar esta, pero en verdad fue lo que me salió más rápido y conseguí de primero.

Hacer una petición POST es así de tonto:

import requests
    result = request.post(url, params = parametros[, cookies = ....])

Si queremos que sea una petición GET, siemplemente se cambie la palabra. Por ejemplo si queremos atentificarnos en una página y luego sacar información el script sería algo así:

import request

auth_cookies = None
def login():
    request_result = requests.post(url, params = {'username' : usuario, 'password' : clave})
    request_result.raise_for_status()
    global auth_cookies
    auth_cookies = request_result.cookies

def get_information():
    request_result = requests.get(url', params = ..., cookies = auth_cookies)
    request_result.raise_for_status()
    #En request.text esta el resultado, lo parseamos o buscamos lo que necesitamos de acá

if __name__ == "__main__":
    login()
    get_info()
    ....

Así de fácil.

Mandar email

Lo saque de internet y le comenté ciertas cosas que no me agarranon bien:

import os
import smtplib
import mimetypes
from email.MIMEMultipart import MIMEMultipart
from email.MIMEBase import MIMEBase
from email.MIMEText import MIMEText
from email.MIMEAudio import MIMEAudio
from email.MIMEImage import MIMEImage
from email.Encoders import encode_base64
from sys import argv

def sendMail(subject, text, *attachmentFilePaths):
    gmailUser = ''
    gmailPassword = ''
    recipient = ''
    msg = MIMEMultipart()
    msg['From'] = gmailUser
    msg['To'] = recipient
    msg['Subject'] = subject
    msg.attach(MIMEText(text))
    for attachmentFilePath in attachmentFilePaths:
        msg.attach(getAttachment(attachmentFilePath))
        mailServer = smtplib.SMTP('smtp.gmail.com', 587)
        mailServer.ehlo()
        mailServer.starttls()
        mailServer.ehlo()
        mailServer.login(gmailUser, gmailPassword)
        mailServer.sendmail(gmailUser, recipient, msg.as_string())
        mailServer.close()
       print('Email enviado a %s' % recipient)

def getAttachment(attachmentFilePath):
    contentType, encoding = mimetypes.guess_type(attachmentFilePath)
    if contentType is None or encoding is not None:
    contentType = 'application/octet-stream'
    mainType, subType = contentType.split('/', 1)
    file = open(attachmentFilePath, 'rb')
    '''
    if mainType == 'text':
        attachment = MIMEText(file.read())
    elif mainType == 'message':
        attachment = email.message_from_file(file)
    elif mainType == 'image':
        attachment = MIMEImage(file.read(),_subType=subType)
    elif mainType == 'audio':
        attachment = MIMEAudio(file.read(),_subType=subType)
    else:
    '''
    attachment = MIMEBase(mainType, subType)
    attachment.set_payload(file.read())
    encode_base64(attachment)
    file.close()
    attachment.add_header('Content-Disposition', 'attachment', filename=os.path.basename(attachmentFilePath))
    return attachment
 

Mandarlo es simplemente completar las variables y usar las funciones como uno desee.

Como vamos

Primero comentare del pasado domingo brevemente:

No hubo fraude, simplemente tenemos una mayoría en el país que fue exluida por 40 años y ahora que le dan migajas de esperanzas, dan su voto por la mediocridad. Un cambio es necesario y es hora de una política seria.

Desde hace que no posteo nada, he estado ajustado de tiempo. Las cosas que han pasado:

  • Ya no ando programando en asp.NET (use MVC 3.0 con VB y 2.0 con C#)
  • Lo del artículo va en camino de tortuga.
  • Ahora ando en un proyecto de investigación, donde he tenido que usar Java, Python, bash y SQL.
  • Me compre un Nexus 7 y unos audífonos. Excelente hasta ahora, 100% recomendables.
  • asp.net MVC >= 3.0 no tiene nada que envidiarle a otro frameworks. Es facil de usar y de programar. En mi caso use el EntityFramework para manejar la parte del modelo. Es bastante configurable y permite usar stored procedures. Ésto último es muy buena práctica. IIS lo poco que tuve que tocar, me pareció bueno. Mis quejas serían tener que pagar por algo que se puede tener gratis igual o mejor (RoR, Django) y la documentación no es tan buena en comparación con las cosas que son open source.
  • Team Fundation y svn, son un asco al lado de git. Gracias Linus Trovalds.
  • Como escribí antes me encanta Python, lástima que lo conocí y aprendí tarde. Es bastante legible y poderoso. Ando seguro que Perl es muy usado y posiblemente más poderoso, pero odio los $ (si odio php).
  • Es increíble la cantidad de herramientas que existen hoy en día. Ejempo son hadoop, pig, oozie, que otros en el trabajo andan usando.
  • Con respecto al anime, me leí gran parte de las novelas de Sword Art Online. Muy buenas. Salió una ova de Code Gueass.
  • Me puse a ver Breaking Bad. Voy terminando la 3era temporada. Que serie tan buena. Tiene unas partes que te mantienen pegado, pero debo decir que a veces se pone algo calmada y lenta. Ya veremos como sigue.

A ver si tengo cosas más interesantes que colocar, ya veremos.

XSRF Django

En la web uno se debe cuidar de tres cosas (y muchas otras, pero de las principales y más comunes para mí) son: inyecciones SQL, XSS y XSRF.

La primera como dice el nombre es simplemente a través de llamadas HTTP ingresar código de SQL (esto puede aplicar a otro tipo de bases de datos No-SQL). La forma más común es a la hora de un formulario por el cual se pasan datos bien sea por POST o GET, colocar valores estílo ‘; comando sql;  por medio del cual se pueden robar valores, dañar la base datos, etc.

Luego tenemos los XSS, siglas de cross-site scripting, lo cual es ingresar código en la página que se ataca. Ejemplo un párametro que se pasa por GET y que se imprime en la página. Con poner en ese parámetro algo estilo < iframe src = “http://paginamaliciosa” > </ iframe >  se logra que otras personas vean lo que uno desee y se puede robar información u otras cosas.

Finalmente tenemos el XSRF, siglas de cross-site request forergy. Éste ataque es más complejo, pero puede hacer mucho daño. Consiste en hacer que un usuario autentificado en una página haga cosas que él no autorizo. Un ejemplo sería el siguiente:

  • Un usuario anda autentificado en X página, la cual hace el cambio de contraseña por POST.
  • Una persona maliciosa simplemente debe recrear ese request de POST y hacer que el usuario lo haga sin darse cuenta.

Yo ya en un post pasado publique un link (http://google-gruyere.appspot.com/) que encontré muy bueno que habla de seguridad de páginas web y que explican de estos ataques y como defenderse.

Hable de todo ésto ya que me topé con lo siguiente:

https://docs.djangoproject.com/en/dev/ref/contrib/csrf/

Cada día me sorprendo más con lo excelente que es este framework, al igual que Python.

De un modo bastante simple previsto por Django se es posible defenderse de éste último tipo de ataque que comente. No soy un experto de en programación web, nunca me ha gustado, pero me pregunto si muchos de los otros frameworks tienen está capacidad.

Fuera del tema, ya empezó el curso de seguridad ofrecido por la universidad de Standford, espero poder dedicarle, ya vi por encima el material que colocaron y se ve full interesante, espero tener el tiempo y las ganas de leerlo, ya veremos!