New revision of redmine-cmd released

Yesterday, I decided spend some of my time in a tinny tool created for me one year and half ago. This tool was named redmine-cmd and, obviously, the purpose of this tool is the usage of the Redmine ticketing system directly from the console system but also auto-submit the time expended in each task automatically.

The tool was functional with Redmine <=1.2 until now but it didn’t implement all the API definition covered  by the latest versins of Redmine. The reason of that it was bacause the places where I was using this tool had not been upgraded to the latest version of Redmine for years. One of the consecuences of this was that many API/REST ending points was not be available for my tool in those early Redmine enviroments, therefore some relevant values related to a Redmine’s issue as the tracker id, the activity id or the issue status code wasn’t available to be obtained from the server causing, these restrictions,  weird things like the definition of  enumerators in the redmine-cmd configuration file with the same values that in the server.

 

redmine-cmd console example
redmine-cmd console example

But it’s a new time today, the time come down and the last Redmine with a version < 2.2 is not anymore  around me so,  yesterday, finally I decided end the integration with the Redmine API using the ending points required by my tool to get dinamically all the data required from the server:

The final implemantion is already available on PIP public repositories with MIT license to be used for everybody. The usage is quite trivial and the installation and setup steps are documented int the README file. Please, download and use it, any feedback will be welcome.

Extenal link: https://github.com/psaavedra/redmine-cmd

Mini-tip about Django templates

Django templates priority order

  • First, the TEMPLATE_DIRS dir setting in settings.py file of the project enviroment
  • Secondly, templates dir into de apps.
  • The last one is the propertly app which use this template

In addition templates used by admin gui or any other Django core module  can be overwritten in cascade. For example:

  • /usr/share/pyshared/django/contrib/admin/templates/admin/change_list_results.html
  • <app_dir>/templates/admin/change_list_results.html
  • <app_dir>/templates/admin/<lowercase_app_name>/change_list_results.html
  • <app_dir>/templates/admin/<lowercase_app_name>/<lowercase_model_name>/change_list_results.html

these templates are being replaced by the next one in order. That is, you can replace the template for a concrete template for a singular model of a specific application.

Disabling a site-wide action on Django

If you need to disable a site-wide action you can call AdminSite.disable_action().
admin.site.disable_action(‘delete_selected’) (See: Django reference guide)

… or

def get_actions(self, request):
  actions = super(ApplicationAdmin, self).get_actions(request)
  if 'delete_selected' in actions:
    del actions['delete_selected']
  return actions

, for a specific ModelAdmin.

Paramiko example

I have the pleasure of presenting a tip from the past. Today from long time ago: Paramiko.

import os
import paramiko
hostname="vps.doc.com"
username="admin"
password="password"
port=22
remotepath="/tmp/test"

ssh = paramiko.SSHClient()
ssh.load_host_keys(os.path.expanduser(os.path.join("~", ".ssh", "known_hosts")))
ssh.connect(hostname, port=port, username=str(username), password=str(password))
sftp = ssh.open_sftp()

remote_file = sftp.file(remotepath, "r")
remote_file.set_pipelined(True)
file_lines = remote_file.read()
return file_lines
file_lines = ...

sftp.open(remotepath, 'w').write(file_lines)
sftp.close()
ssh.close()

HTML tables sorter from Canada

I’m very fascinated by one JavaScript library that I’ve found recently. The purpose of this library is very simple: Making  HTML tables sortable.

The performance of sorting a table using this JavaScript library is much better than other table sorting strategies (for example, AJAX+JSON queries to server side).
The quiz of this library is that it  uses the quicksort (makes O(nlogn) comparisons to sort n items) algorithm.

Links:

– Project HomePage: http://www.terrill.ca/sorting/
– JavaScript library: http://www.terrill.ca/sorting/TSorter_1.js
– The example: http://www.terrill.ca/sorting/table_sort_example.php

Debian package guide: Latest Python policy

From a couple of days ago, I has been recycling my knowledge about Debian-Python packages. Debian 6.0 is currently next to be released and we’ll need effort to adapt many of own packages from etch to squeeze.

I’ve been following the Debian-Python mailling list from one year ago and I know many several troubles, changes or  improvements  which was occurred during this period.

As a brief resume, many things has changed: default Python interpreter for Debian 6.0,  the backend frameworks to build packages (CDBS with python-distutils.mk, Python-central or Python-support) …

All these changes have been discussed on Debian Wiki and have been formalized as the new Python Policy. This policy is already accessible on http://www.debian.org/doc/packaging-manuals/python-policy/.

CMD module: building a Command Line Interpreter using Python.

I’ve been searching documentation about build a Command Line Interpreter (CLI) from some time ago. My requirements were:

  • I was needed a command history
  • I was needed TAB auto-completion.
  • … a easy framework.

Against I could expect, I didn’t found a lot of information on Internet about this aim. So after some time searching documentation about it, I had some luck and I finally found some refers to cmd Python module (oh, what surprise!):

Next lines, show a simple example about how it work:

import cmd

class HelloWorld(cmd.Cmd):
    """Simple command processor example."""

    def do_greet(self, person):
        if person:
            print "hi,", person
        else:
            print 'hi'

    def help_greet(self):
        print '\n'.join([ 'greet [person]',
                           'Greet the named person',
                           ])

    def do_EOF(self, line):
        return True

if __name__ == '__main__':
    HelloWorld().cmdloop()

… and this is a example of use:

$ python cmd_do_help.py
(Cmd) help greet
greet [person]
Greet the named person

One extra reference:

CDM2 is a extentesion of CMD. It adds several features for command-prompt tools:

  • Searchable command history (commands: “hi”, “li”, “run”)
  • Load commands from file, save to file, edit commands in file
  • Multi-line commands
  • Case-insensitive commands
  • Special-character shortcut commands (beyond cmd’s “@” and “!”)
  • Settable environment parameters
  • Parsing commands with flags
  • > (filename), >> (filename) redirect output to file
  • < (filename) gets input from file
  • bare >, >>, < redirect to/from paste buffer
  • accepts abbreviated commands when unambiguous
  • py enters interactive Python console
  • test apps against sample session transcript (see example/example.py)

Defining function args as list of arguments for Python

Saltycrane

Python offers a way to define functions args as a tuple. The syntax is similar to C language, we’ll use *args to refer the tuple of arguments which are used in the function invocation.

def test_args(*args):
    for arg in args:
        print "another arg:", arg  

test_args(1, "two", 3)

Results:

another arg: 1
another arg: two
another arg: 3

Using *args when calling a function

Also, this special syntax can be used, not only in function definitions, but also when calling a function.

def test_args_call(arg1, arg2, arg3):
    print "arg1:", arg1
    print "arg2:", arg2
    print "arg3:", arg3

args = ("two", 3)
test_args_call(1, *args)

Results:

arg1: 1
arg2: two
arg3: 3

More info about:

Is not the same …

Usually, we don’t note  little, but relevant, differents in the code that we are reviewing. For example, the two next classes, apparently, are equivalents:

  class A:
    l = []
    __init__(self):
      ...
  class B:
    def __init__(self):
      self.l = []

    ...

But, really, this two classes are differ in their behavior:

  >>> a = A()
  >>> a.l.append(1)
  >>> a2 = A()
  >>> a2.l.append(2)
  >>> print a.l
  [1,2]
  >>> b = B()
  >>> b.l.append(1)
  >>> b2 = B()
  >>> b2.l.append(2)
  >>> print b.1
  [1]

Class A, due to l var is defined in class definition, share the l var between all A objects instanciates.

Chardet: encoding auto detect for Python

Last week, I has been fighting against the hordes of the character encoding. My new task in tha job-tasks-pool is develop a friendly web app to manage configuration files of cluster apps. Ohh, great idea!, why didn’t I realize it before? (irony) . Only I need 4 things: one parser for each conffile syntax, a stable and secure way to get/save remote files, work with non-controlled kind of differents char encodings, … and a fancy GUI. As you can intuit, the task is not just a bit app, but this post only refer to a very useful python lib ( chardet discovered a few days ago. This lib can be auto-detect the encoding of a file very reliable. I suggest you that visit chardet homesite to see some clear examples.

Using it in a couple of lines of code:

import io
import chardet

s=io.open(‘channels_info’, ‘r’, errors=’replace’)
r=s.read()

# For example:
# fileencoding=”iso-8859-15″
fe = chardet.detect(r)[‘encoding’]
fl = fl.decode(fe)
print fl