Surprise from Python on new years eve, 2016

Alright, so another usual night and I was trying to figure out a strange behavior with a Python class I was working. Looks like I had OOP lectures only in C++, and things are little bit different here. So here you go!

I had this strange class method here described as:

class BenchmarkResults(object):

    def _generate_db_entries(cls, tests, skip_aggregated=False, parent=None, test_table = []):
         # This function recursively calls _generate_db_entries with
         # test_table param set to a list 

and this was processing in a JSON file from one of my POST API and doing some crazy stuff. The API calls this class like

class BotReportView(APIView):
    def post(self, request, format=None):
        test_data_results = BenchmarkResults(json.load(self.request.FILES.get('test_data')))
        results_table = test_data_results._generate_db_entries(test_data_results)

Now the funny part. I found that on subsequent calls to the API, the test_data_results kept on multiplying 😮 like the data from the previous POST also got appended to the current JSON which-should-be-processed. Thinking it was a problem with the client, I tried switching to curl, but with little luck.

The problem
Finally pycharm got me figuring out what went wrong, as it showed a warning on the test_table = [] something like:
The default method argument is mutable. Bah, taking at look at I see that when an empty list [] is kept as a default formal argument for a function, the list is not killed in between, and keeps on growing on subsequent calls – surprise :\

Quoting, when we have something like:

def status(options=[]):
    return options

print status()
print status()
print status()

will print something like

['new_option', 'new_option']
['new_option', 'new_option', 'new_option']

Tough luck finding it out, but it took couple of hours 😀 I got my code easily fixed by not allowing [] to stay as a default param, but separately passing an empty list to the function during the call. Like

class BenchmarkResults(object):

    def _generate_db_entries_helper(cls, tests, skip_aggregated=False, parent=None):
        test_table = []
        self._generate_db_entries(cls, tests, test_tables skip_aggregated=False, parent=None):

    def _generate_db_entries(cls, tests, test_table, skip_aggregated=False, parent=None):
         # This function recursively calls _generate_db_entries with test_table param set to a list 

Yay. that was it, and latter called in the helper function, and things started working. You can see the change here, and finally, Happy New year 2017! Make every commit count!

[Angular JS] Setting a combobox based on selection of another one

This might be my first post which touch Angular JS, and wanted to let you guys know that I too joined the backend to frontend club! Currently Angular JS is powering with Django REST at the backend – and I think its super fast, easy to develop and allows for a cleam responsive UI – WOW is the word.

You have a data model, which looks something like:

bots = [{ 'bot1' : {'platform': "Linux", id:1}}, { 'bot2' : {'platform': "Windows", id:2}}];
platforms = [{ 'name' :'Linux', 'id' :1},{ 'name' :'Windows', 'id' :2}, { 'name' :'MacOSuX', 'id' :3}];     

You have a select box bots and another select box Platforms and you need the following logic to happen:

  1. When no bot is selected,the Platforms combo should show All all the platform options
  2. When a bot is selected, it should force the Platform combo to show the platform property of bot selected, and should disable them to make no further changes.

You will need the following Angular script to make this work. Add this to your scripts.js or wherever place and include it in your html file.

app.controller('AppController', function($scope) {
    $scope.bots = [{ 'name': 'bot1', 'platform': "Linux", id:1}, { 'name': 'bot2', 'platform': "Windows", id:2}];
    $scope.platforms = [{ 'name' :'Linux', 'id' :1},{ 'name' :'Windows', 'id' :2}, { 'name' :'MacOSuX', 'id' :3}];     

see that you can even add this directly to the html file with the tag. Now you can add the following to the HTML file so that the data gets correctly rendered to the browser.

<div class="form-group">
  <label for="bot">Bot</label>
  <select name="bot" class="form-control" ng-model="selectedBot"
	  ng-options=" for bot in bots">
      <option value="">--All bots--</option>
<div class="form-group">
  <label for="platform">Platform</label>
  <select name="platform" class="form-control" ng-model="selectedPlatform" ng-disabled="selectedBot">
      <option value="">--All platforms--</option>
      <option ng-repeat="x in platforms" value="{{ }}">{{ }}</option>
      <option value="{{ selectedBot.platform }}" ng-selected="selectedBot" ng-show="selectedBot">
	  {{ selectedBot.platform }}</option>

How it works?

  • The {{ }} makes sure that all the platforms are shown initially making sure our condition (1) above.
  • The {{ selectedBot.platform }} makes sure that when the bot select is clicked, this option value is set for the combo box – adding to (2) above.
  • The ng-selected="selectedBot" ng-show="selectedBot" makes sure that the combo gets disabled when someone selects in some value for bots contributing to (2) above
  • You can see the dropdowns live in action at and do take a look and comment if something seems weird.

    Update: It seems like there was a problem with this approach as the selectedPlatform is not getting set correctly, even though the combo gets set. You can fix this by
    adding in the following action on ng-change on the select combo

    <select name="bot" class="form-control" ng-model="selectedBot"
          ng-options=" for bot in bots" ng-change="updateOtherCombos()">
      <option value="">--All bots--</option>

    and now defining the function updateOtherCombos() to your controllers.js

    app.controller('AppController', function($scope) {
        $scope.bots = [{ 'name': 'bot1', 'platform': "Linux", id:1}, { 'name': 'bot2', 'platform': "Windows", id:2}];
        $scope.platforms = [{ 'name' :'Linux', 'id' :1},{ 'name' :'Windows', 'id' :2}, { 'name' :'MacOSuX', 'id' :3}];     
        $scope.updateOtherCombos = function () {
          if ( $scope.selectedBot ) {
    	  $scope.selectedPlatform = $scope.selectedBot.platform;
    	  $scope.selectedCPU = $scope.selectedBot.cpu;
    	  $scope.selectedGPU = $scope.selectedBot.gpu;

API custom authentication with django-rest-framework

Long time since I blogged about anything in here! This time I am working on building a python-django powered dashboard for browser test result analysis with Igalia, and came across this the frist day! Let me get into this straight, following my usual template of blog posts

You have a default User login model, but have some bot POSTing at say yourwebsite/bot-api. Your bot has its own authentication details sent as parameters in the POST as

{bot_name: fooboot, password: bar}

and you want to authenticate this from a Bot model in your django application, and make sure that this thing go throgh only after a green flag.

The best method here is to write a custom authentication in your which would look like

from rest_framework import authentication
from your_models import Bot 

class BotAuthentication(authentication.BaseAuthentication):
    def authenticate(self, request):
        bot_name = request.POST.get('bot_name')
        bot_password = request.POST.get('password')

        if not bot_name or not bot_password:
            return None

            bot = Bot.objects.get(name=bot_name)
        # If you have some other methods to auth, use here
        if bot.password != bot_password:
                return None
        except Bot.DoesNotExist:
            raise exceptions.AuthenticationFailed('The bot failed to authenticate')

        return (bot, None)

and you can directly use this in your ApiView which should be ran on recieving a hit on the API.

from django.http import HttpResponse
from rest_framework.views import APIView
from rest_framework import authentication, permissions

class BotReportView(APIView):
    authentication_classes = (BotAuthentication,)
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)

    def post(self, request, format=None):
         return HttpResponse("If it reached here, the bot was authenticated = yay")

Well. There are issues with using such a plain-text authentication, and doing a 1:1 password comparison. In real world, you might want to use django password field and authentication functions to compute hash of the recieved password, and compare with the one in the database table.

Hope this helps!

Reflecting changes in your python web-app without restarting apache

This would be a pretty simple hack, and concern the devs using python web frameworks – hosted with apache-wsgi. The Django help to deploy a web-app on the apache server can be found over here[1].
In either way, you will have your apache configuration pointing to the path of the wsgi file of your web-app. You will have something similar to the following in your apache conf.

WSGIScriptAlias /mysite  /path/to/your/application.wsgi

Now – problem come when you have made some local changes to your repo, and do not have sudo privilege to restart your webserver to make the changes take effect. You can fix the same with this simple hack.

$ touch /path/to/your/application.wsgi

touch command[2] in GNU/Linux can do wonders! It can create a new file ( if not exist ), and can refresh the timestamp if one exists.