Entry Script (index) like module in Python

Many times we need to pass config file to our python modules. And sometimes we forget that. If we have multiple environments, we may end up passing wrong paths.

In web it gets easier! We have an entry script (index.php file). It is the only file a web user has access to. Depending upon your environment, it takes you to the correct config file path.

#!/usr/bin/python
import os
import sys
ENVIRONMENT = "development"
CONFIGFILE = None

def getConfigFileForEnv():
    directory = os.path.dirname(__file__)
    return {
        "development" : "%s/../config/development.cfg" % directory,
        "staging" : "%s/../config/staging.cfg" % directory,
        "production" : "%s/../config/production.cfg" % directory
    }.get(ENVIRONMENT, None)

CONFIGFILE = getConfigFileForEnv()
if CONFIGFILE is None:
    sys.exit("Configuration error! Unknown environment set. \
              Edit configurations.py and set appropriate environment")
print "CONFIGFILE : %s" % CONFIGFILE
if not os.path.exists(CONFIGFILE):
    sys.exit("Configuration error! Config file does not exist")
print "configurations ok ......"

Suppose your module is called main.py. Just import above entryscript.py in it and use entryscript.CONFIGFILE. The entry script itself validates config file path so you don’t have to do the same in main.py

#!/usr/bin/python
import entryscript
class Main:
    def __init__(self, configFile):
        pass

    def process(self):
        print "ok"

if __name__ == "__main__":
    m = Main(entryscript.CONFIGFILE)
    m.process()

So when you run main.py and the environment is wrong / config file doesn’t exist, you will get an error in entryscript.py itself.

If you put the code from entryscript.py in __init__.py, you don’t have to import anything in main.py. That’s much better!

 

The right Ajax code for Edit, Cancel and Save feature

Many times we come across Edit-Cancel-Save kind of scenarios. And sometimes we end up writing bad but functioning code. The code / solution works so we don’t bother checking if the code is right.

I tried, I wrote, This is as right as I could get.

<span id="spanId" style="float:left;"> Guest </span>&nbsp;
<input type="text" id="inputField" style="display:none;">
<input type="submit" value="Edit" id="editButton" onclick="editIt();" />
<input type="submit" value="Save" id="saveButton" style="display:none;" onclick="saveIt(this);">
<input type="submit" value="Cancel" id="cancelButton" style="display:none;" onclick="cancelIt(this);">
<script src="http://code.jquery.com/jquery-latest.min.js"
type="text/javascript"></script>
<script type="text/javascript">
window.cancelIt = function(elm) {
    $('#saveButton').hide();
    $('#editButton').show();
    $(elm).hide();
    $('#inputField').hide();
    $('#spanId').show();
}
window.editIt = function() {
    $('#saveButton').show();
    $('#cancelButton').show();
    $('#inputField').show();
    $('#editButton').hide();
}

window.saveIt = function (elm) {
    var params = {
        'key': 'value'
    };
    $.post("controller/action", params, function (data) {
        // success
        // status: 2xx and 3xx
        // client provided a valid input
        if (input in validInputs) {
            // set output corresponding to the valid input
            $('#spanId').html(output);
        } else {
            $("#spanId").html("Invalid ");
        }
    }).fail(function (err, status) {
        // error 4xx : client side errors (e.g. controller/action or url does not exist)
        // error 5xx : server side errors (e.g. db query failure)
        $("#spanId").html("Error ");
    }).always(function () {
        $('#saveButton').hide();
        $('#cancelButton').hide();
        $(elm).hide();
        $('#editButton').show();
        $('#inputField').hide();
        $('#spanId').show();
    });
}
</script>

I used to completely miss out the fail case. I didn’t know about always function, so I used put the whole code in the success callback function only.

You can checkout the demo on jsfiddle from here. You can also fork it as a gist from here.

Let me know if it’s still not right :)

The right way to write PHP arrays to log files and then read it.

How can we log PHP arrays in log files?

$arr = array(
     'name' => 'the_dark_knight',
     'userId' => 'test',
     'status' => 'fail',
);

The traditional method

#I used to do:-
foreach ($arr as $key=>$value) {
   log_message('INFO', "param: $key = $value");
}

#But what if the array is:-
$arr = array(
   'id' => '123232dkfkd',
   array(
     'name' => 'the_dark_knight',
     'userId' => 'test',
     'status' => 'fail',
     'data' => array('key'=>'test'),
   ),
);

You can guess how much code you have to write for this thing?

But you can do this the easy way

log_message('INFO', "data : " . print_r($arr, true));

Elaboration

print_r($arr, true) returns string. So this way, we can write the whole array in a log file. Remember, we used to run a for loop to print $_POST params. This way you just have to do log_message(‘INFO’, “POST data : ” . print_r($_POST, true)); It will also handle nested arrays.

Now my problem is

1. tail -f log-2014-04-01

INFO  - 2014-04-01 18:17:11 --> data : Array
(
    [name] => the_dark_knight
    [userId] => test
)

which is fine. But
2. cat log-2014-04-01 | grep 18:17:11
INFO  - 2014-04-01 18:17:11 --> data : Array

How do I get the output from case-1 in case-2?

Solution

cat log-2014-04-01.php | grep -A 4 18:17:11

Reference

man(grep)
-A NUM, --after-context=NUM
              Print NUM lines of trailing context after matching lines.  Places a line containing a group separator (--)  between  contiguous  groups  of  matches.
              With the -o or --only-matching option, this has no effect and a warning is given.

 

Calendar in PHP

I have been thinking about implementing a Calendar in PHP for some time now. It is very surprising how it has taken me 2 days to do it.

I don’t know if this is already a been there done that kind of thing. But it is a pretty cool!

The PHP code for Calendar: 2014


<?php

$year = '2014';
$start = date("$year-01-01");
$end = date("$year-12-t");

$week = array();
$month = array();
$i = 0;
print_r("Calendar: $year\n\n");
do {
	$week['start'] = $start;
	$date = strtotime($start);
	$d = date("D", $date);
	if ($d == "Sat")
		$weekend = $date;
	else if ($d == "Sun")
		$weekend = strtotime($start . " +6 days");
	else{
		$weekend = strtotime($start . " next saturday");
	}
	$weekend = date("Y-m-d", $weekend);
	$week['end'] = $weekend;
	array_push($month, $week);
	$start = strtotime($weekend . " +1 days");
	$start = date("Y-m-d", $start);
	$i++;
} while(strtotime($start) <= strtotime($end));

$month[$i - 1]['end'] = $end;
//print_r($month);

foreach ($month as $week) {
	$start = $week['start'];
	$end = $week['end'];
	$begin = new DateTime($start);
	$end = strtotime($end . " +1 days");
	$end = new DateTime(date("Y-m-d", $end));
	$interval = DateInterval::createFromDateString('1 day');
	$period = new DatePeriod($begin, $interval, $end);
	$d = date('D', strtotime($start));
	if ($d != 'Sun') {
		$day = strtotime($start);
		$lastSun = strtotime($start . ' last sunday');
		$datediff = $day - $lastSun;
		$difference = floor($datediff/(60*60*24));
		echo str_repeat('   ', $difference);
	}
	foreach ($period as $dt) {
		$day = $dt->format("d");
		print $day . " ";
	}
	print "\n";
}

And here we go :-

Calendar: 2014

         01 02 03 04 
05 06 07 08 09 10 11 
12 13 14 15 16 17 18 
19 20 21 22 23 24 25 
26 27 28 29 30 31 01 
02 03 04 05 06 07 08 
09 10 11 12 13 14 15 
16 17 18 19 20 21 22 
23 24 25 26 27 28 01 
02 03 04 05 06 07 08 
09 10 11 12 13 14 15 
16 17 18 19 20 21 22 
23 24 25 26 27 28 29 
30 31 01 02 03 04 05 
06 07 08 09 10 11 12 
13 14 15 16 17 18 19 
20 21 22 23 24 25 26 
27 28 29 30 01 02 03 
04 05 06 07 08 09 10 
11 12 13 14 15 16 17 
18 19 20 21 22 23 24 
25 26 27 28 29 30 31 
01 02 03 04 05 06 07 
08 09 10 11 12 13 14 
15 16 17 18 19 20 21 
22 23 24 25 26 27 28 
29 30 01 02 03 04 05 
06 07 08 09 10 11 12 
13 14 15 16 17 18 19 
20 21 22 23 24 25 26 
27 28 29 30 31 01 02 
03 04 05 06 07 08 09 
10 11 12 13 14 15 16 
17 18 19 20 21 22 23 
24 25 26 27 28 29 30 
31 01 02 03 04 05 06 
07 08 09 10 11 12 13 
14 15 16 17 18 19 20 
21 22 23 24 25 26 27 
28 29 30 01 02 03 04 
05 06 07 08 09 10 11 
12 13 14 15 16 17 18 
19 20 21 22 23 24 25 
26 27 28 29 30 31 01 
02 03 04 05 06 07 08 
09 10 11 12 13 14 15 
16 17 18 19 20 21 22 
23 24 25 26 27 28 29 
30 01 02 03 04 05 06 
07 08 09 10 11 12 13 
14 15 16 17 18 19 20 
21 22 23 24 25 26 27 
28 29 30 31 

I know this can be improved. But I am a bit impatient. I couldn’t wait more :)

Actually this will find much better use in web. Above implementation was executed on PHP’s command line interface (cli)

Please do let me know what you think.

Comparison of svn and git commands

I have been using both svn and git for some time. I haven’t noticed any difference in functionality as of now.  I didn’t choose one over the other for that matter.

Apparently there is a lot much difference between them and people have been doing debates over which one’s better. [1] [2]

But let’s not get into that. Let’s help people use one if they already know the other one. I’ll show you commands from svn and equivalent commands from git.

If you also know github, it will be much more easier to relate equivalent commands of svn and git.

svn git
svn checkout url git clone <repo.git URL>
svn add <file/dir> git add <file/dir>
svn commit [-m "msg"] <file/dir> git commit [-m “msg”] <file/dir>
svn up git push # on gitbub repo
svn up git pull # on working copy
svn list git remote
svn import path/url git init [path/url]
svn log [path/url] git log [path/url]

I hope you found what you were looking for!

Most important svn (subversion) commands

Subversion is a revision control system distributed under an open source license used for software version control.
Explaining about why to use svn is not the point here. Let’s just leave it to wiki.
Suppose http://10.1.0.1/svn/Repo is the location of your repository. Instead of writing this whole url, I’ll write URL. A working copy will be a local copy of this repository at URL. Let’s call the path to the working copy as PWC


1. checkout / co

: Checkout a working copy from a repository.

svn checkout URL PWC
Now, you will have your own working copy of the repo. If path of working copy is not given then the base name of the repository will be created in present working dir. It basically creates a working copy for the user. It is one time thing.


2. import

: Commit an unversioned file or tree into the repository. The Repo/ need not exist before you import into it.


svn import PWC URL

After importing data, note that the original tree is not under version control. To start working, you still need to svn checkout a fresh working copy of the tree.


3. commit / ci

: commit send changes from your working copy to the repository.


svn commit PWC

svn commit -m "comment" PWC

If you are in the working copy, you can commit the present working directory like svn commit. The commit message is just optional.


4. update / up

: update brings changes from repository into working copy. If revision is not specified, it makes the working copy up to date.

To update whole working copy go there and type in


svn update

You can even update a specific file like


svn update [filepath from PWC]

Also you can update the particular file from your working copy to it’s any version like


svn update -r  [filepath from PWC]


5. add

: add files and directories to the working copy. They will be uploaded and added to the repo when you commit the changes.


svn add

and then


svn commit [file or dir path from PWC]


6. delete / del / remove / rm

: delete an item from working copy or the repository.


svn delete < file / dir path from PWC > / <  file / dir path from URL >

and then


svn commit [PWC]


7. info

: info displays information about a local or remote item. Go to the repository and type


svn info


8. list / ls

: list items of the repository.


svn list [URL]


9. status

: status recursively lists all the modified, deleted, added files. Go to the working copy and type in

svn status

10. resolved

: resolve  the conflicts in a file


svn resolved [file path from PWC]


11. relocate

: relocate will let you relocate your repo to some other location


svn switch --relocate OLD_URL  NEW_URL


12. log

: log will give you history of the revisions. It displays the user who has modified that version along with the message of revision. i.e. Message telling what the changes are done.


svn log [path of the file in your working copy]

To limit this log upto some number of entries then use it like


svn log -l <number of entries> <path of the file in your working copy>


13. resolve

: resolving tree conflicts can be a headache. Not anymore.


svn resolve --accept working -R


14. if it says “file is out of date” / “remains in tree-conflict”

If you get errors like “file is out of date” or “remains in tree-conflict” while commiting your changes, type in
svn update
svn resolved <path of the directory in conflict>
svn commit
This covers all the important svn commands. svn done.

Spinners in Shell and Python

Spinners are helpful when you want to get the feel of progress on command prompt. Is this complex to code? No!

The basic idea is some chars periodically. So this can be done in any language. Here is how I did it in shell.

echo "processing.." 
while true ; 
do 
for i in \| \/ \- \\ 
do 
echo -e "\b\b$i \c" 
sleep 0.5 
done 
done 

In python -

from sys import stdout, exit
from time import sleep

def showProgressSpinner():
        l = ['|', '/', '-', '\\']
        while 1:
                for i in l:
                        stdout.flush()
                        stdout.write(i)
                        stdout.write('\r')
                        sleep(0.2)

try:
        showProgressSpinner()
except KeyboardInterrupt, ki:
        exit("Process terminated intentionally with CTRL-C")

voila!