Thursday, April 28, 2011

Using {% url %}

Want to use the {% url %} template tags in Jinja2?

https://github.com/dcramer/coffin/blob/master/coffin/template/defaulttags.py

Want to use Jinja AND the Django template (for backwards compat with the admin screen)?

https://gist.github.com/472309

'delete' doesn't trigger keypress events in JavaScript

http://unixpapa.com/js/key.html


pecial Keys
KeyASCIIMozilla keycodesIE keycodesOpera keycodespseudo ASCII codesexceptions
Insert-45454545Konqueror: 0
Opera < 9.0: 0
Delete-46464646Konqueror: 127
Opera < 9.0: 0
Home-36363636Opera < 9.0: 0
End-35353535Opera < 9.0: 0
Page Up-33333333
Page Down-34343434
Function Keys
F1 to F12
-112 to 123112 to 123112 to 123112 to 123
Keypad Keys


Some browsers avoid this problem by not generating keypress events for special keys. A good case can be made that this is the right thing to do, since these keystrokes are arguably not character events. But such arguments are weakened by the arbitrariness of the division between normal and special keys. Why should the keyboard Backspace key have a keypress event, but not the keypad Delete key? Is Tab really fundamentally different than right arrow?
keypress events
event.keyCodeevent.whichevent.charCode
Internet Explorer (Windows)normal:ASCII codeundefinedundefined
special:no keypress events for special keys
Internet Explorer (Mac)normal:ASCII codeundefinedASCII code
special:no keypress events for special keys
Geckonormal:zeroASCII codeASCII code
special:Mozilla keycodezerozero
WebKit ≥ 525normal:ASCII codeASCII codeASCII code
special:no keypress events for special keys
WebKit < 525normal:ASCII codeASCII codeASCII code
special:extended ASCII codeextended ASCII codeextended ASCII code
Opera ≥ 10.50 (all platforms)normal:ASCII codeASCII codeundefined
special:Mozilla keycode, except keypad and branded keys give Opera keycodeszeroundefined
Opera ≥ 9.50 (all platforms)
Opera 7 (Windows)
normal:ASCII codeASCII codeundefined
special:Mozilla keycode, except keypad and branded keys give Opera keycodeszero for arrows, function keys, PageUp, PageDown
same as event.keyCode otherwise
undefined
Opera 8.0 to 9.27 (Windows)normal:ASCII codeASCII codeundefined
special:Opera keycodezero for arrows, function keys, PageUp and PageDown,
same as event.keyCode otherwise
undefined
Opera < 9.50 (Linux & Macintosh)normal:ASCII codeASCII codeundefined
special:Opera keycodezero for arrows, function keys, PageUp and PageDown,
same as event.keyCode otherwise
undefined
Konqueror 4.3normal:ASCII codeASCII codeASCII code
special:Pseudo-ASCII codePseudo-ASCII codezero
Konqueror 3.5normal:ASCII codeASCII codeASCII code
special:Pseudo-ASCII codezerozero
Konqueror 3.2normal:ASCII codeASCII codeundefined
special:no keypress events for special keys

Chrome Better Pop Up Block (v2.1.6) interferes with Hotmail

http://optimalcycling.com/other-projects/better-pop-up-blocker/

It is this popup blocker 2.16 that prevents from opening up Hotmail within Chrome browser.

With all my other extensions and plugins enabled or turned on, when the popup is enabled, email messages could not open Hotmail but could if it is disabled.

Surprisingly, Hotmail actually works very well with Chrome and is tacitly recommended by Microsoft to use!

Wednesday, April 20, 2011

Pylint and maximum recursion depth errors

Ever see these error messages in your pylint?

Exception RuntimeError: maximum recursion depth exceeded while calling a Python object

This bug was filed here: https://bugs.launchpad.net/pylint/+bug/456870 The solution seems to just upgrade Pylint using pip install instead of the Ubuntu Lucid package.

sudo apt-get remove pylint
sudo apt-get remove python-logilab-common
sudo pip install pylint

pylint --version
No config file found, using default configuration
pylint 0.23.0, 
astng 0.21.1, common 0.55.0
Python 2.6.5 (r265:79063, Apr 16 2010, 13:57:41) 
[GCC 4.4.3]

do...and and {} in Ruby

http://www.troubleshooters.com/codecorn/ruby/basictutorial.htm

Difference Between {} and do/end

As mentioned, there's one small difference between brace enclosed blocks and do/end enclosed blocks: Braces bind tighter. Watch this:

#!/usr/bin/ruby
my_array = ["alpha", "beta", "gamma"]
puts my_array.collect {
 |word|
 word.capitalize
}
puts "======================"
puts my_array.collect do
 |word|
 word.capitalize
end
[slitt@mydesk slitt]$ ./test.rb
Alpha
Beta
Gamma
======================
alpha
beta
gamma
[slitt@mydesk slitt]$

The braces bound tightly like this:

puts (my_array.collect {|word| word.capitalize})
Whereas do/end bind more loosely, like this:
puts (my_array.collect) do |word| word.capitalize} end

This issue is similar to the problem reported in http://stackoverflow.com/questions/5513531/ruby-do-end-vs-braces

Tuesday, April 19, 2011

Relative paths in PYTHONPATH breaks Nose tests

http://wingware.com/pipermail/wingide-users/2008-September/005878.html
What you're seeing is the affect of the current working directory being 
different when tests are run versus when the main debug file is run.  By 
default, the initial current working directory is the directory that the 
file run in in -- this applies to either the main debug file or the 
individual test files.
Another observation is that your HUDSON_HOME should be properly set too...otherwise Nose will not know to look for the right imports if you use $WORKSPACE in your PYTHONPATH.

Friday, April 15, 2011

Dropbox & Ubuntu installation -- upgrading to the latest version from an older copy

The Dropbox page has a pretty straightforward landing page to download the Linux version of Dropbox:

https://www.dropbox.com/downloading

For Ubuntu users, you can download the .deb file and do a sudo dpkg -i <deb file>.

The confusing part is that what you're downloading is a plugin for the Nautilus file manager, not the application itself. So when you're searching for 1.0.10 or whatever stable release, you get tripped up into trying to figure out why Dropbox is providing a 0.6.7 install link. The 0.6.7 is the version for the plugin, but application is something else.

What if you have an old version and want to upgrade? There is a selective sync feature recently released that makes it easier for you to manage which directories within folders actually get stored, which helps reduce your file space usage. It turns out the Nautilus plugin for Dropbox downloads the version and installs in your personal .dropbox-dist. You can check the version by doing a cat on the ~/.dropbox-dist/VERSION.
$ dropbox stop
$ rm -r ~/.dropbox-dist/
$ dropbox start 

You should notice that Dropbox will download the newest version. You can confirm again by looking at the ~/.dropbox-dist/VERSION file.

Tuesday, April 12, 2011

Cobertura and Hudson..

Two recent commits to fix some minor issues with the Cobertura plugin for Hudson:

This first patch will fix the issue with Python's coverage utility outputting the packages in non-alphabetical order. A more detailed explanation is here:

http://hustoknow.blogspot.com/2011/03/coveragepy-xml-outputs-in-random-order.html

The GitHub fix is here:
https://github.com/rogerhu/cobertura-plugin/commit/c34a72fff53eae398dfd4bc035df6b488a04aef0


One undocumented feature in Cobertura is that you can have a cobertura/ directory inside your jobs workspace that links to the source code. However, without the <pre> tags, the source code just appears as one line:

https://github.com/rogerhu/cobertura-plugin/commit/33bf5c44357d499533842a0cc14764990f576534

Next up? Putting the coverage HTML output there in lieu of the source code..

The documentation to compile Hudson/Jenkins plugins from a previous dev environment isn't clear, but you basically have to add a Jenkins repo in your ~/m2/settings.xml:

http://hustoknow.blogspot.com/2011/04/hudson-becomes-jenkins-compling-plugins.html

Hudson becomes Jenkins - compling plugins for Jenkins

When trying to compile the Cobertura plug-in, I noticed that the code has sufficiently changed to rely on the new Jenkins naming conventions. In order to compile these plugins, your ~/.m2/settings.xml must also be changed. You don't need to remove all the <repository > tags. In fact, you can just add the maven.jenkins-ci.org repository to the rest of the ones listed within the repositories.
<repositories>

       <repository>
         <id>maven.jenkins-ci.org</id> 
         <url>http://maven.jenkins-ci.org/content/groups/artifacts/</url> 
       </repository> 
     </repositories>

So your diff for your /.m2/settings.xml could look like:
~/.m2$ diff settings.xml.orig settings.xml
7c7
<    <id>hudson</id>
---
>    <id>jenkins<</id>
29a30,33
>     <repository> 
>              <id>maven.jenkins-ci.org</id> 
>              <url>http://maven.jenkins-ci.org/content/groups/artifacts/</url>
>           </repository> 
35c39
<     <activeProfile>hudson</activeProfile>
---
>     <activeprofile>jenkins</activeProfile>
39c43
<     <pluginGroup>org.jvnet.hudson.tools</pluginGroup>
---
>     <plugingroup>org.jenkins-ci.tools</pluginGroup>
Just run 'mvn' and it should download from the maven.jenkins-ci.org site!

Coverage.py XML outputs in random order

In using the nose-xcover plugin to create XML outputs for Hudson/Cobertura, I noticed that doing a pip install on nose-xcover installs Coverage v3.4b2 (http://nedbatchelder.com/code/coverage) and outputs the package reports out of order. The problem can be traced to the coverage/xmlreport.py code, which appears to create a DOM tree while relying on a dictionary in self.packages():

# Call xml_file for each file in the data.
        self.packages = {}
        self.report_files(self.xml_file, morfs, config)
.
.
        # Populate the XML DOM with the package info.                                                                                                                                                                                        
        for pkg_name, pkg_data in self.packages.items():
            class_elts, lhits, lnum, bhits, bnum = pkg_data
            xpackage = self.xml_out.createElement("package")
            xpackages.appendChild(xpackage)
            xclasses = self.xml_out.createElement("classes")
            xpackage.appendChild(xclasses)
            for className in sorted(class_elts.keys()):
                xclasses.appendChild(class_elts[className])
            xpackage.setAttribute("name", pkg_name.replace(os.sep, '.'))
            xpackage.setAttribute("line-rate", rate(lhits, lnum))
            xpackage.setAttribute("branch-rate", rate(bhits, bnum))
            xpackage.setAttribute("complexity", "0")

            lnum_tot += lnum
            lhits_tot += lhits
            bnum_tot += bnum
            bhits_tot += bhits

        xcoverage.setAttribute("line-rate", rate(lhits_tot, lnum_tot))
        xcoverage.setAttribute("branch-rate", rate(bhits_tot, bnum_tot))

        # Use the DOM to write the output file.                                                                                                                                                                                              
        outfile.write(self.xml_out.toprettyxml())
In the release notes for 3.4, however, this issue was fixed:

http://nedbatchelder.com/code/coverage/changes.html

The XML report output now properly includes a percentage for branch coverage, fixing issue 65 and issue 81, and the report is sorted by package name, fixing issue 88.
The XML report is now sorted by package name, fixing issue 88.
The specific diff is here:
https://bitbucket.org/ned/coveragepy/changeset/28a2ee046c75

Apparently the changes for 3.4b2 had not yet incorporated this fix, even though it was in the 3.4 release notes.
>>> import coverage
>>> coverage.__version__
'3.4b2'

The problem was that nose-xcover's setup.py has a requirement that the version of coverage used must be <3.4, which results in the older version being installed. To fix this issue, the setup.py must be updated to use <=v3.4.

A pip --install upgrade coverage will not work, since the nose-xcover plugin has a dependency that the coverage < 3.4 must be installed. So the --xcoverage option will not work since this check will fail when trying to use with Nose! For temporary measures, you can do a pip install git+git://github.com/rogerhu/nose-xcover.git#egg=nosecover to get yourself going.

Note: even with these changes, currently the Cobertura plug-in treats the packages as a HashMap and outputs the results in non-alphabetical order. So even though we've upgraded coverage to the right version and it properly outputs the package/classes in alphabetical order, Cobertura also must be fixed to do the same:

http://wiki.jenkins-ci.org/display/JENKINS/Cobertura+Plugin

The issue seems to be reported here already too. The authors appear to allow the items to be sortable, but the default ordering is still not by alphabetical:
http://issues.hudson-ci.org/browse/HUDSON-3182
http://issues.hudson-ci.org/browse/HUDSON-2966?focusedCommentId=128562&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel

The difference between using TreeMap and HashMap is located here:

http://javabeanz.wordpress.com/2007/07/13/treemap-vs-hashmap/

The GitHub patch has been submitted as a pull request:

https://github.com/rogerhu/cobertura-plugin/commit/c34a72fff53eae398dfd4bc035df6b488a04aef0

Sunday, April 10, 2011

Toshiba laptops...fan always on (and how to turn it off)

One recent issue I noticed with the Toshiba Satellite U205-S5002 (or perhaps any Toshiba Satellite notebook) is that the fan is always on.  Even after taking out the keyboard and using compressed air to remove the dust, the fan stays on no matter what.  One thing you can do is to enable the "TOSHIBA Power Saver" power scheme inside the Power Options manel, which lets you have access to the  Toshiba Power Saver icon in the Control Panel.  You can then change the Cooling Method from "Cooling Optimized" to "Maximum Performance."  Apparently not using the Toshiba Power Saver appears to keep the fan always turned on.

Note: you should double-check that the fan actually turns on in "Maximum Performance" (i.e. playing multiple YouTube clips simultaneously to tax the CPU).  If the fan is actually working, it could simply be a configuration issue in your Control Panel.

Friday, April 8, 2011

Can't see any wireless networks in XP


A program that Microsoft makes available called devcon (http://support.microsoft.com/kb/311272) let me confirm that the PCI card was still working.  You can issue a rescan through the program to probe your cards.  Soon enough, the wireless card showed up, but didn't show any wireless networks.  I then updated the wireless driver to the 11/2010 version, reset your TCP/IP stack (net sh reset), removed the Wireless Network Adapter, and then saved the ThinkVantage connection, and all of sudden things started working again.

Thursday, April 7, 2011

Why Django inserts LIMIT 21 on QuerySets...

Running the 'debugsqlshell' command in Django shows a lot of LIMIT 21 queries.  Why do they appear?  Here is a good explanation for why (basically so you don't see infinite items listed when doing a repr() on a QuerySet):

http://www.mail-archive.com/django-users@googlegroups.com/msg67486.html

Tuesday, April 5, 2011

Selenium v2.02b2

Recently, SauceLabs must have upgraded their Remote Control Servers from v1.0 to v2.0b2.  One thing to notice is that for IE browser testing, invoking get_text() on empty elements yielded a "Command execution failure" problem.  The issue was first reported here:

http://code.google.com/p/selenium/issues/detail?id=1163

A similar issue was also reported here:

http://code.google.com/p/selenium/issues/detail?id=1270&q=gettext%20undefined&colspec=ID%20Stars%20Type%20Status%20Priority%20Milestone%20Owner%20Summary

I also confirmed the issue exists on the latest beta release for Selenium (v2.0b3).  If you want to resolve the issue, I posted the patch here. For the more detailed explanation, see below.

How to verify the issue: If you're using SauceLabs and running Selenium tests, you can also set a breakpoint and verify for yourself that this issue exists for blank HTML elements:

(Pdb) sel.get_text('preview_url')
(Pdb) sel.get_eval('selenium.browserbot.getCurrentWindow().jQuery("#preview_url").html("")')
u'http://cnn.com'
(Pdb) sel.get_text('preview_url')
*** Exception: ERROR: Command execution failure. Please search the forum at http://clearspace.openqa.org for error details from the log window.  The error message is: 'undefined' is null or not an object
(Pdb) sel.get_eval('selenium.browserbot.getCurrentWindow().jQuery("#preview_url").html("aa")')
(Pdb) sel.get_text('preview_url')
u'aa'


Why does this issue happen?  The tests provided in http://code.google.com/p/selenium/issues/detail?id=1270&q=gettext%20undefined&colspec=ID%20Stars%20Type%20Status%20Priority%20Milestone%20Owner%20Summary actually for a good basis for how to verify that the problem exists only in IE browsers but not in Firefox.  Here's how you can reproduce the issue yourself:

1. a. Download http://selenium.googlecode.com/issues/attachment?aid=2624640355068451943&name=assert-span-empty.zip&token=b1a0f8e2d362e20eb01ede9614292dfc.

b. Download Selenium RC v2.0(http://seleniumhq.org/download/). Make sure you have Java installed to be able to run Selenium RC locally.

c. Set your environment path in Windows to be c:\Program Files\Mozilla Firefox.  Note: I found that v2.0b3 works with Firefox3 but not v2.0b2 right out of the box.

2. Unzip assert-span-empty.zip and change assert-span-empty.html to point the first set of lines to a URL that will host example-of-empty-span.html (i.e).  The original was expecting a local webserver but you can change it to be a remote one:

<tr>
<td>open</td>
        <td>http://myhost.com/static/example-of-empty-span.html</td>
<td></td>
</tr>

3. Edit the run.bat and edit the URL:

java -jar sele.jar -htmlSuite *iexplore http://myhost.com/static ./assert-span-empty-suite.html ./assert-span-empty-suite.log.html -singleWindow -timeout 10

You can toggle between *iexplore and *firefox to verify that the test suite passes the latter, but the former:

4. FTP the example-of-empty-span.html to the URL. Verify that you can connect to the file before invoking run.bat.

5. Invoke run.bat.

Once the issue is verified, how does one fix the problem?  It turns out Selenium relies on a bunch of JavaScript files that it exposes as an API interface. You can find them within the .jar file (i.e. selenium-server-standalone-2.0b3.jar) in the core/scripts dir. The main ones to trace are selenium-api.js, selenium-browserbot.js, and atoms.js.

Within selenium-api.js, you have this function:
Selenium.prototype.getText = function(locator) {
    /**
   * Gets the text of an element. This works for any element that contains
   * text. This command uses either the textContent (Mozilla-like browsers) or
   * the innerText (IE-like browsers) of the element, which is the rendered
   * text shown to the user.
   *
   * @param locator an element locator
   * @return string the text of the element
   */
    var element = this.browserbot.findElement(locator);
    return core.text.getText(element);
};
It turns out that the findElement() works properly. The problem appears to be inside the core.text.getText() function, which happens to be located in atoms.js. The reason is that for blank elements, the a.innerText in IE will resolve to false and b will therefore never be set.  In Firefox/Chrome/Opera, the getTextContent_() function is invoked and always appears to return a valid string.

The solution then is to initialize b to be an empty string (var b = '') to avoid these issues altogether:
core.text.getText = function(a) {
  a = core.locators.findElement(a);
  var b = '';
  if(goog.userAgent.GECKO && goog.userAgent.VERSION >= "1.8" || goog.userAgent.KONQUEROR || goog.userAgent.SAFARI || goog.userAgent.OPERA) {
    b = core.text.getTextContent_(a)
  }else {
    if(a.textContent) {
      b = a.textContent
    }else {
      if(a.innerText) {
        b = a.innerText
      }
    }
  }
  b = core.text.normalizeNewlines_(b);
  b = core.text.normalizeSpaces_(b);
  return goog.string.trim(b)
};

You can verify this change works by editing atoms.js, re-updating the atoms.js within core/scripts dir of the .jar file, and then re-running run.bat in *iexplore mode.  Once the .jar file has been updated and you run run.bat again, both tests should pass!

The diff for core/scripts/atoms.js can be located here:

http://code.google.com/p/selenium/issues/detail?id=1163