Wednesday, February 24, 2010

So you never wrote a line of code? How to learn to program

This ad was linked in this blog post. This was interesting to me as I was just telling someone the other day about how "when I was a kid" the line being using a computer and programming it were quite blurry. The most common way to share software for the TRS-80s at my middle school was to exchange listings (printed source code).

So this weirdly ties together with a challenge that I am taking on tomorrow morning. Can I introduce people who have never programmed to programming? Of course, in a way that makes them want to keep programming and to make some apps that they would like for Ubuntu. But first, get started with the whole notion of programming.

They say, "write what you know." So I decided to use my own experience being introduced to programming to introduce others to programming. My first program was a crazy text adventure game.

So I wrote this wiki page to help me walk through the class session for Opportunistic Developer Week. If you want to join, get the time and place here.

I'm hoping that I see what works and doesn't and can ultimately create a kind of story that folks can read to get them introduced to programming concepts. We'll see how it goes.

Tuesday, February 23, 2010

What software will be "Featured"?

Following from mvo's great working getting a Featured Category in the Software Center, the desktop team discussed how to gt that actually populated with apps.

The process for determining what apps will be featured is specified in a blueprint, of course. Please leave comments regarding *the criteria for apps* on the blueprint.

If there is an app that you think meets the criteria, please list it on the specification wiki.

Next week at the desktop team meeting we will sort through the list and come up with the list of apps to be featured.

Fast User Switching is Back In Lucid!

Thanks Ayatana devs (tedg?) and robert_ancell too. Nice. I guess the root of the problem was the new GDM did not have the API necessary for pre-selecting the user. So Robert spent some time adding the API back to GDM so that Ted could call it from the session menu.

In Karmic with the reworking of the session menu and the switch to the new GDM, we lost the ability to switch to another user in fast way, you had to go back to the GDM greeter and pick the user that you wanted to switch to from a list. This was a regression from Jaunty. Now you can just choose from the list again.

UNE on my Desktop, I likes

I've been running UNE on my desktop with a largish monitor since yesterday morning. Because the Desktop Team now also manages the UNE distro, I figured I should get in the habit of using UNE daily, but I don't use my netbook as much as my desktop during the course of a normal week. Above is the launcher ready for me to get started.

Fortunately, didrocks has tweaked the way UNE and the normal Gnome desktop interact. He set up a system where you can install UNE on a Desktop, or a Desktop on UNE, and then choose the session you want when you log into GDM.

To get UNE running on your desktop in Lucid, I did this:
  1. Used Software Center to install ubuntu-netbook

  2. Restarted my session, it will select a UNE session by default. You can easily switch back to a normal desktop session by selecting Gnome when you log in with GDM.

  3. Went to System -> Administration -> Start Up Programs, and turned off Maximus. If you don't do this all apps on your desktop will automatically go to full screen, which you probably don't want on your desktop.
Here's a couple of apps running, notice the "background" is the launcher.
Here's a full screen app running.

UNE is naturally very space savings. So you can see that all of the window switching and such is handled in this compact area.
Running a desktop session on a UNE installation should work in an inverse manner. I will try that out in the next couple of days.

Monday, February 22, 2010

PPAs in Software Center

PPAs are great. Having a reliable way to get apps to your users, and a reliable way to update them there as well is a huge benefit for the Ubuntu platform.

To get to a PPA you can use Software Sources to add the PPA by using the Add button in the "Other Software" tab. But then how to actually install the app in the PPA?

Well, once again Michael Vogt comes through with a graphical way to manage software from PPAs, right in Software Center! Thanks again mvo for another awesome contribution to the Ubuntu Desktop.

Saturday, February 20, 2010

Learning Python, what I wish they told me

On Thursday I will be running a couple of little sessions to kick off Opportunistic Developer Week. One of these will be for folks who know a little or a lot of programming today, but haven't tried or gotten into Python:
  • Thu 25th Feb 2010 - 16.00 UTC - Ubuntu Opp Dev Week Prep: Intro to Python for programmers - Rick Spencer

The reason I was excited about doing this session, is I remember when I was struggling to figure out how to write programs for Ubuntu. It was sad and frustrating that it was so hard to figure out what languages, libraries, and tools to use, because I could already write programs for Windows (I was working at Microsoft at the time, after all), and I could write web sites. I'll never claim to be anything but an opportunistic programmer, but when I fell in love with Ubuntu as a platform, I could make things happen on other platforms, but just couldn't get going with Ubuntu without lots of struggling. In fact, I essentially quit my job so that I could dedicate myself to solving this problem for Ubuntu. At the time, of course, I never dreamed that I'd actually get to work for Canonical and get paid to work on FOSS software. I thought I'd be lucky to pick up some opportunities to do some training and writing about it, targeted at folks migrating from Windows to Ubuntu.

Before I even quit my job, I tried my hand at contributing to solving this "how do I get started" problem by writing some "chapters". They are here, but there are some wrongnesses in them. Feel free to grab them, read them, modify them, share them, etc... However, beware, there are some wrong things in them that I need to fix. For example, the code samples us one space for indents instead of 4, I didn't understand how underscores worked, or the difference between "==" and "is". I know there are more, but hey, it was a start.

So I went through a couple of the chapters to put together and outline for the session. My goal for the session will basically be to help build a bridge between languages people know now to Python.

Here are my notes so far. I will go through and make code samples and such to get ready and make the session very productive.

Language Concepts
1. Indentation levels
- controls scoping instead of {}, "end", etc...
- standard is to use 4 spaces for each indentation level
- you will get used to it, and probably format you code this way anyway
- at first, many errors will be caused by this

2. Strong Dynamic Typing
- Object and sibclasses, int, float, etc...
- A variable can change type
- don't declare variables with types
- can convert a *variable* to another type, not casting and assigning

3. Types
- Numeric types
- Integer, Long Integer, Float, Complex
- Normal operands and conversion functions float(), int(), etc...
- Can mix and match them in math, will convert to use least "restrictive" type

- Strings
- lots of functions
- not difference between characters and strings
- concatenation with +, +=, etc...
- ",' are the same
- """ can included \n, ",', etc...

- None
- like Null, null, etc...
- None is an object of type NoneType
- undefined variables are not None, just undefined errors

4. Lists and Tuples
- Like an array
- Not types, can contain anything
- Tuples are immutable lists
- how to append, remove, etc...

5. Dictionaries
- Like hash tables
- "foo in bar" syntax
- how to append, remove, etc...

6. Comparisons and branching
- True and False
- if, ==, !=, <=, >=, etc....
- is, is not
- or, and
- else, elif

7. Loops
- for foo in bar:
- while loops
- for i in range(10)

8. Error Handling
- try, except
- Exception type: except Exception
- Exception instance: except Exception instance:

9. comments and doc comments
- #comment is just for folks reading code
- using """ in strategic places == doc comments, pydoc

Modules, Files, Classes
1. file overview
- shbang
- tell bash what interpreter to use
- imports section
- like #include
- import os
- from foo import bar
- code section
- if __name__ == "__main__"
- runs if module is called directly not from another module
- start your program, also useful for writing test apps

2. Code section
- class overview
- class decleration
- define superclass, call super.__init__(self)
- __init__
- member functions, what's this "self" thing?
- member variables
- in a function
- outside of functions
- can define multiple classes in a file
- can define functions variables outside classes

3. OO syntax
- instantiating object
- no private variables, really?
- convention: start with _ for members that should be private and inheritable
- start with __ for members that should be private and not heritable (munging)

Wednesday, February 17, 2010


A UDS for Lucid in Dallas, during the default application install session, we discussed adding some kind of "picks" for software center where we could "feature" software that we loved, though it may not be appropriate for installation on the default CD.

Michael Vogt got this featured implemented, and tonight it showed up in Lucid. So far, it is just a container. Michael added the Gimp and Abiword (both safe bets), but now we need to fill it with "featured apps"!

Thanks Michael!

Monday, February 15, 2010

Quickly.Widgets API Design and Documentation

As I've been working of Photobomb and Bughugger, I've been using Quidgets, and extending or tweaking as I needed to do different stuff for the programs.

One thing is, Quidgets need a better name. "Quidgets" was a sort of as a joke. "Quidgets" does have teh advantage of being silly, and maybe keeps folks from taking it too seriously. It's good the name that expresses that. But maybe it's time to boost the configence of the project. So didrocks repackage quidgets as "quickly-widgets", now the namespace is quickly.widgets, quickly.prompts, etc... We'll see how it goes.

Any hoo...

The start of quickly.widgets was focused on one-liners, making it take no more than a line or two to use a quickly.widget. It's good to try to make it easy and fun to write programs. So for instance, with DictionaryGrid, all you need is a dictionary and one line to create the DictionaryGrid, and you are displaying tabular information to users:
 #create a dictionary if you don't already have one
dicts = [{"test?":True,"price":100,"foo count":100,"Key4":"1004"},
{"test?":True,"price":100,"foo count":100,"Key4":"1004"},
{"test?":True,"price":100,"foo count":100,"Key4":"1004"}]
#create the DictionaryGrid
dg = DictionaryGrid(dictionaries=dicts)
It's consuming a quickly-widget, simply by "using" it. A quickly-widget when the underlying PyGtk library is just barely exposed, if at all, and covers up to about 80% of the use cases. In other words, you shouldn't always need to change anything to make it work for your program.

However, sometimes you have to tweak a quickly.widget for your needs. It's best when most of the essential functionality is provided, but perhaps you have to write a few more lines of code to configure the quickly.widget. This is the "configuring" level of consuming, You can write a few lines of code to set properties and call functions on a quickly.widget. It's a bit more work, but I the code should be easy to write as well. Somtimes the code for configuring a quickly.widget requires knowing or learning about a few parts of the underlying PyGtk library. Sometimes you have to learn about another quickly.widget. For instance, with DictionaryGrid you can configure the types of columns to use:
 #Define column types to use
hints = {"price": StringColumn}
dg = CouchGrid(dictionaries=dicts,keys=keys, type_hints = hints)
In some cases you confige using the underlying PyGtk library directly. For instance to configure a DictionaryGrid to use a different column label, you use the TreeView API like this:
I tried to make the GridFilter be a simple matter of configuring, so you can get special behiavior without the work deriving from a base class:
 blank_filter = BlankFilterCombo()
blank_filter.append("=",custom_equals_function )
blank_filter.append("<>",custom_no_equals_function )
filter_hints = {"status":blank_filter}
filt = GridFilter(grid, filter_hints)
For some applications there will be way way way too much code just configure an object, so you might end up extending a quickly.widget. For example, I was trying to add offline bug editing for Bughugger. The code was hard to modify starting after only about an hour into writing it because just configuing a DictionryGrid to save it's data in Desktopcouch required too much code strewn about the bughugger code file. So instead, I extended DictionaryGrid to be the new CouchGrid. Doing this required lots of knowledge of the DictionaryGrid widget, DesktopCouch, and PyGtk. However, my requirement was supported and the code is reusable.

I'm hoping to see in time an application library that is easy to use for task at hand, using, configuring, or extending.

Sadly, I have been totally lame about writing documentation for quickly widgets. So I have started doing proper pydoc documentation, adding a use, configure, and extend section to each module. For example, for couch_grid the module documentation now works in pydoc and includes an overview in addition to the reference for each function:

I've gotten dictionary_grid and grid_filter modules done so far, and in trunk.

Thursday, February 11, 2010

CouchGrid Feature Completeness

So what we have here is the new CouchGrid that is really just a DictionaryGrid with an associated Grid filter. You can see Futon behind the test app with one of the records.

So here's the code to create the grid and filters and also persist the data in Desktopcouch:

dicts = [{"ID": 0, "key?": True, "tags": "aaa bbb ccc"},
{"ID": 1, "key?": False, "tags": "bbb ccc ddd"},
{"ID": 2, "key?": True, "tags": "ccc ddd eee"},
{"ID": 3, "key?": False, "tags": "ddd eee fff"},
{"ID": 4, "key?": True, "tags": "eee fff ggg"}]
database_name = "couch_widget_test"
record_type = "couch_grid_filter_test"
grid = CouchGrid(database_name, record_type=record_type, dictionaries=dicts)
filt = GridFilter(grid)
That really is all there is to it. Notice that the CouchGrid infers all of the keys from dictionaries that I passed in. That was a feature which I added back in today as well. I kind of forgot about it yesterday.

So I am assuming that there are all kinds of breakages now. I'll have to write some more test apps and some tests to make sure it is really all working perfectly. In the meantime, I've pushed it to trunk.

Speaking of trunk, I also accepted the first merge proposal in quickly-widgets today. James Tatum modified AsynchTaskProgessbox so that it passes a function that you can use to make the progress box increase in increments instead of just pulse. Nice!

Thanks for that James. He also fixed a bug or two while at it. Hopefully, I didn't bring those back today!

Wednesday, February 10, 2010

Closing the Photobomb Chapter, and Now Back To Quickly Widgets

Last week I stopped blogging because I was hanging with the Ubuntu Platform team at our every-mid cycle "release sprint". I didn't have any free time, too busy, so no time to blog.

However, just because I wasn't blogging, doesn't I haven't been getting some work done on my projects.

First, I did some work on photobomb, but using the new gwibber widget that kenvandine created. As you can see, it's much nicer looking, but also has built in protocol selectors. It's the same widget that Gwibber uses, in fact.

The code is much nicer as well. I deleted all of my code for displaying the widget and replaced it with this:
     poster = widgets.GwibberPosterVBox()
Just create a poster object and add it to your window or dialog. Sweeeeet! FTW! If you want to add the ability to broadcast to your app, that's it, literally a few lines of code.

Creating Photobomb has been fun, but it's time for me to turn my attention back to Quidgets for a while.

First thing is, Quidgets is no longer "Quidgets". It is now "Quickly Widgets", because it is in the package "quickly-widgets" which is now available in Universe, thanks to didrocks. The launchpad project is still called "Quidgets", but I'll probably change that soon as well.

In any case, I've been spending my extra time the last couple of days porting CouchGrid to Quickly Widgets. And by this I mean CouchGrid is now a subclass of DictionaryGrid and is part of the Quickly Widgets library. Deriiving CouchGrid from DictionaryGrid was a lot of work but it has a huge benefit. All the automagic persistence of CouchGrid, with all the Goodness of DictionaryGrid. So here's the test up showing that CouchGrid now handles all the same column types DictionaryGrid handles.
I haven't tested it with GridFilters yet, but it's good to save something for tomorrow night :) I had to change the internals of DictionaryGrid a bit, so I hope that apps that use it won't break when I update it. I'll test it out a bit first and see.

Next Up
Now that CouchGrid is substantially done, there is *a lot* of work I would like to do on the Quickly Widgets library. However, before I embark on that, I think it's time to document Quickly Widgets really well. I have had some thoughts about how to design the library (and some changes that causes) and also to document it. I'm thinking about doing a "document a day" kind of thing, where I document one part of the Quickly Widgets library each day.

While I was at the sprint Brian Murray demoed Bughugger to the platform team. The #1 request was for an offline mode. Well, seems that CouchGrid is perfect for that, and since a CouchGrid is really just a special DictionaryGrid, it should be pretty easy for me to add that capability. But I think I'll do the documentation first.