Author Archives: Hai

About Hai

I am a software engineer who spend most of my time coding test automation, mostly in Python. I love the Mac and Linux.

Simple Online IDE for Python

I am in need of a quick way to post Python code snippet online, run it and show output. My research points me to quite a few and I like three of them.



What I like

  • No ad!
  • Does not require signing up to use
  • The code and the output are nicely formatted and easy to view
  • Once submitted, codepad generates a new page with a unique URL. The users cannot change the code unless they choose to fork. This is great to present someone a code snippet without fear of someone modifying it
  • Has a comment section, good for discussion

Improvements Wish List

  • Syntax highlight
  • Code completion
  • Optional title, description, and tags

Python Fiddle


What I like

  • No ad!
  • Does not require signing up to use
  • Syntax highlight
  • Code completion
  • Large editing area

Improvements Wish List

  • Buggy sometimes. I typed import json and got invalid syntax on print import json
  • Importing of modules takes a long time: the first time I import json, it took about 2 seconds
  • Output not clearly labeled



What I like

  • Does not require signing up to use
  • Syntax highlight
  • Many languages
  • Ability to specify stdin

Improvements Wish List

  • Larger editing area
  • Required Flash
  • Lots of ads
  • Output is burried below an ad

Why Returning a Mutable Attribute Might Be Dangerous

Avoid Returning Mutable Attribute

People who come from C++, Java or C# often provide getter/setter to provide access to their classes’ internals. In Python, there is not point to use getter/setter unless there is a good reason for doing so. I have been coding in Python for several years and have not yet come by one such reason.

I have seen code where people prefix a class instance’s attribute with underscore thinking it should make that attribute private. The following example will demonstrate that point:

class Car(object):
    def __init__(self, owners):
        self._owners = owners

    def get_owners(self):
        return self._owners

if __name__ == '__main__':
    car = Car(['Peter', 'Paul'])
    print 'This car belongs to', car.get_owners()

    owners = car.get_owners()
    print 'This car belongs to', car.get_owners()


This car belongs to ['Peter', 'Paul']
This car belongs to ['Peter', 'Paul', 'Mary']

In the example above, the user calls car.getowners() to gain access to a private member, but then went on modifying it. The immediate solution is to return a copy of self.owners. That way, changes made to the copy does not affect the original member.

Avoid Returning Attributes at All

Instead of allowing the users to gain access to your class’ internals, why not provide what the users really want. Think of a class attributes as nouns (things) and methods as verbs (actions). A class should provide the users with actions, not nouns.

Here is a typical example:

import fnmatch

class FileFilter(object):
    def __init__(self, include=None):
        self._include = include

    def include_patterns(self):
        return self._include[:]

# Usage example: prints all the files that fit a set of patterns
filter = FileFilter(include=['*.py', '*.ipynb'])
for filename in ['readme.txt', '', 'greeting.ipynb']:
    for pattern in filter.include_patterns:
        if fnmatch.fnmatch(filename, pattern):
            print filename


Provide Services Instead of Attributes

In the example above, the class FileFilter provides a getter, include which returns a list of pattern. Instead of providing the users with an attribute (self.include, a noun), it should instead provide a service, an action, namely: shouldinclude:

import fnmatch

class FileFilter(object):
    def __init__(self, include=None):
        self._include = include

    def should_include(self, filename):
        return any(fnmatch.fnmatch(filename, pattern) for pattern in self._include)

# Usage example: prints all the files that fit a set of patterns
filter = FileFilter(include=['*.py', '*.ipynb'])
for filename in ['readme.txt', '', 'greeting.ipynb']:
    if filter.should_include(filename):
        print filename


Notice in the example above, FileFilter does not expose any internal data. Instead, it offers a service (an action, or verb, namely should_include). Also notice the code which uses the FileFilter class is also simpler, with one less nested level.


When designing a class, you should avoid returning a class’ internal data, especially mutable structures. Instead, you need to study the users code to see what they use those data for and offer services to accomplish their goals.

Disney Cruise 2013

Day One: Getting on Board

The Disney Fantasy

We boarded the ship as early as we could in order to spend as much time on the ship as possible. Think about it, cruises are not cheap, so the more we spend on the ship, the better bang for the buck we get.

Once aboard, we took the advice from other seasoned travelers and went straight to the lunch room as our stateroom (that’s what they called our room) were not yet ready. Many chose to went swimming before having lunch. We went to our stateroom around 1:30PM to find our luggages ready outside the door.

Dinner was very nice. The portions seem little, but we got very full because of the appetizer, bread, main course, then dessert. If you have food allergy like I do, then let your server know as soon as you pass the introduction. The same server will serve you for the whole duration of the trip, so you don’t have to repeat what you said, which is nice.

After dinner, we went to the theater and got in line early. Seatings in the theater are limited so be there early to get a good seat. The cruise director advised not to save seats for your party, so you need to all be there or risk losing your seats. We highly recommend going to the theaters after dinner and do not miss any show. These are the kind of shows that back home might cost anywhere from $50/ticket to $150, so you might want to maximize your money’s worth.

Day Two: at Sea

We spent the second day exploring the ship. Since we did not bring a lot of clothes, we started searching for self-service laundry room. The one we used had about four washers and four dryer. We purchased detergent and dryer sheets right in the room using our keycard. These are not cheap: while detergent and dryer sheet cost about two dollars each, adding to that the cost of operating washer and dryer, the cost per load is about $10-$12. Budget-conscious travelers might want to bring detergent and dryer sheets from home. We highly recommend of bringing dryer sheets: they add almost no weight to the luggage, but save a lot of money. If you bring them, make sure to keep them inside zip lock bags or they will loose their magic freshness.

Day Three: Grand Cayman

Grand Cayman Beach

We did not buy on-shore packages from Disney. Instead, we just played it Russian-roulette style: We got off the ship and “shop” around for destinations. We ended up in wonderful beach which I forgot the name.

Grand Cayman is part of the British-oversee territory and it showed in the way people drive on the left side of the road. From the beach, we could smell the pungent smell of durian. Except for our younger daughter, we all love durian. However, if you don’t like (read: are terrified of) durian, let your driver know.

We spent most of our time on Grand Cayman at the same beach. Originally, we wanted to explore the town, but our daughters did not want to leave the beach. Being from Seattle, where the water is too cold year-round, we could not blame them.

Day Four: Costa Maya, Mexico

Chacchoben Maya Ruin

We decided to book through Disney for our excursion to see the Chacchoben Maya Ruin–a set of pyramid structures. When we got ashore, we got on one of the buses heading to the site, which took about an hour. Unfortunately, it was raining on that day, but the pyramids were an incredible sight. Since the trip took four to four and a half hours to complete, we disembark as soon as we could.

Since it was raining, the site was muddy and slippery. It was a good thing that we brought with us the raincoats that the cruise staff gave us. The rain prevent us from taking many pictures and video, but we did manage to capture a few shots. For those who care about history or anthropology, this is a must-visit place.

Day Five: Cozumel, Mexico


My daughters wanted to go on the Dolphin Discovery excursion, but instead of booking through Disney, we chose to book it ourselves to see if we saved any money. As soon as we got on shore and walked outside the fenced area, we saw a busy street full of shops and taxis. We asked for direction to “the dolphin place” which many people gave different answers. Finally, we booked through a middleman, who told us the price would include taxi ride to our destination and back.

When we arrived at Chankanaab, dolphin discovery park, we learned a few things. First, the price is identical whether we booked through an agent on the street, or at Chankanaab. However booking at Chankanaab is safer because we did not have to pay the middleman cash deposit. Second, we were swindled as the price did not include any taxi ride back, which costed $12 (prices in US dollars). If we were booking from Disney, the price would be $112 x 2 = $224 with transportation. When we booked ourselves, the price came to $79 x 2 = $158. Add $12 for transportation, we ended up spending $170 for the two kids–a $54 saving for two kids, or $27 per person. Also, in order to get into the park area to watch our kids, both my wife and I had to pay entrance fee of $21/person, which would be $26 if booked through the middleman. Fortunately, we did not. So, the lessons I learned from this excursion are:

  • Learn the name of your destination to make it easer on your transport
  • Take a taxi ride (or other mode of transportation) there. Do not book through any agent or middleman.
  • If you want peace of mind, book through Disney. It might worth $27/person premium.

Once we arrived at the park, we had an hour before the next dolphin session. At this point, our family can get into a large pool, a mini lagoon, or hang around the bars, shops within the park. My wife and I chose stay dry while the kids had a good time around the pool. They preferred this pool over the one on the ship since it was larger, and much less crowded.

The park did not allow parents to accompany the kids in order to take pictures, unless we paid yet another fee. We chose not to do that and enjoyed ourselves at the Cove–their restaurant. The Guacamole and chips was good and the price was right: about $5.75 (US dollar).

Our kids had a great time with the dolphins, we could see it in the pictures the park took. However, they demanded $37 per picture, or all 24 of them for $124. Again, we chose not to purchase due to the high price.

Day Six: at Sea

Inside the Fantasy

On this day, we continued to explore the ship. We spent our morning at the pools and hot tubs. We also visited the movie theater and saw The Lone Ranger. We also took this opportunity of taking many photos at various places, especially with the Disney characters. At night, after the nightly show, we went to a club and found that they played disco of the 70’s. What a night!

Day Seven: Castaway Cay

Castaway Cay

We decided to go on shore as early as we could and it paid off: when we got the the beach, it is already full of people and we were lucky to find some chairs. Castaway Cay (pronounce: key) has to beaches. If you don’t find any chairs from the first one, continue on to the second one.

Next to our beach, Disney has a private beach for those who pay or belong to some sort of clubs. We recommend to to pay, unless you like to have an empty beach to yourself. We did not find may people there, only a handful.


  • Check in at least three days in advance so you can choose the time that is convenient. Disney said the check-in time is from 1:00PM to 3:30PM, but we arrived early and was able to get in around 12:30PM.
  • Once on board, you can immediately hit the pools on deck 11 since they are not crowded.
  • Another option is to have lunch, also on deck 11. For the kids, they offer the “kid-comfort” food by the pool: pizza, burger, sandwiches… For the adults and kids alike, head the rear (aft) of deck 11 for the Cabana, a buffet-style lunch-and-breakfast place.
  • Don’t waste for first hours checking out the ship–you can perform your inspection later. Instead, go swimming or have lunch.
  • If you get seasick, head to the guest services on deck three midship and ask for some pills.
  • Buy bottled water and bring them onboard. I saw many families who bought them by 24-bottle cases and the cruise will bring them to their staterooms. While drink is free on the ship, there is no water in the staterooms, unless you take a long walk to the dining rooms and get them. You can also buy bottled water onboard, but it is expensive.

Post-It Notes Resume


I am currently searching for a job, as the result, I often carry in my “murse” (man-purse) a stack of paper resume. Due to the size of the bag (a Tom Bihn Small Cafe bag), I have to fold the pages in half. In addition, these pages add bulk in a bag where space is already at a premium.


To solve this problem, I put my resume online, then point people to it.

Posting Resume Online

I used Google Docs to create my resume. Consequently, they already available online. All I need to do is to make my document public and received a random (and long) URL. The next step is to shorten that URL using a URL-shortening service such as Now that I have a short, easy-to-type URL, the next step is how to give that URL to someone. Writing on a piece of paper is always an option, but there is a better way.

Post-It Note Resume

To easily hand out my resume, I print the URL for my resume, along with a QR code on Post-It notes and carry those notes with me. These notes take only a fraction of spaces compare to the full letter-size pages of my resume. They are easier to hand out as well.

To create the QR code, I searched online and found many places to do so. I used for my creation, but other sites work as well. Next, I searched online for a way to print onto Post-It notes and found many pointers as well. The one I used was from a site called One Good Thing.

How to type Vietnamese on Windows 7

Typing Vietnamese on Windows 7 does not require any third-party software. All we need is to enable the Vietnamese keyboard and learn how to type special characters.



Open Control Panel and click on Clock, Language and Region.


Click on Change keyboards or other input methods at the bottom of the right pane.


Click Change keyboards…


In the Text Services and Input Languages window, click Add…


Select Vietnamese from the list and click OK.


We will see the Vietnamese keyboard added. Click  OK and we are done with the installation.


How to Type Vietnamese Text

The first step is to switch the keyboard from English (or your current language) to Vietnamese.  Look at the bottom of right of the screen, we will see “EN” for English. Click on it and select “VI” for Vietnamese.



Next, we will learn how to type special Vietnamese characters:

Huyền = 5
Hỏi = 6
Ngã = 7
Sắc = 8
Nặng = 9

ă = 1
â = 2
ê = 3
ô = 4
đ = 0
ư = [
ơ = ]

Good luck.


tcltest Part 9: Provides Exit Code

The Problem

One of the complains against tcltest is the fact that it does not return an exit code to communicate test pass/fail status.

Consider a simple scenario. In a directory, we have two files: all.tcl, which drives all the tests, and test1.test, which contains the actual tests. The contents of all.tcl is:

package require tcltest

And the contents of test1.test is:

package require tcltest
namespace import ::tcltest::*

test fail_me {} -body { set foo 1 } -result 0
test pass_me {} -body { set foo 1 } -result 1


In the scenario above, one of the tests will fail, but all.tcl will always return with exit code 0. It would be more useful if it returns 0 when all tests passed and 1 when not all tests passed.

The Solution

We looked into the tcltest source code and found an array, tcltest::numTests, which looks what we need. So, we modified all.tcl to see if we can use it:

package require tcltest
parray tcltest::numTests

The result is disappointing:

(irrelevant output omitted)
tcltest::numTests(Failed)  = 0
tcltest::numTests(Passed)  = 0
tcltest::numTests(Skipped) = 0
tcltest::numTests(Total)   = 0

With one failed tests, we thought tcltest::numTests(Failed) should be 1, but it was not. we went back to the source code and dug a little deeper and found tcltest::cleanupTests resets these numbers after it finishes reporting.

Just when we was about to give up, we thought of asking Mr. Google for help. Sure enough, tcltest provides a hook into its tcltest::cleanupTests, which gives us access to the statistics variables before it resets them. Here is the final all.tcl:

package require tcltest

# Hook to determine if any of the tests failed. Then we can exit with
# proper exit code: 0=all passed, 1=one or more failed
proc tcltest::cleanupTestsHook {} {
    variable numTests
    set ::exitCode [expr {$numTests(Failed) > 0}]

exit $exitCode


The trick is to write a hook, tcltest::cleanupTestsHook. Before resetting the test statistics, tcltest::cleanupTests calls the hook function, which gives us the opportunity to access these statistics, and use them to determine the exit code.

Now that all.tcl returns the proper exit code, we can use it to determine pass/fail. Here is an example using the bash shell in Unix-like systems:

if tclsh all.tcl; then
    echo Tests passed
    echo One or more tests failed

For Windows environment:

tclsh all.tcl
if errorlevel 1 echo One or more tests failed


We wish tcltest automatically returns the correct exit code, but it does not. For now, we will stick with this solution and hope that whoever working on tcltest won’t make our code obsolete.

How to Install .apk File onto an Android Device

The Problem

I am new to the Android platform. At work, I need to side-load our app for testing. My device is an HTC one of 2012. At first, I installed and ran the HTC Sync Manager from my MacBook Pro with hope that it could help me, but after half an hour, I gave up: I copied the .apk file to the file section, sync, then check the phone: I could not find that .apk file anywhere. It could be me, but for the life of me, I could not find a way to copy the file in question onto the device. There must be a better way.

My Solution

As I stated before, the problem is with me being a novice. However, I did spend a good half an hour googling for solutions to no avail. Finally, an idea came to me: what if I can transfer the file from my Mac to the HTC One via HTTP? With that though, I opened up a terminal session, cd to the directory where my .apk file is, and issued the following command:

python -m SimpleHTTPServer

That command created an impromptu web server to serve all the files within the current directory. From the HTC One, I fired up a web browser and jumped to my server: haiv-mac1.local:8000 and expected to see the directory listing. However, I could not connect to my Mac at all. Frustrated, I tried again and again, prepending http:// to the address, check my spelling, knelt down and prayed… But nothing worked. I tried the same address using my iPhone and it works. So the problem was with the Android device. Finally, I was able to connect using my Mac’s IP address. How I love Android!

Once I downloaded the file, it was a simple matter of tapping the Downloads icon, find my file, and tap on it to install.


I like the Android platform for giving me the ability to side-load apps, which is great for testing. However, the process could be simpler. Veteran Android users and developers might laugh hearing this story, but it is no joke to me. Until I gain enough expertise, I’ll stay with my trusty iPhone.

Tcl: A Custom For Loop

The Problem

I often need to loop through a list of items and need both the index position, and the item itself. Typically:

set names {John Paul George Ringo}
set i 0
foreach name $names {
    puts "$i - $name"
    incr i


0 - John
1 - Paul
2 - George
3 - Ringo

Initial Solution

Since I frequently do this, I decided to implement my own loop and call it for_item_index for lack of creativity. Here is my loop and a short code segment to test it:

proc for_index_item {index item iterable body } {
    uplevel 1 set $index 0
    foreach x $iterable {
        uplevel 1 set $item $x
        uplevel 1 $body
        uplevel 1 incr $index

# Test it
set names {John Paul George Ringo}
for_index_item i name $names {
    puts "$i - $name"

I have tested it with break, and continue and found my new loop performs as expected. My concern is the excessive use of uplevel command in the code.

Here are my own review of my code:

  • Excessive use of uplevel – I don’t know what to do about it. If you have an idea, please send it my way.
  • The index always starts at zero. There are times when I want it to start at 1 or some other values. To add that feature, I will probably introduce another parameter, startValue
  • Likewise, the index always get incremented by 1. The user might want to increment it by a different values such as 2, or –1 to count backward. Again, introducing another parameter, step might help, but at this point, the loop is getting complicated.

Revised Solution

Shortly after the initial solution, I posted it on StackExchange’s CodeReview site. While waiting for comments, I started to revise the initial solution to include the start- and increment values. Here is the revised solution and code snippets to demonstrate:

proc for_index_item {indexexpr itemvar iterable body} {
    # Break down indexexpr
    set step 1
    set start 0
    if {[llength $indexexpr] == 3} {
        set step [lindex $indexexpr 2]
    if {[llength $indexexpr] >= 2} {
        set start [lindex $indexexpr 1]
    upvar 1 [lindex $indexexpr 0] index
    set index $start

    upvar 1 $itemvar item

    # Actual loop
    foreach item $iterable {
        uplevel 1 $body
        incr index $step

# Test

puts "\nDefault, start with 0"
set names {John Paul George Ringo}
for_index_item i name $names {
    puts "  $i - $name"

puts "\nStarts from 1"
set names {John Paul George Ringo}
for_index_item {i 1} name $names {
    puts "  $i - $name"

puts "\nWith start value and increment"
set names {John Paul George Ringo}
for_index_item {i 110 10} name $names {
    puts "  $i - $name"


Default, start with 0
  0 - John
  1 - Paul
  2 - George
  3 - Ringo

Starts from 1
  1 - John
  2 - Paul
  3 - George
  4 - Ringo

With start value and increment
  110 - John
  120 - Paul
  130 - George
  140 - Ringo

A few comments:

  • I took in a suggestion and used upvar instead of uplevel, which makes the logic a little cleanner.
  • Half of my code is now devoted to parsing
  • The word index is miss-leading: it has nothing to do with the index as in a list index. It is just part of a sequence of numbers. In the future, I might rename it to remove confusion.

Let the Mac Speak for Me

The Problem

I often lose my voice temporarily due to allergy. During that time, my main mode of communication is a notepad, or the electronic equivalent: Zen Brush. I was looking for a solution that can convert what I type into spoken words.

The Solution

Since I am using Mac both at home and at work, and Mac has the say command which is useful for this purpose; I decided to roll my own solution. It turned out that the solution is a very simple bash script, which I named, which I saved in my ~/bin directory:

while read line
    say -v Alex $line

To make the script executable, I issued the following command:

$ chmod +x ~/bin/


To use, from the terminal, issue the following command:


After that, start typing your message. As soon as you hit the return key, the script will “say” what you type. You can keep on typing and hitting return. To end the script, just type Ctrl+C.


The script is very simple, pragmatic and free from bells and whistles, but it works the way I like it. The -v Alex part of the say command specifies a voice from Alex. OS X comes with a few voices which you can experiment with yourself. To list the voices your system has, issue the following command:

$ say -v ?
Agnes               en_US    # Isn't it nice to have a computer that will talk to you?
Albert              en_US    #  I have a frog in my throat. No, I mean a real frog!
Alex                en_US    # Most people recognize me by my voice.
Bad News            en_US    # The light you see at the end of the tunnel is the headlamp of a fast approaching train.
Bahh                en_US    # Do not pull the wool over my eyes.
Bells               en_US    # Time flies when you are having fun.
Boing               en_US    # Spring has sprung, fall has fell, winter's here and it's colder than usual.
Bruce               en_US    # I sure like being inside this fancy computer
Bubbles             en_US    # Pull the plug! I'm drowning!
Cellos              en_US    # Doo da doo da dum dee dee doodly doo dum dum dum doo da doo da doo da doo da doo da doo da doo
Deranged            en_US    # I need to go on a really long vacation.
Fred                en_US    # I sure like being inside this fancy computer
Good News           en_US    # Congratulations you just won the sweepstakes and you don't have to pay income tax again.
Hysterical          en_US    # Please stop tickling me!
Junior              en_US    # My favorite food is pizza.
Kathy               en_US    # Isn't it nice to have a computer that will talk to you?
Pipe Organ          en_US    # We must rejoice in this morbid voice.
Princess            en_US    # When I grow up I'm going to be a scientist.
Ralph               en_US    # The sum of the squares of the legs of a right triangle is equal to the square of the hypotenuse.
Trinoids            en_US    # We cannot communicate with these carbon units.
Vicki               en_US    # Isn't it nice to have a computer that will talk to you?
Victoria            en_US    # Isn't it nice to have a computer that will talk to you?
Whisper             en_US    # Pssssst, hey you, Yeah you, Who do ya think I'm talking to, the mouse?
Zarvox              en_US    # That looks like a peaceful planet.

Python: Making Complex Regular Expression Easier to Read

In my last post, I shared a way to created regular expression with embedded comments for the Tcl scripting language. It turns out that Python also offers similar feature.

The Problem

I often need to deal with complex regular expression while scripting in Python. The problem is, the expression syntax is terse, cryptic and hard to understand and debug. There must be a better way to deal with regular expression, a way to add comments would be nice.

The Solution

As with my last post, I will use the same example: fishing out email addresses from a chunk of text. Below is the Python counterpart of my previous solution:

import re

if __name__ == '__main__':
    test_data = '''
            This is a bunch of text
            within it, there are some emails such as
            What about mixed case:
            Let see if we can extract them out
    email_pattern = r'''
            # The part before the @

            # The ampersand itself

            # The domain, not including the last dot

            # The last dot

            # The top-level domain (TLD), which ranges from 
            # 2 to 4 characters
    print 'START'
    result = re.findall(email_pattern, 
    print '\n'.join(result)
    print 'END'

The output:



With the re.VERBOSE flag, I can embed white spaces and comments in the regular expression, making it easier to read and understand.