Running Standalone SQLAlchemy Scripts in Pyramid

From time to time there comes the need to run automated scripts managed by either Python or Cron. In a recent project I had to run a standalone script that checks records on a database at certain hours. So here’s what I came up with. Most of the script is based on this post by Daniel Mayer.

from paste.deploy import appconfig
 
from sqlalchemy import engine_from_config
 
from sqlalchemy.orm.exc import NoResultFound, MultipleResultsFound
 
#here is where sqlalchemy objects are imported
from PRJ.models import DBSession as db,DBRecords
 
#import the session manager. This way commits will be handled automatically by the Zope Transaction Manager
import transaction
 
# Load Application Configuration and Return as Dictionary
conf = appconfig('config:' + 'development.ini', 
        relative_to="/var/www/PRJ",
        name="main")
 
# Bind Engine Based on Config
engine = engine_from_config(conf, 'sqlalchemy.')
db.configure(bind=engine)
 
#Query the DB
data = db.query(DBRecords).one()
 
with transaction.manager:
  for record in data:
    #query or update DB

Facebook FQL Request Error

Today while attempting to query Events data through FQL, I received the following error:

Impersonated access tokens can only be used with the Graph API.

It was a strange error since I had already created my access token with the right scope. To query the data I’m using the pythonforfacebook SDK which uses https://api.facebook.com/method/fql.query as the url for FQL requests (REST API).

I then tried the graph method (https://graph.facebook.com/fql) which worked perfectly, but the response didn’t include Event pictures and I really need pictures to be present on my events listings. So what worked for me was to make a GET request thought the Graph API instead of a POST.

I use Requests for this so the code is very simple.

data = db.query(Model) #retrieve my access_token from DB
payload = {'q' : query, 'access_token': data.access_token,'format' : 'json'}
res = requests.get('https://graph.facebook.com/fql', params=payload)

With this change everything worked as expected.

Simpleform Localization in Pyramid

In a recent project I had to localize the errors thrown by the pyramid_simpleform package. Googling for information I couldn’t find how to do it, so here’s what worked for me at the end.

  from pyramid.i18n import get_locale_name
  from pyramid_simpleform import Form,State
 
  from formencode import api as formencode_api
 
  def includeme(config):
    config.scan(__name__)
    config.add_route('login', '/login')
 
  @view_config(route_name='login',renderer='website/login.mak')
  def login(request):
     """
     set the language in FormEncode according to the request url param _LOCALE_
     """
     formencode_api.set_stdtranslation(languages=[get_locale_name(request)])
     form = Form(request,
           defaults=dict(request.params),
           schema=MySchema,
           state=State()
     )
     """
     set an empty gettext translation function,
     since FormEncode has one already
     configured in the set_stdtranslation function
     """
     form.state._ = ''
     return dict(renderer=FormRenderer(form))

And that’s it, try it for example http://mysite.com/login?_LOCALE_=fr. Make sure the action param in your form passes the _LOCALE_ value if the method is set to post.

Manage cron jobs with python-crontab

Cron is the main time based scheduler for any linux based system and is available in almost every distro. And in a recent project I had the task to manage jobs in cron from python. Searching for a good cron manager I came across python-crontab. It makes it really easy to manage jobs directly from cron, here are some examples:

NOTE: This examples used version 0.9.6, there’s a new version available 1.2 on pypi along with some examples, the main difference is that the API has been changed from slice calls to be properties instead of methods.

Installing python-crontab is easy as pie. First we install our virtual enviroment:

cd /var/www
python virtualenv.py --no-site-packages prj-env
cd prj-env
bin/activate

Then we proceed to install python-crontab

pip install python-crontab 
or
easy_install python-crontab

Let’s schedule a job to be executed everyday at 12pm

from crontab import CronTab
 
"""
Here the object can take two parameters one for setting 
the user cron jobs, it defaults to the current user 
executing the script if ommited. The fake_tab parameter 
sets a testing variable. So you can print what could be 
written to the file onscreen instead or writting directly
into the crontab file. 
"""
tab = CronTab(user='www',fake_tab='True')
cmd = '/var/www/pjr-env/bin/python /var/www/PRJ/job.py'
# You can even set a comment for this command
cron_job = tab.new(cmd, comment='This is the main command')
cron_job.minute().on(0)
cron_job.hour().on(12)
#writes content to crontab
tab.write()
print tab.render()

It will print out

0 12 * * * /var/www/pjr-env/bin/python /var/www/PRJ/job.py

If we want to schedule a job to be executed every five minutes we could do something like this

 
from crontab import CronTab
 
tab = CronTab(user='www',fake_tab='True')
cmd = '/var/www/pjr-env/bin/python /var/www/PRJ/job.py'
cron_job = tab.new(cmd)
cron_job.minute().every(5)
#writes content to crontab
tab.write()
print tab.render()

It will print out

*/5 * * * * /var/www/pjr-env/bin/python /var/www/PRJ/job.py

If we want to schedule a job for a specific range of hours for example only working hours, we could do the following

from crontab import CronTab
 
tab = CronTab(user='www',fake_tab='True')
cmd = '/var/www/pjr-env/bin/python /var/www/PRJ/job.py'
cron_job = tab.new(cmd)
cron_job.minute().on(0)
cron_job.hour().during(09,18)
#writes content to crontab
tab.write()
print tab.render()

It will print out

0 09-18 * * * /var/www/pjr-env/bin/python /var/www/PRJ/job.py

Now to schedule a job to run twice a day at 11 and 16 hrs, we could do the following

from crontab import CronTab
 
tab = CronTab(user='www',fake_tab='True')
cmd = '/var/www/pjr-env/bin/python /var/www/PRJ/job.py'
cron_job = tab.new(cmd)
cron_job.minute().on(0)
cron_job.hour().on('11,16')
 
#writes content to crontab
tab.write()
print tab.render()

it will print out

0 11,16 * * * /var/www/pjr-env/bin/python /var/www/PRJ/job.py

Let’s delete the previous command

from crontab import CronTab
cmd = '/var/www/pjr-env/bin/python /var/www/PRJ/job.py'
tab = CronTab(user='www',fake_tab='True')
 
cron_job = tab.find_command(cmd)
if len(cron_job) > 0:
    tab.remove_all(cmd) 
#writes content to crontab
tab.write()

So there you have it, examples that make python-crontab a great python manager for cron jobs. Now I know there are pure Python implementations like this, an event scheduler named sched and libraries like Kronos. But I decided to keep things simple.

Hey Facebook, your help support center is crap.

It’s been almost a month since a friend of mine had her account “Temporarily deactivated”, now here the word temporarily is misleading because she hasn’t recovered her account yet. The worst part is that Facebook doesn’t tell her why the account was blocked. After many hours we came to the conclusion that maybe a jealous friend might have reported her account.

Now can you imagine if she also had a paying subscription to one of those online services that have Facebook based auth logins only?, now she could also be losing money because of this.

So she tried to have Facebook send her a code to a cellphone but their system didn’t sent shit. We live in México so maybe our cellphone carrier is not supported, but do Facebook cares to let you know that?, of course not. So after a few tries for a couple of days Facebook now just shows a message which says “The system is overloaded”. Overloaded with what!?, fuck this is just so frustrating because that message is the only thing that appears from now on.

After a long period of time she received an email from Facebook but it didn’t help at all, they didn’t give any info on why her account was blocked or anything they just sent her a link to the same page where you tell Facebook to send you a code.

The worst thing of all this is that Facebook has top notch engineers working for them, why not try to improve the help support center?. Oh no they can’t they are too busy developing all those innovating features right?.

The good thing is that now I know how to deactivate my account in just one simple step. Just tell a friend to report your profile and Facebook will not give a fuck and deactivate your account for you without a notice. This way you won’t have to receive those fucking emails from them trying to convince you to come back and activate your account.

Facebook please get your shit together. This mechanism of recovering your account is unfriendly, inhuman, it frustrates users and leads to posts like this one. My friend since then has been feeling sad, desperate and depress from all this, it saddens me to see her like this.

Setup The Newrelic Monitoring Agent On A Pylons App

Today I decide to signup for a free trial of the newrelic monitoring agent and I wanted to write on how to setup the agent on a Pylons app.

EDIT: Commenter Graham Dumpleton has advised against this setup in the comments. There’s the potential risk of the agent initializing twice and additional modules not working correctly. So please don’t use this setup on a production app.

Open the middleware.py file located on PRJNAME/config and add the following. Make sure to set the correct path where your newrelic.ini file is located

#import the agent
import newrelic.agent
 
#create a middleware class to initialize the agent
class NewRelicAgent(object):
    def __init__(self, app):
        self.app = app
        newrelic.agent.initialize('/path/to/the/file/newrelic.ini')
 
    @newrelic.agent.wsgi_application()
    def __call__(self, environ, start_response):
        return self.app(environ, start_response)

Now it’s time to add our custom middleware inside the make_app def

# CUSTOM MIDDLEWARE HERE (filtered by error handling middlewares)
app = NewRelicAgent(app)

And that’s it. Now it’s time to collect some stats :) .

Facebook SDK For Python Deprecated

Yesterday Facebook without a notice or warning decided it to delete their SDK github repo for Python. Today the repo is back online but with a notice saying that they have no plans to update it anymore. I’ve been seeing this coming since they stop adding new features awhile ago. So anyways there’s an alternative that will help us continue developing applications for Facebook even without their official support.

The move of deleting the repo really took me by surprise. All I have to say is that I really feel frustrated with this company, because they have abandon the Python comunity.

UUID Objects in Pylons with SQLAlchemy

Recently I had to generate and store uuid objects into a Postgres database, but to my surprise SQLAlchemy kept showing the following error:

sqlalchemy.exc.ProgrammingError: (ProgrammingError) can't adapt type 'UUID'

So the solution was that I had to change my field type from varchar to uuid on my Postgres database, import the psycopg2 extras functions and register the uuid type:

import psycopg2.extras
import sqlalchemy
from sqlalchemy import create_engine
from sqlalchemy import MetaData,Column, Table, ForeignKey
 
engine = create_engine('postgresql://user:pass@localhost/db',echo=True)
metadata = MetaData(bind=engine)
hash_key = uuid.uuid4()
psycopg2.extras.register_uuid()
conn = engine.connect()
query = conn.execute("insert into tbl (uuid_col) values(%(uuid)s",uuid=hash_key)

And voila, values were inserted correctly on my database.

Implementing a text based captcha in Pylons

One of the must have elements on any html form as an anti-spam measure is a captcha, and the captcha technique that has worked pretty well for me is text based. So here’s how to implement one.

Create a controller and name it captcha

 ~$ paster controller captcha

Add this function to your helpers.py file

def makeCaptcha(lang):
      label = {
          1 : 'one',
          2 : 'two',
          3 : 'three',
          4 : 'four',
          5 : 'five',
          6 : 'six',
          7 : 'seven',
          8 : 'eight',
          9 : 'nine',
          10 : 'ten'
      }
      num1 = random.randint(1,10)
      num2 = random.randint(1,10)
      res = num1 + num2
      session['captcha'] = res
      session.save()
      return [label[num1],label[num2]]

On the templates folder create an html file with an example form

<form method="post" action="${url(controller='captcha',action='contact')}" id="contact-frm">
  <fieldset>
    <%
      capt = h.makeCaptcha()
      c.captcha =  u"What is the result of the sum %s and %s?." % (capt[0],capt[1])
    %>
    <span>${u"As an  anti spam measure, please answer the following math question."}</span><br />
    <label for="captcha">${c.captcha}</label>
    <!-- we set a maxlength of 2 characters on this input field because the answer should be numeric -->
    ${h.text('captcha',maxlength=2)}
 </fieldset>
</form>

Save it and call it captcha.html

Add the following to captcha controller

I decided to create a validation schema using formencode:

import formencode
 
from formencode import variabledecode
 
from formencode import validators
 
from formencode.validators import Invalid, FancyValidator
 
#this class will validate the captcha value entered by the user
class CaptchaValidator(formencode.FancyValidator):
    def _to_python(self,values,state):
        if session.get('captcha') != int(values.get('captcha')):
          raise formencode.Invalid(u"The math answer is incorrect",values, state)
          return values
 
class NewInquiry(formencode.Schema):
  allow_extra_fields = True
  filter_extra_field = True
  captcha = formencode.validators.String(
    not_empty = True,
    messages = {
      'empty' : 'You need to answer the math question.'
  })
  # chain the captcha validator
  chained_validators = [CaptchaValidator()]
 
# our contact view
def contact(self):
      if request.method == 'POST':
        try:
          values = dict(request.params)
          schema = NewInquiry()
          results = schema.to_python(values)
        except Invalid, e:
          #raise error if something went wrong
        else:
          #send to contacts
      return render('captcha.html')

And that’s pretty much it. The only drawback I can find is that isn’t very intuitive at times since users my try to answer with words instead of numeric values. That’s why I added a maxlength of 2 characters to the input field.

But you could easily implement a Javascript validation function to notify the user to type numeric values instead of characters before she submits the form.

HTML lists with jQuery for mobile devices

Recently I had to transform a group of li elements into an accordion for a mobile version of a client website. So this is what I came up with.

I had an html that looked like this

<ul>
<li><span>Category1</span>
  <ul>
    <li>Subcategory1</li>
    <li>Subcategory2</li>
  </ul>
</li>
<li><span>Category2</span>
  <ul>
    <li>Subcategory</li>
    <li>Subcategory1</li>
  </ul>
</li>
 
</ul>

And I wanted to collapse all the subcategories on load leaving only the categories visible and when they click/touched each category subcategories will expand. So I wrote this script based off from Sam Croft script.

(function($){
  $.fn.accordion = function() {
    var el = this;
    var catHeight;
    catHeight = new Array();
 
    el.find('.category ul').each(function(i){
      var category = $(this);
      catHeight[i] = category.height();
      category.addClass('closed')
 
    });
 
      el.find('.category-header ').bind('touchstart', function(e) {
        e.preventDefault();
        var toExpand = $(this).next('ul');
        var i = toExpand.index('li ul');
 
        if (toExpand.attr('id') == 'active') {
          toExpand
          .removeAttr('id')
          .removeAttr('style')
          .addClass('closed');
 
        } else {
        var active = $('#active')
 
        if (active.length > 0) {
          active
          .removeAttr('id')
          .removeAttr('style')
          .addClass('closed');
        }
 
        toExpand
        .attr('id', 'active')
        .css('height', catHeight[i]+'px')
        .removeClass('closed');
 
      }
  });
}
})(jQuery);

And with this script I had to modify my html lists to look like this

<ul class="list">
<li class="category"><a class="category-header" href="#">Category1</a>
  <ul>
    <li>Subcategory1</li>
    <li>Subcategory2</li>
  </ul>
</li>
<li class="category"><a class="category-header" href="#">Category2</a>
  <ul>
    <li>Subcategory</li>
    <li>Subcategory1</li>
  </ul>
</li>
 
</ul>

My css file

.closed {  height: 0; display:none;}
#active{display:block}

Usage

$(document).ready(function() {
  $('.list').accordion();
})

You can see a working example here.