/srv/irclogs.ubuntu.com/2010/03/04/#ubuntu-classroom.txt

=== ChanServ changed the topic of #ubuntu-classroom to: Welcome to the Ubuntu Classroom - http://wiki.ubuntu.com/Classroom || Support in #ubuntu || Upcoming Schedule: http://is.gd/8rtIi || Current Session: NBS and how to keep the archive fresh - Instructor: persia || Questions in #ubuntu-classroom-chat
=== ChanServ changed the topic of #ubuntu-classroom to: Welcome to the Ubuntu Classroom - http://wiki.ubuntu.com/Classroom || Support in #ubuntu || Upcoming Schedule: http://is.gd/8rtIi
=== mohi_away is now known as mohi1
jonodpm about set?16:58
dpmjono, ready to roll16:58
jonoyou rock :)16:58
dpm#community rocks!16:59
jono:)16:59
=== ChanServ changed the topic of #ubuntu-classroom to: Welcome to the Ubuntu Classroom - http://wiki.ubuntu.com/Classroom || Support in #ubuntu || Upcoming Schedule: http://is.gd/8rtIi || Event: Ubuntu Opportunis tic Developer Week - Current Session: Hot rodding your app for translations support - David Planella - Instructor: dpm || Questions in #ubuntu-classroom-chat
dpmhello everybody!17:00
dpmWelcome to today's first session of Ubuntu Opportunistic Developer Week17:01
dpmlet's just wait a couple of minutes, to see that everyone gets here...17:02
dpmI should also remind you that today is a snippets day17:03
dpmof which you'll find all details here: https://wiki.ubuntu.com/PythonSnippets17:03
dpmThere'll also be a snippets party in #ubuntu-app-devel later, so be sure to join the fun!17:04
dpmAnyway, without further ado...17:04
dpm[SLIDE 1]17:04
dpmWelcome to this session on Hot rodding your application for translations support17:05
dpmIn the next hour we'll talk on how to get your app ready to speak a multitude of languages17:06
dpmand set up so that our awesome translation teams can do their work17:06
dpmFor those who are not using Lernid, here's a direct link to the slides in this session: http://people.ubuntu.com/~dpm/Quickly-i18n.pdf17:06
dpmThis talk will be based on quickly as the framework to opportunistically create your application in no time17:07
dpmparts of the talk were contributed by didrocks, Didier Roche, who's the main quickly developer17:08
dpmLet's start having a quick look at the main players involved in the internationalization game:17:08
dpm[SLIDE 2]17:09
dpm== GNU Gettext ==17:09
dpmGettext is the underlying and most widely used technology to enable translations of Open Source projects.17:09
dpmIt defines a standard format of translation files translators can do their work with (PO files)17:09
dpmand lets applications load those translations compiled in a binary format (MO files) at runtime.17:09
dpmIt has implementations for many programming languages, and amongst them, of course, Python.17:10
dpmYou'll find that the comprehensive gettext manual at http://www.gnu.org/software/gettext/manual/gettext.html can be a very useful reference,17:10
dpmThe Python implementation of the gettext API is what we'll use to internationalize our project with Quickly today.17:10
dpmNeedless to say, it also comes with some nifty documentation at http://docs.python.org/library/gettext.html17:11
dpm== intltool ==17:11
dpmIntltool is a higher level tool that adds functionality to gettext by allowing the extraction of translatable strings from a variety of file formats17:11
dpmIt has also become a standard tool when implementing internationalization for OSS projects. Nearly all (if not all) GNOME projects, for example, use intltool.17:11
dpm== python-distutils-extra ==17:12
dpmPython-distutils-extra is a python package that makes it easy to integrate themable icons, documentation and gettext based translations in your python install and build tools, and it's basically an enhancement to python-distutils.17:12
dpmThe project's page is at http://www.glatzor.de/projects/python-distutils-extra/17:12
dpmThe three above technologies (gettext, intltool, python-distutils-extra) are transparently used by quickly, so we won't get into much more detail for now.17:12
dpmThere are also more aspects involved in internationalizing applications, such as font rendering, input methods, etc., but this should get you started for now.17:13
dpm== Quickly ==17:13
dpmI'll be very brief here and let you figure out more on quickly as we go along17:14
dpmFor now, it will suffice give you a teaser and tell you that it is the tool which brings back the fun in writing applications!17:14
dpm== Launchpad Translations ==17:14
dpmLaunchpad Translations ( https://translations.launchpad.net/ ) is the collaborative online tool which allows translation communities to be brought together and translate applications online through its web UI.17:15
dpmApart from the very polished UI to provide translations, it has other nice features such as message sharing across project series (translate one message in a series and it instantly propagates to all other shared series),17:15
dpmglobal suggestions (suggestions of translations across _all_ projects in Launchpad), automatic imports of translations and automatic commits to bzr branches, several levels of permissions, and a huge translator base.17:15
dpmOn the right hand side of the URL I gave you you can see that there are quite a lot of projects using Launchpad to make translations easy both for developers and translators.17:16
dpmOk, enough theory, let's have a go at using quickly to create your first internationalized application17:16
dpmYou can install Quickly on Karmic or Lucid simply by executing 'sudo apt-get install quickly'17:17
dpmor if you are brave, you can try the trunk version (bzr branch lp:quickly)17:18
dpmlet's focus on the stable version, though17:18
dpm[SLIDE 3]17:19
dpmYou should see an overview of quickly here17:19
dpmQuickly has two parts: the core, which basically parses your input and templates.17:20
dpmTemplates are sets of commands and code generators that are designed to work together in an end to end fashion to help developers write a certain kind of application.17:20
dpmwith templates, you can then create application or document set.17:21
dpmWe'll focus there only on i18n with the first template that Quickly 0.2 provides: ubuntu-project (renamed ubuntu-application on the coming 0.4 release!)17:21
dpm(this template is using Glade, couchdb, has some nice trick for gedit, use bzr, and complete integration with LaunchPad and debian packaging)17:21
dpmFor instance, Lernid that some of you may be using, was created with the ubuntu-project template. (http://www.jonobacon.org/?p=2258 for a shot of the story)17:22
dpm[SLIDE 4]17:22
dpmSo, let's create first a simple ubuntu-project (assuming you are using Quickly 0.2, the stable version):17:22
dpmYou can run this:17:22
dpm    quickly create ubuntu-project fooby17:22
dpmthis tells Quickly to use the ubuntu-project template, and to call what is created "fooby"17:23
dpmThis causes a bunch of info to be dumped to the command line, but ends with the application being run17:23
dpmWhat Quickly did was to copy over basically a sample application, and do some text switcheroos to customize the app17:23
dpmYou can see there the ui which contains some text that needs translation.17:23
dpmTo start making change to your app, cd to it (normally,17:23
dpm    cd fooby17:24
dpmYou can then edit your code with $ quickly edit, change the UI with $ quickly glade, and try your changes with $ quickly run17:24
dpmYou can save your change with $ quickly save17:24
dpmchanges17:24
dpmFinally, to package, share, release your apps so that other will be, with the following commands (not all are necessary): $ quickly package / $ quickly share / $ quickly release17:25
dpmI won't cover in any more detail Quickly or the ubuntu-project template here (quickly help <command> does this for you),17:25
dpmyou can find more info at: https://wiki.ubuntu.com/MeetingLogs/devweek0909/QuicklyFun17:26
dpmLet's see what you can do in "quickly edit" and "quickly glade": adding internalization support to your app17:26
dpmAs the project stands now, it has the infrastructure for internationalization in place, but we have to initialize it to enable it.17:26
dpmThis will include:17:27
dpm * Initializing gettext17:27
dpm * Marking strings for translation17:27
dpm * Updating the translation template17:27
dpm[SLIDE 5]17:28
dpmFirst of all, we'll initialize gettext, which will basically be adding four lines of code. Here's how it goes:17:28
dpm    quickly edit17:28
dpmThis will open all your project files in a text editor (Gedit by default)17:28
dpm1. Go to the fooby file and add the following two lines below 'import gtk', near the top of the file:17:28
dpm    import gettext17:28
dpm    import locale17:28
dpmThis will import the required modules for internationalization17:29
dpm2. Still on the fooby file, add the following line below the 'import logging, optparse' one, near the end of the file:17:29
dpm    gettext.install('fooby', unicode=True)17:29
dpmThis will install the _() function to mark (and call) translations as such in Python's builtins namespace, based on the 'fooby' domain. The domain basically tells gettext where to load translations from.17:29
dpmThis will also save you to include 'import gettext' statements in all of your project files using gettext. This will do for your first application17:30
dpmRefer to the gettext documentation to find out more about translation domains.17:30
dpm3. Finally, add the following line to 'fooby', before the 'builder = gtk.Builder()' line17:30
dpm    locale.textdomain('fooby')17:30
dpmThis will tell GtkBuilder about the translation domain as well17:30
dpmSo that was it! Let's move on to marking strings for translation:17:31
dpmFirst of all we'll tackle the .destop file17:31
dpmOpen the fooby.desktop.in file and prepend the Name and comment fields with an underscore (_), so they look like:17:31
dpm    _Name=Fooby17:31
dpm    _Comment=Fooby application17:31
dpmThis will tell intltool that this strings contain translations17:32
dpmNext comes the UI. Let's see how you can mark strings in the UI for translation. Try:17:32
dpm    quickly glade17:32
dpmThis will open your UI files in the glade editor.17:32
dpmOnce opened, click on the "Your application has been created! ..." label, find it in the General > Label field on the right, click on the ellipsis (the three dots) button and...17:32
dpmamaze at the fact that it has already been marked as "Translatable", so you won't have to do anything.17:33
dpmRight, so next comes something very important that you'll have to bear in mind for all strings you'd like to be translatable in your application:17:33
dpm * using the _() function call.17:33
dpmThis will mark them as translatable and call gettext to load the translations, and should be used for all messages you'd like to present to users.17:33
dpmLet's just see how we can do this.17:34
dpmGo back to your fooby file and find the "parser.add_option("-v", "--verbose", action="store_true", dest="verbose", help="Show debug messages")" line near the bottom.17:34
dpmWe want the "Show debug messages" message to get shown to users in their language, so we'll enclose it with the _() function, and it will look like:17:34
dpm    parser.add_option("-v", "--verbose", action="store_true", dest="verbose", help=_("Show debug messages"))17:34
dpmNow we're done17:35
dpmThe last part will be to update the translations template.17:35
dpmA translations template is a formatted text file generally named yourproject.pot17:35
dpmwhich contains your project's translatable strings in English and is what translators use as a basis for their translations.17:35
dpmYou should do this at least before each release, so that translations are put in this template and are up-to-date for translators to work on.17:36
dpmIt is considered good practice to announce a string freeze (that is, the period in which strings are considered to be stable) a week or two before the release, so that translators know when they can start their work.17:36
dpmThis can be done in several ways with quickly, let's pick one:17:36
dpm    quickly package17:36
dpmAfter running this, you'll notice that (apart from having your application packaged!) there is a 'po' folder containing the translation template, ready for translators to work on.17:37
dpmIf you open it, you'll notice the format and will see that all the strings you marked for translation are there.17:37
dpmYou can also do this with 'quickly share', 'quickly release' or directly using the python-distutils-extra command: './setup.py build_i18n'17:37
dpm== Launchpad Translations ==17:37
dpmIf this weren't awesome enough, once you've created a project in Launchpad ('quickly share', 'quickly release' or https://help.launchpad.net/ will help you on that) you can expose it for the world to translate17:38
dpmso that you as a developer can use the automatic bzr import/export features to basically "forget" about translations and translators can use the web UI to translate.17:38
dpmLet me tell you a bit more on those:17:39
dpm[SLIDE 6]17:39
dpm== Automatic imports ==17:39
dpmEnabling this feature will allow you to automatically import the translation template for your application into Launchpad upon commit, with no further steps required.17:39
dpmSo the basic workflow will be: hack, hack, hack, update template, commit, have translators automagically see the new strings in Launchpad.17:39
dpmYou can find more about this at http://blog.launchpad.net/translations/import-translation-templates-from-your-projects-bazaar-branches and http://blog.launchpad.net/general/trying-out-launchpad-translations17:40
dpmor at http://blog.launchpad.net/translations/screencast-importing-translation-templates-from-a-bazaar-branch17:40
dpm== Automatic exports ==17:40
dpmWith automatic exports, you'll be able to complete the whole circle for automation: getting translations committed automatically (daily) to a bzr branch of your choice, so that neither you nor translators have to worry to get translations into your project.17:41
dpmI personally find this one of the most coolest features17:41
dpmHere's more info: http://blog.launchpad.net/general/exporting-translations-to-a-bazaar-branch17:41
dpmAnd here's a screencast on how to enable it http://blog.launchpad.net/translations/screencast-exporting-translations-to-a-bazaar-branch17:41
dpm== Permissions ==17:42
dpmOne very important aspect is how you want translations permissions for your project to be. This basically means choosing who will be responsible for submitting and reviewing those17:42
dpmtranslations for each language.17:42
dpmLaunchpad is flexible in allowing different levels of openness for translating your project.17:42
dpmThis generally means that you as a maintainer will have to make a decision to balance openness (open translations for everyone) with quality control (a more closed process with reviewers and a QA workflow).17:43
dpmThe Launchpad help page on permissions at https://help.launchpad.net/Translations/YourProject/PermissionPolicies explains very well the different permissions you can use (Open, Structured, Restricted and Closed).17:43
dpmIf you decide for quality, you'll next have to choose to whom you assign the translation of your project.17:43
dpmHere is where translation groups come to the rescue.17:43
dpmTranslation groups are confederations of translation teams, one for each language you can assign as a pack to translate your project.17:44
dpmThe teams in those groups are considered to be trusted to have experience with translations and generally have a review process in place.17:44
dpmHere's a list of all current translation groups: https://translations.launchpad.net/+groups17:44
dpmYou can see that the two biggest ones are Launchpad Translators and Ubuntu Translators.17:44
dpmWhile you can create a translation group specific to your project, we generally encourage maintainers to choose one of the existing ones,17:45
dpmin order to reuse the pool of translators and not to further fragment translations communities.17:45
dpmI personally recommend choosing Restricted (or Structured), assigned to the trusted Launchpad Translators or Ubuntu Translators (if your project is Ubuntu-specific) translations groups17:45
dpm[SLIDE 7]17:45
dpmI'll rapidly go through quickly's incoming features and then we can do some Q&A17:46
dpmQuickly 0.4 will bring a lot of new experiences and commodities to the users (more than 200 commits, 6 months of hard work!) and will be delivered in Lucid.17:46
dpmRegarding internationalization, all the tedious job of importing/initalizing gettext and adding _() will be done for you in all newly created apps.17:47
dpm"$ quickly add pythonfile" will also add one boiler plate file containing that for you.17:47
dpmQuickly 0.6 later on will try to achieve the automatic imports and exports previously described on each $ quickly share / $ quickly release command.17:47
dpmSo, normally, you won't have to bother anymore about localization and being in sync with the awesome work of your contributors17:48
dpmjust mark strings with _()17:48
dpmSo that was it!17:48
dpmQuestions?17:48
dpm<gnunezr> QUESTION: How does one get the translation files for each language from the .pot file?17:51
dpmThat's usually the work of translators17:51
dpmwhen you've committed the .pot file to your bzr branch, and it is exposed in Launchpad with automatic imports17:51
dpmtranslators will see the translatable strings in Launchpad and start doing their work17:52
dpmif you've got automatic exports activated, the PO files will be created for you whenever there is a new translation, and committed to your branch of choice17:53
dpmSo, in short, as a maintainer this will happen automagically for you :)17:53
dpmkeep them coming :)17:54
dpmO I see, gnunerz is asking:17:55
dpmQUESTION: I get that... I'm just curious as to how does the manual process goes :)17:55
dpmif you were not using Launchpad, you'd announce that there is a new POT file available, and translators would fetch it, create a PO file containing the translation for their language, and would send it back to you17:56
dpmThe same process: translators always take care of translations, but with a bit more manual work for all people involved17:56
dpmSo, in shourt, I'd recommend using Launchpad and automatic import/export17:57
dpm<alucardni> QUESTION: It is possible to define which languages I want my app be translated to?17:57
dpmNo, in general you want your application to be available in as many languages as possible, and Launchpad allows translating in almost any language17:58
dpmYou might be able to limit which translations are build in your project's build infrastructure17:58
dpmBut you'll have to explicitly set it up to use just some of the translations17:59
dpm<gnunezr> QUESTION: Does this process also take care of locale stuff, like how is the date presented to the users?17:59
dpmin general, yes17:59
dpmbut we'd need another session to go into the details :)18:00
dpmbasically, the app must set up the locale settings right on initialization18:00
=== ChanServ changed the topic of #ubuntu-classroom to: Welcome to the Ubuntu Classroom - http://wiki.ubuntu.com/Classroom || Support in #ubuntu || Upcoming Schedule: http://is.gd/8rtIi || Event: Ubuntu Opportunistic Developer Week - Current Session: Learning through examples with Acire and Python-Snippets - Jono Bac - Instructor: jono || Questions in #ubuntu-classroom-chat
jono:)18:01
jonoalrighty18:01
jonothanks dpm18:01
jonoisn't that man such a freaking rock star?!18:01
jonoeveryone needs to give him a hug in #ubuntu-classroom-chat :)18:01
* jono hugs dpm18:01
jonohi everyone and welcome to the python snippets session at Ubuntu Opportunistic Developer Week!18:01
jonohow are we all doing today?18:02
jonothe focus of this session is some work I have been doing recently around building a library of python snippets and (a) how this library can be useful for you as an opportunistic developer, but also (b) how you contribute to it to make it an even better resource!18:02
jonoso, let's get started18:03
jonoI have always been the kind of person who learns via examples18:03
jonowhen I started learning the guitar, I learned by watching other guitarists play, and when I started learning Python and how to build apps on Ubuntu, I have always learned by hunting out little source code examples that do what I need to do and then learning from them and merging them into my programs18:03
jonothe problem is that these snippets were scattered all over the Internet and sometimes pretty hard to find18:04
jonomy dream was to have a program that would bring these snippets together into a library so that I could select them, run them and learn from them18:04
jonowell, on a flight home from England at Christmas, armed with those small bags of peanuts and a few gin and tonics, I decided to write this little program and it is called Acire, named after my wife's name backwards (Erica)18:05
jonoAcire is a really simple program that provides an interface to this library of snippets18:05
jonolet's look at how it works18:06
jonocheck out http://farm5.static.flickr.com/4045/4406908674_2934c4d5c0_o.jpg18:06
jonothis is a screenshot of the main Acire interface18:06
jonoin the top-left part of the window there is a drop-down combo box that lists a series of categories of different snippets18:06
jonowhen you select a category, the list of snippets that are in that category are listed below18:07
jonoin the screenshot you can see the list of snippets that are in the Python Core category: that is, snippets that demonstrate features in the main Python language18:07
jonoto see a snippet you just click on it and it appears in the code view to the right, all nicely syntax highlighted so you can read it easily :-)18:07
jonorunning the snippet is simple, just click on the Execute button18:08
jono<LakomLacen33> how come i don't have python core in my acire ?18:08
jonowe had a few out of date python-snippets packages - you might have an old package18:09
jonoembedded in the window is a little terminal view: this is important for snippets that don't have a GUI (such as the Python Core snippets) - if you select a GUI snippet the window will appear when you click the Execute button18:09
jonorunning the snippet gives you a good chance to play with it and see how it works and then take a look at the snippet code in the window18:09
jonoanother feature is that you can edit the snippet code and when you hit Execute it will run your modified program too: this makes it really easy to play with the snippet inside Acire itself - you can then click the Save As button and save the code somewhere else if you like18:10
jonowe already have a bunch of snippets in Acire: 104 right now (as you can see in the status bar)18:10
jonohere is the current list of categories18:11
jonohttp://farm5.static.flickr.com/4050/4406908744_d75cbac80f_o.jpg18:11
jonoif you are curious what my wallpaper is, it is the most awesome duck ever - http://www.flickr.com/photos/w9ned/3563985252/sizes/l/in/pool-1058695 :-)18:11
jonoanyway, back to the screenshot: http://farm5.static.flickr.com/4050/4406908744_d75cbac80f_o.jpg18:12
jonoas you can see, it is pretty cool: it provides a really nice resource for looking at a bunch of python examples and it helps you to learn quickly and easily and solve problems right away18:12
jonolet me now explain how to get it18:13
jonoI have deliberately split the actual python snippets from the graphical interface - this was because many people may want to produce viewers for the snippets (e.g. a KDE version, a web interface etc) so I did not want to depend on the GUI18:13
jonoas such, we have two projects:18:13
jonoacire - the graphical interface to the snippets available at http://www.launchpad.net/acire18:14
jonopython-snippets - the library of snippets available at http://www.launchpad.net/python-snippets18:14
jonothe first thing we want to grab are the snippets18:14
jonopart of my goal here is to make sure that the library of snippets is regularly updated as more snippets are made available18:15
jono<nvsbl> how can i get the latest version of acire?18:15
jonoI will explain in just a moment :)18:15
jonofortunately, we have an awesome technology for doing this - Personal Package Archives (PPA) - a place in which you can subscribe to a package and you get regular updates18:15
jono<sam90> is acire going to be available in Lucid?18:16
jonoit runs on Lucid now :)18:16
jonoso, we have a PPA that generates a daily package of the latest python-snippets library18:16
jonoryanprior, nope, what was it?18:17
jono QUESTION: can we add snippets in languages other than Python?18:17
=== yofel_ is now known as yofell
jonono, Acire and python-snippets is focused on Python18:17
jonoalthough I would love to see other languages have a similar project :)18:18
jonoso, we have a PPA that generates a daily package of the latest python-snippets library18:18
jonoadding the PPA is simple, just click Applications -> Accessories -> Terminal and add these commands:18:18
jonosudo add-apt-repository ppa:python-snippets-drivers/python-snippets-daily18:18
jonosudo apt-get update18:18
jonosudo apt-get install python-snippets18:18
jonothis will add the snippets to /usr/share/python-snippets18:19
jonoyou now need to install Acire to view them18:19
jonowe also have a PPA for this too18:19
jonoI recently kicked out a new release, but I haven't had a chance to provide a Karmic package yet, so the new release is just in Lucid right now - the PPA still has the older release though, so this still works18:20
jonojust follow these steps:18:20
jonoclick Applications -> Accessories -> Terminal (or use the Terminal in Lernid!) and add these commands:18:20
jonosudo add-apt-repository ppa:acire-team/acire-releases18:20
jonosudo apt-get update18:20
jonosudo apt-get install acire18:20
jonoall of the instructions for doing this are on https://wiki.ubuntu.com/PythonSnippets18:21
jonook, so let's now get to the question about running the latest bleeding edge Acire18:21
jonosome of you may want to grab the latest code for Acire and run it - this is also really simple, just follow these commands:18:21
jonoclick Applications -> Accessories -> Terminal (or use the Terminal in Lernid!) and add these commands:18:22
jonofirst install all the packages requires to run it:18:22
jonosudo apt-get install bzr python-desktopcouch-records python-gconf python-gtk2 python-gtksourceview2 python-vte quickly18:22
jonothis will grab everything you need18:22
jonoit may take a little while to grab everything, but not too long :)18:22
jono<evrick> :'( no amd6418:23
jonoyeah, but the 32-bit version should run I imagine18:23
jonoor you can follow these instructions18:23
jonook18:23
jonofirst install all the packages requires to run it:18:23
jonosudo apt-get install bzr python-desktopcouch-records python-gconf python-gtk2 python-gtksourceview2 python-vte quickly18:23
jononext, let's grab the code18:23
jonoagain, this is really simple thanks our pal, bzr:18:23
jonojust type in:18:23
jonobzr branch lp:acire18:23
jonothis will grab the latest acire code from Launchpad18:24
jonowhen it has got the code, now enter the directory:18:24
jonocd acire18:24
jonoand then run it:18:24
jonoquickly run18:24
jono<alucardni> A few broken dependencies in Karmic :(18:25
jonoyeah we had a few issues with dependencies, but you can solve them by making sure you run this line:18:25
jonosudo apt-get install bzr python-desktopcouch-records python-gconf python-gtk2 python-gtksourceview2 python-vte quickly18:25
jonothat will get everything you need18:25
jonoand you obviously need to ensure the python-snippets PPA is installed, as I described above18:25
jono:)18:25
jonothis will then get you up and running :)18:26
jonoawesome to see you folks getting it up and running :)18:26
jononow, today is an exciting day as we are really keen to encourage you folks to join us in making a bunch of python snippets today to add to the library18:26
jonothis resource is only as useful as the snippets inside it, so I am really keen to crowdsource this and have any many people as possible join in and contribute snippets18:27
jonoright now we have 104 snippets18:27
jonomy dream for today is that we hit the 150 mark :)18:27
jonoyou folks interested in helping?18:27
jonointeresting in helping to make this rock?18:27
jono:)18:27
jonowe welcome snippets on *any* python module18:27
jonoso if you can do *something* in python, you could write a snippet18:28
jonowhether it is as simple as doing something to a list or using a module such as feedparser18:28
jono<ryanprior> QUESTION: should snippets for a given package (like PyGTK for example) live in python-snippets, or in pythin-gtk2-doc, or where?18:28
jonogreat question ryanprior18:29
jonolet me explain how the snippets are organized18:29
jonook18:30
jonotake a look at http://bazaar.launchpad.net/~jonobacon/python-snippets/trunk/files18:30
jonothis is a list of the content in the main python-snippets archive right now18:30
jonoas you can see, there are a bunch of directories18:30
jonoeach directory refers to a particular python module18:31
jonoas an example, the gstreamer dir has snippets that use the GStreamer multimedia framework18:31
jono<ryanprior> This seems like a great opportunity for upstream involvement. We can help people with their documentation.18:32
jonoexactly! :)18:32
jonoinside each dir lives the snippets18:32
jonoso if we click on the gwibber dir:18:32
jonohttp://bazaar.launchpad.net/~jonobacon/python-snippets/trunk/files/head:/gwibber/18:32
jonothere is one snippet18:32
jonogwibber is a python module that ships in Lucid that allows you to microblog right from your app18:33
jonoso the snippet we have is sendmessage.py18:33
jonoyou can see it at http://bazaar.launchpad.net/~jonobacon/python-snippets/trunk/annotate/head:/gwibber/sendmessage.py18:33
jonoand that explains how in just a few lines of Python you can tweet, dent, Facebook etc18:33
jonoso in a nutshell the library of snippets is in /usr/share/python-snippets and in there are subdirs, each of which refers to a python module, and the snippets about that module live in there18:34
jonoso let me explain how a snippet is mad18:34
jonomade18:34
jonoa snippet is just a piece of code that demonstrates something18:35
jonobut what allows us to categorize and show it in Acire are some comments at the top18:35
jonolet's use http://bazaar.launchpad.net/~jonobacon/python-snippets/trunk/annotate/head:/gwibber/sendmessage.py as an examoke18:35
jonoexample18:35
jonothe comments with 'SNIPPET' in them are what Acire uses for index and show them18:35
jonohere are the different lines:18:35
jono[SNIPPET_NAME: Send a message]18:35
jonothis is the text that appears in the sidebar when you have select a snippet category18:36
jonoa short, sharp description of the snippet18:36
jono[SNIPPET_CATEGORIES: Gwibber]18:36
jonothis is a tag for the snippet18:36
jonothis is the category that appears in the drop-down box18:36
jonosnippets can have multiple categories separated by commas if needed18:37
jonowe have a main list of categories in the CATEGORIES file in the main /usr/share/python-snippets dir18:37
jono[SNIPPET_DESCRIPTION: Send a message using the Gwibber API]18:37
jonothis is the description that appears under the code - a longer description of what the snippet does18:37
jono[SNIPPET_AUTHOR: Jono Bacon <jono@ubuntu.com>]18:38
jonothis is who wrote it with their email address18:38
jono[SNIPPET_LICENSE: GPL]18:38
jonoand this is the license18:38
jonoagain, a standard set of licenses are in the LICENSES file in /usr/share/python-snippets18:38
jonoI am happy to accept snippets into the library so long as they use a recognized free software license18:38
jonoso created a snippet is simple:18:39
jono 1. pick which dir it should be in (or create a new one if your snippet is the first for a given python module)18:39
jono 2. write the snippet18:39
jono 3. include these comments at the top18:39
jono 4. submit it :)18:39
jonosubmitting a snippet is explained on https://wiki.ubuntu.com/PythonSnippets18:40
jonoso today we are having a snippets part18:40
jonoparty18:40
jonothis is a session in #ubuntu-app-devel where I am encouraging folks to submit snippets for inclusion :)18:41
jonoso this is a great opportunity to join and get involved and share your knowledge18:41
jonothe snippets party takes place at 9pm UTC18:41
jonoand will go on for a few hours, so do come along and join us - it is really cool seeing a snippet that you made show up in the library for everyone to learn from18:42
jonodo you folks want me to explain how you contribute a snippet?18:42
jonook cool :)18:43
jonoso first run:18:43
jonobzr branch lp:python-snippets18:43
jonothis will grab the python-snippets library18:43
jononow go in and add your snippet18:43
jonoyou can add it to an existing directory in there if the snippet is about one of those topics18:43
jonoor feel free to create a new dir for a python module that is not covered in the library yet18:44
jonowhen you create your snippet make sure you have the comments at the top of the file18:44
jonoe.g:18:44
jono# [SNIPPET_NAME: Playing a Pipeline]18:44
jono# [SNIPPET_CATEGORIES: GStreamer]18:44
jono# [SNIPPET_DESCRIPTION: Construct and play a pipeline]18:44
jono# [SNIPPET_AUTHOR: Jono Bacon <jono@ubuntu.com>]18:44
jono# [SNIPPET_LICENSE: GPL]18:44
jono<raven_99> i'm seriously learning a lot this week. contributing as a developer actually seems possible now.18:44
jonothat is awesome! :D18:44
jonowhen you have added your snippet, add it to the local library with:18:45
jonobzr add your-snippet.py18:45
jonoobviously replace your-snippet.py with the filename for your snippet18:45
jononow commit your changes:18:45
jonobzr commit18:45
jonowhen you run the above command you can enter a short message about what your snippet does18:46
jononow you need to upload the snippet to Launchpad:18:46
jonobzr push lp:~<your launchpad username>/python-snippets/<name of your branch>18:46
jonoso an example if I was to upload this I might use the following command:18:46
jonobzr push lp:~jonobacon/python-snippets/new-gstreamer-snippet18:46
jonofinally,  go to https://code.launchpad.net/python-snippets and you should see your branch listed there. Click on it and when the branch page information page loads click on the Propose for merging link. Add a short description of what you examples do in the Initial Comment box and then click the Propose Merge button.18:47
jono<titeuf_87> QUESTION: is it possible to run acire and make it look in that directory for snippets instead of the default one?18:48
jonoright now, no, but I am adding a feature to do that18:48
jonowhat you can do is set up a symbolic link from /usr/share/python-snippets to wherever you checked out the python-snippets code18:49
jono<alucardni> QUESTION: Can we use Ground Control to submit a new snippet?18:49
jonoabsolutely!18:49
jonoso what I recommend you folks do is check out the python-snippets library, add a snippet and submit it and I can test if it works in Acire18:50
jonomeanwhile I will get as feature into Acire to point it at another directory so it is easier to test it18:50
jonoso we have our snippets party at 9pm UTC, that is two hours away - I recommend you all come along to #ubuntu-app-devel and join us and I can help you get started writing snippets :)18:51
jonoany more questions?18:51
jono<evrick> How about adding snippets as design patterns or algorithms?18:52
jonoabsolutely! we have a Patterns dir for design patterns18:52
jonoI would love an algorithms dir too18:52
jonoI am keen to ensure that *all* python snippets are welcome18:52
jonoif they run and they explain how to do something, I will make sure we add it :)18:52
jonoany more questions?18:53
jono<ryanprior> QUESTION: if I run a snippet in Acire and it crashes, does that bring Acire down too?18:53
jonousually no18:53
jonoif it does crash Acire, that is a bug and we need to fix it :)18:54
jono<lsteeger> QUESTION: As Acire grows, how about adding some Search/Sort functions?18:54
jonoI am really keen to add that too18:55
jonoif someone wants to write a patch for this, do go ahead18:55
jonoI think Acire needs a search facility and a find facility for search snippets18:55
jono<jgbel> QUESTION: how do contributors handle python versioning idiosyncacies (e.g., 2.5 functions versus 3.x)?18:55
jonosnippets that need to care about Python versions typically do a test in the code18:56
jonothere are a few snippets that have examples of this18:56
jonoawesome18:56
jonoI think we are done18:56
jonothanks everyone for joining me here!18:56
jonoand I hope to see you all in #ubuntu-app-devel in two hours for the snippets party!18:57
jonorockstar, all good?19:00
=== ChanServ changed the topic of #ubuntu-classroom to: Welcome to the Ubuntu Classroom - http://wiki.ubuntu.com/Classroom || Support in #ubuntu || Upcoming Schedule: http://is.gd/8rtIi || Event: Ubuntu Opportunistic Developer Week - Current Session: Write Beautiful Code (and Maintain it Beautifully) - rockstar - Instructor: rockstar || Questions in #ubuntu-classroom-chat
=== Goomba is now known as Guest41661
rockstarjono, starting now?19:01
rockstarjono, starting now?19:01
jonoyep :)19:01
rockstarHi folks.  Apologies in advance for the Lernid users, but I'm not really a slide guy, so you'll just have to follow along.19:02
rockstarSo, dholbach asked me if I'd be willing to talk about writing beautiful code.19:03
rockstarThat puts me in a hard spot, since sometimes I write code that fell out of the ugly tree and hit every branch on the way dawn.19:03
rockstarAs I thought about it though, beautiful code is a process.  It's iterative, and the things you find beautiful now will (probably) be ugly to you in a year.19:04
=== yofell is now known as yofel
rockstarSo I began thinking about that process - this is what I'd like to chat about today.19:05
rockstarSince this is opportunistic developer week, I want to make this a story about opportunities.19:06
rockstarThe scenario I'd like to start with is this:19:08
rockstar"You've been using Ubuntu and you're feeling very comfortable.  You're in an IRC channel when someone says 'It would be nice if I had an app that would...'"19:08
rockstarUh oh.  There's not an app for that.19:08
rockstarBut guess what?  You're an opportunistic developer!  This is an opportunity!19:09
rockstarQUESTION: <JayFo> will you be going over some tips for making ugly code better? :)19:09
rockstarANSWER: Yes, as I said, making ugly code better is a process.  The process is the core of this talk.19:10
rockstarSo, we're going to start a new project.  In this scenario, staying away from ugly code is easy, since there's no ugly code to begin with.19:10
rockstarWhen you start a new project, you should get a few things together.  First, you need some version control system (Renaming files to .bak doesn't count)19:11
rockstarYou also should have an issue tracker, even if you haven't even released your code.  This may be as simple as a TODO file.19:12
rockstarLuckily, we have Launchpad.  Those Launchpad developers are awesome.  They do awesome things.19:12
rockstarYou'll also want a style guide.19:13
rockstarProgrammers have stolen the idea of a style guide from writers and journalists.  A style guide allows you to set some social contracts in how your code is structured.19:14
rockstarThis is a must.  If you don't have this right now in your project, your homework is to go out and establish one.19:15
rockstarEveryone has different tendencies in their code, so code can get messy as soon as more than one person touches it.19:15
rockstarQUESTION: <ylynfatt> I assume when you say style guide you mean the same thing as "coding standards"?19:15
rockstarYes, same idea.  You should have common idioms.19:16
rockstarDocument this well.  It makes life much better when contributors come aboard.19:16
rockstarQUESTION: <JayFo> QUESTION: are there any good sample style guides to start with?19:16
rockstarPython (my favoritest most bestedest language) has a language-wide style guide.19:17
rockstarIt's called PEP 8.19:17
rockstarhttp://www.python.org/dev/peps/pep-0008/19:17
rockstarBasically, it addresses where to put comments, how to name variables/classes/"constants"/functions/etc19:18
rockstar\sh kindly points out https://dev.launchpad.net/StyleGuides19:18
rockstarSo, on the Launchpad team, there is a style guide that supplements PEP 8, and then we have a style guide for our javascript, etc.19:19
rockstarI don't personally like some of the standard styles in the Launchpad team.  If I wanted, I could violate those styles, but then no one would approve the code review, and I'd never get anything done.19:20
rockstarThe "social contract" basically allows us all to come to the table with the same expectations for the quality of code.  That's what the style guide gives us.19:20
rockstar<somename> QUESTION: Kinda offtopic but is there a reason why space indentation is preferred to tab indentation in PEP 8?19:21
rockstarsomename, the BDFL of Python has spoken.19:21
rockstarThat question is actually quite on-topic.  Sometimes there's no other reason to have the rule than to just have a standard rule.  You can't have both, so there as a choice made.19:22
rockstarSo put together your style guides.  They won't be set in stone.  In fact, they'll be quite fluid.19:22
rockstarThe Launchpad team meets once a week to evaluate if style changes are needed.19:23
rockstarJust yesterday I proposed a change in style and everyone agreed.19:23
rockstarQUESTION: <theDtTvB2`MB> When there is a small bug that needs to be fixed real quick, I violate all the style guides and fix it as fast as I can. Does anybody have the same problem as me?19:23
rockstarI guess I don't know the specific situation, and sometimes you need to do some hacky things to get bugs fixed.  Your style guide shouldn't get in the way of your work.19:24
rockstarHowever, when you violate the guide, you're automatically making your code harder to read for others.19:25
rockstarThis actually brings me to my next point (thanks for the easy segway).19:25
rockstarIn whatever language you're working with, the code you write is not for the computer.19:25
rockstarThe computer is going to take that code, translate it into something it understands, and then run it.19:26
rockstarThe code you write is for humans like you and me.19:26
rockstarRemember that when you're writing the code.  Keep it in mind.  Read your code out loud.19:27
rockstarC-code, for me, is especially difficult to read aloud, but it helps me to see where something doesn't make sense.19:27
rockstarSince most documentation standards target US or UK English, your code should kinda make sense that way as well.19:28
rockstarSometimes (as in the case of asychronous code) you won't be able to write your code left-to-right/top-to-bottom19:29
rockstarUse comments in those cases.19:30
rockstarAlright.  We have about 20 minutes left.  In about 10, I'd like to take and review some "ugly code" that some of you would like to submit.  Please pastebin your examples of "ugly code" and then post them in the chat19:31
rockstarOkay.  So let's look at another situation, one that is more common, and will probably help you to be better when you actually start projects.19:32
rockstarYou're in IRC, and someone says "<App> is really cool, but it has a problem with <feature-x>"19:32
rockstarOpportunity awaits!19:33
rockstarOften, this is where I see "ugly" code, because it's not my code, and it's not in a style I understand immediately.19:33
rockstarIf the project has a style guide, read it before sleuthing to fix the problem.19:34
rockstarIf it doesn't, Thor help you.  :)19:34
rockstarAfter you're comfortable with reading the app's code (whether by style guide or fumbling around), find the code you want to work in.19:35
rockstarAs you write your feature, explore the idea of writing a test for that feature.19:35
rockstarMany languages have great test frameworks that you can use.19:36
rockstarTesting helps you to avoid embarrassment when (not if) your feature breaks.19:37
rockstarMake sure, as you write your patch, that you're sticking with common coding conventions.19:37
rockstarWhen I say "common" I mean "common the surrounding source code" - Make the code consistent.19:38
rockstarOnce you have your patch (and hopefully test), you're ready to show someone your code.19:38
rockstarThis step is the most important.19:39
rockstarYou're more likely to write ugly code when no one has to see it, and when you don't have to justify why it's ugly.19:39
rockstarI had a friend who worked as an intern on a proprietary mobile phone platform that said "You would hate this source.  It's terrible, because no one has to see it."19:40
rockstarOkay, so we submit our code for review.19:41
rockstarDoes anyone want to pastebin their ugly code?19:41
rockstarQUESTION: <tgalati4> Question first:  Are there any Python style (say PEP 8) checkers?19:42
rockstarYes.  On Launchpad, we use pylint (slow, annoying) and pyflakes (doesn't handle exceptions to the rule well)19:42
rockstarFor javascript (my second favoritest language) jslint is what I use.19:43
rockstarLet's look at the "ugly code" here: http://pastebin.com/1jWRpKCG19:44
rockstarThanks to theDtTvB2`MB for putting himself out there.  That's good.19:44
rockstarOkay, so this javascript code.19:45
rockstarJavascript is notorious for being a wild west "every man for himself" language.  It's easy to write messy code, it's easy to write code that leaks memory.19:45
rockstarSo as a reviewer, I'm first going to ask what "r" on line 4 is.19:46
rockstar"r" doesn't tell me anything about the variable, what it contains, or what it's used for.19:46
rockstarNeither does "c" or "is_DM"19:46
rockstarThat makes this code hard to follow.19:47
rockstarI also don't have very many comments.19:49
rockstarLine 53 is actually succinct and rather helpful.19:49
rockstarBasically, are we starting with the first item in the index?19:50
rockstarI also am not entirely clear on what the function returns.  It returns a few different things, depending on specific conditions.  A comment at the top of the function would go miles in helping understand what's going on.19:52
rockstarI rather like jsdoc, and having been using it in my javascript gaming engine I've been working on.19:52
rockstarBy documenting, you help other young developers to start off knowing what the function is doing, and then they can use that context as they read the code.19:53
rockstar<theDtTvB2`MB> And now I starting to forget what some of these line do.19:53
rockstartheDtTvB2`MB, this is why we strive to write beautiful code.19:53
rockstar:)19:54
rockstarAny other questions?19:54
rockstarLet me point out a potential opportunity here: <tgalati4> Does Lernid have a search feature in the Session window?  That would help to jump to code.19:54
rockstarQUESTION: <theDtTvB2`MB> Does it need a rewrite?19:55
rockstarSo, rewrites can be scary, especially when you don't have tests (and sometimes even when you do).19:55
rockstarUsually, when I get into code I wrote that I have forgotten about, I will take some time to sleuth the code, remind myself, and then document the code, and sometimes make slight changes (variable names, etc.)19:56
rockstarSometimes code is unsalvagable, and you'll have to re-write it, but just be careful there.  You don't want to be KDE 4.0, do you?  :)19:56
rockstar<evrick> QUESTION: when does it makes sense to make code more generic (useful in many places). Or to make an abstraction to it?19:57
rockstarI would say that you should NEVER repeat code.  Never, ever, ever, never, ever.19:57
rockstarSometimes, abstractions are harder to understand, so you'll have to "glue" that with good comments.19:57
rockstarQUESTION: <tgalati4> So can I find good examples of python coding style by doing:  grep python /usr/bin/* ?19:58
rockstarSo, I'm not sure what that would give you.19:58
rockstarBazaar's source code is awesome for seeing good coding standards as well as ways to make python perform better.19:59
rockstarThey have some potentially difficult and crazy code that is commented with things like "we have to do this now, or the function won't return fast enough" and things like that.19:59
rockstarAny more questions?20:00
=== ChanServ changed the topic of #ubuntu-classroom to: Welcome to the Ubuntu Classroom - http://wiki.ubuntu.com/Classroom || Support in #ubuntu || Upcoming Schedule: http://is.gd/8rtIi || Event: Ubuntu Opportunistic Developer Week - Current Session: Speed your development with quickly.widgets - Rick Spencer - Instructor: rickspencer3 || Questions in #ubuntu-classroom-chat
rockstarThanks folks!20:00
rickspencer3hi all20:01
rickspencer3shall we dive into quickly-widgets?20:01
rickspencer3or maybe you need some time to recover from that stellar class by rockstar20:01
rickspencer3ok, I guess I'll get started20:03
rickspencer3ok20:03
rickspencer3my code is ugly20:03
rickspencer3but functional ;)20:03
rickspencer3as usual I put my class notes on the wiki20:03
rickspencer3https://wiki.ubuntu.com/UbuntuOpportunisticDeveloperWeek/Quidgets20:03
rickspencer3so, quickly-widgets started as a personal side project of mine20:04
rickspencer3and it got totally out of control20:04
rickspencer3at some point I discovered it was writing itself at night20:04
rickspencer3the goal of quickly widgets is to make PyGtk programming more easy and fun20:04
rickspencer3PyGtk is a fantastic UI tool kit20:04
rickspencer3It is very powerful, functional, and flexible20:04
rickspencer3However, at the moment, it lacks some higher order abstractions that developers have come to expect20:05
rickspencer3The result being that developers have to write reams of code using multiple classes and such for things that are more simple in other frameworks20:05
rickspencer3for example, popping dialogs, putting data into a grid and such20:05
rickspencer3so I'm hoping quickly-widgets can fill in some of these use cases20:05
rickspencer3please note that quickly-widgets is very early in development and experimental20:05
rickspencer3this means that it is to be buggy and incomplete20:05
rickspencer3or at least I strongly suspect that it is20:06
rickspencer3but it also means that if you want to, you can have a lot of influence on how it develops20:06
rickspencer3so bug reports and branches, more than welcome20:06
rickspencer3btw20:06
rickspencer3so what is Quidgets?20:06
rickspencer3"Quidgets" is the original name of quickly-widgets20:06
rickspencer3it was a silly name20:06
rickspencer3I made it up without really thinking20:06
rickspencer3the project is still called Quidgets20:06
rickspencer3so you can get the code:20:06
rickspencer3$bzr branch lp:quidgets20:06
rickspencer3quickly-widgets is currently in universe for Lucid20:06
rickspencer3(this scares me a bit, but what the heck ;) )20:07
rickspencer3it is not packaged for Karmic20:07
rickspencer3though if someone wanted to do that, I would not complain too much ;)20:07
rickspencer3currently, quickly widgets has two modules20:07
rickspencer3quickly.prompts20:07
rickspencer3and quickly.widgets20:07
rickspencer3quickly.widgets has some general widgets20:07
rickspencer3but also some widgets for displaying data, basically extending TreeView and making it simpler to use20:07
rickspencer3I'll discuss each of these three areas in a bit more depth20:07
rickspencer3But first, Questions?20:08
ClassBotoskude asked: does quickly-widgets work with or without glade (the editor) ?20:08
rickspencer3currently there is no glade integration20:08
rickspencer3I don't think it would be too hard to add this, but it hasn't been tackled yet20:08
rickspencer3I think to do this would require crafting a library file in XML20:08
rickspencer3but then also making sure the properties were properly setable in the glade propery editor20:09
rickspencer3Before we look at the modules, a word on the mental model of using quickly-widgets20:09
rickspencer3There are 3 "levels" to consuming quickly-widgets20:09
rickspencer3Most of the time, you should be fine with the first level, which is the "Use" level20:09
rickspencer3At this level, you just make a one-liner that uses the API and does something useful20:09
rickspencer3like, get as string from the user:20:10
rickspencer3quickly.prompts.string("My Title","Give me a string","default val")20:10
rickspencer3or maybe you want do display the data in a dictionary:20:10
rickspencer3dg = DictionaryGrid(my_list_of_dicts)20:10
rickspencer3dg.show()20:10
rickspencer3see, you just go ahead and "use" the classes20:10
rickspencer3sometimes you want to tweak something a bit. In these cases you go to the configure level.20:10
rickspencer3When you are doing "configure" you might end up a using the underlying PyGtk API a bit20:10
rickspencer3For example, a dictionary grid is really just a Treeview20:10
rickspencer3So if you want to configure the title for a column, you might go20:10
rickspencer3dg.get_columns()[0].set_title("New Title")20:11
rickspencer3some of the configuration might be done in the quickly.widgets library though20:11
rickspencer3like if you want to display certain keys from your dictionary, you can use a list of keys to display20:11
rickspencer3keys = ["key1","key2']20:11
rickspencer3dg = DictionaryGrid(my_dict,keys=keys)20:11
rickspencer3I'll talk about the specifics here a bit later20:11
rickspencer3but the point is, you can go beyond the one liner if you need to20:11
rickspencer3so if you start with the one liner, but then need to expand out a bit20:12
rickspencer3you don't throw away your code, just add some "configure" code20:12
rickspencer3let's say you get back a feature request from a user or customer, and you need to do something that is not suppported by quickly-widgets through using or configuring20:12
rickspencer3well, quickly-widgets strives to consume PyGtk in such a way that you can extend classes as needed to accomplish your goals20:12
rickspencer3for example, if you want a grid that displays data from a certain SQL database somewhere, you can inherit from DictionaryGrid and add the SQL functionality.20:12
rickspencer3This is exactly what CouchGrid does, but for generally desktopcouchy things20:12
rickspencer3So, before I discuss using the prompts a bit, any questions?20:12
ClassBot\sh asked: which audience did you have in mind when you started Quickly?20:13
=== AndChat is now known as Guest68634
rickspencer3well, fundamentally I was scratching my own itch20:13
rickspencer3I was working on bughugger and thought ...20:13
rickspencer3"I cannot believe I am writing this same TreeView code *again*"20:13
rickspencer3I vowed at that moment to never craft a TreeView again20:14
rickspencer3though I don't mind writing code that writes TreeViews ;)20:14
rickspencer3beyond me, I am thinking about application writers on Ubuntu20:14
rickspencer3so I don't mind making some distro specific assumptions20:14
rickspencer3ultimately, I am thinking about folks who, like me, often can visualize and app, and want to get straight to the fun part20:15
rickspencer3without bothering with all the boiler plate of a powerful library like Gtk20:15
rickspencer3more questions?20:15
rickspencer3ok20:16
rickspencer3prompts20:16
rickspencer3Prompts are basically dialogs that you can use to interact with the user without writing too much code20:16
rickspencer3rather than creating a PyGtk dialog or similar yourself, and then populating it, for certain scenarios a prompt in quickly-widgets can take care of it for you20:16
rickspencer3the prompts module is right under quickly, so you can get it like this:20:16
rickspencer3from quickly import prompts20:16
rickspencer3or just quickly.prompts.string() if you want20:16
rickspencer3there are three kinds of prompts20:16
rickspencer3the first kind just displays info the the user20:16
rickspencer3these take a couple of strings from you and display a message box to the user with the appropriate icon20:16
rickspencer3so, you can go20:17
rickspencer3prompts.error("Title for the Error Dialog","Error text")20:17
rickspencer3this will pop up a little dialog that says "Error text"20:17
rickspencer3with a dialog error icon next to it20:17
rickspencer3there is also prompts.warning and prompts.info20:17
rickspencer3they works the same as error20:17
rickspencer3The next kind of prompt collects some info from the user20:17
rickspencer3the kind of prompts built in of this kind are:20:18
rickspencer3string, date, integer, decimal, and price20:18
rickspencer3they all take care of displaying an appropriate widget for the user input for you20:18
rickspencer3like a textbox for a string, a calendar for a date, and a spinner appropriately formatted if appropriate20:18
rickspencer3they let you set a title, a message, a default value, and in the case of the numeric ones some other defaults if you want20:18
rickspencer3the functions all return a gtk.RESPONSE and a value20:18
rickspencer3make sure you check the response because if the user cancelled, you want to do the right thing20:18
rickspencer3so to get a string, go:20:19
rickspencer3response, val = quickly.prompts.string()20:19
rickspencer3if response == gtk.RESPONSE_OK:20:19
rickspencer3 #do something with val20:19
rickspencer3where val is a string20:19
rickspencer3you can get a date in the same way20:19
rickspencer3when dealing with date values are tuples in the form of integers for (year,month,day)20:19
rickspencer3where month is zero indexed (Jaunary is 0, December is 11)20:19
rickspencer3and you use tuples for the default value in teh same way20:20
rickspencer3so:20:20
rickspencer3response, date = quickly.widgets.date("Title String","Enter your birthday",(1968,03,22))20:20
rickspencer3so that's *April* because the months are zero indexed20:20
rickspencer3if you want to get an integer, you can set min_value, and max_value as well20:20
rickspencer3if you look at the doc string, you can see other options as well20:20
rickspencer3decimal and price are also rich in options20:20
rickspencer3price is just decimal, but with 2 decimal places set20:20
rickspencer3however, they all work basically the same way, response, val = function()20:20
rickspencer3if you need to configure the prompt a bit more, for each function, there is a symetrical class that you can use20:21
rickspencer3so for string(), if you want to own the dialog for some reason, you can use StringPrompt20:21
rickspencer3sp = StringPrompt(title, text, default_string)20:21
rickspencer3then you can party on sp if you want20:21
rickspencer3there is a similar dialog for date, integer, decimal, and price20:21
rickspencer3each has a "get_value()" function to extract the value20:21
rickspencer3The last set of prompts are FileChooserDialogs20:21
rickspencer3they work the same way20:21
rickspencer3response, path = quickly.prompts.choose_directory(title)20:22
rickspencer3there is choose_directory, save_image_file, and open_image_file20:22
rickspencer3there are classes for these as well20:22
rickspencer3DirectoryChooserDialog, OpenImageDialog, and SaveImageDialog20:22
rickspencer3these lack get_value, because they are just subclasses of FileChooserDialog20:22
rickspencer3which already has a get_filename() function20:22
rickspencer3before I talk about the gtk.Widgets, any questions?20:22
ClassBottgalati4 asked: I noticed that quidgets is only packaged for Lucid, no Karmic.  Any plans?20:23
rickspencer3I'm not planning this myself20:23
rickspencer3but I would be happy to work with anyone who wanted to do this20:23
rickspencer3btw, I should have mentioned that the package name is quickly-widgets in universe20:24
rickspencer3alright20:24
rickspencer3moving on to quickly.widgets20:24
rickspencer3for widgets, there are a few miscelaneous ones, and then the grid related ones20:24
rickspencer3I'll start with the miscelaneous ones20:24
rickspencer3the most miscelaneous one is20:24
rickspencer3from quickly.widgets.camera_button import CameraButton20:24
rickspencer3CameraButton wraps up the PyGame web cam API and serves up pixbufs20:25
rickspencer3I don't like how this is implemented at the moment, and am planning to pull it into it's own package for a while, until I can make it work well20:25
rickspencer3however, it's kinda fun when it works20:25
rickspencer3there's also a subclass of button called PressAndHold button20:25
rickspencer3this one is quite useful and functional20:25
rickspencer3this guy fires a signal every 250ms, so long as the user is holding the button down20:25
rickspencer3so this allows you to do something while the user is holding down a button20:26
rickspencer3I use this in photobomb to manage rotation of times for example20:26
rickspencer3first, create the button, then connect to the signal20:26
rickspencer3        button = PressAndHoldButton()20:26
rickspencer3        button.connect("tick",action)20:26
rickspencer3then write a function that does something every time the signal fires20:26
rickspencer3def action(self, widget=None, data=None):20:26
rickspencer3 #do something every 250ms20:26
rickspencer3for photobomb "something" is selected_item.rotate() or such20:27
rickspencer3the last misc. quickly.widget is20:27
rickspencer3from quickly.widgets.asynch_task_progressbox import AsynchTaskProgressBox20:27
rickspencer3in general, you should avoid threads in your python app20:27
rickspencer3you should use things like gobject.timeout_add() or gobject.idle_add()20:27
rickspencer3and the gio library20:27
rickspencer3however, for times when you absolutely must use a thread AsynchTaskProgressBox can make it easier for you20:27
rickspencer3this derives from gtk.ProgressBox, so it supplies some throbbing UI for you if you need it20:27
rickspencer3the basic idea is to write a function that you want to run on a thread20:28
rickspencer3I usually call this a task20:28
rickspencer3create a dictionary of parameters if you want to pass some params to the function20:28
rickspencer3create the AsynchTaskProgressBox20:28
rickspencer3if you want to know when the task is done, connect to the complete event20:28
rickspencer3here's some photobomb code for example20:28
rickspencer3params = {"directory":directory}20:28
rickspencer3pb = AsynchTaskProgressBox(self.__load_task, params, False)20:28
rickspencer3pb.connect("complete",self.__load_task_complete)20:28
rickspencer3for your task, you can simulate a killable thread (in python you can't really kill a thread, just wait for it to end)20:28
rickspencer3if every20:29
rickspencer3if *ever* even20:29
rickspencer3you do this by checking a special key that is added to params called "kill"20:29
rickspencer3if it's set to True, you can stop working20:29
rickspencer3here's a bit of code from photobomb to demonstrate20:29
rickspencer3    def __load_task(self, params):20:29
rickspencer3        pictures_dir = params["directory"]20:29
rickspencer3        images = []20:29
rickspencer3        files = os.listdir(pictures_dir)20:29
rickspencer3        for f in files:20:29
rickspencer3            try:20:29
rickspencer3                if params["kill"]:20:29
rickspencer3                    return None20:29
rickspencer3                #etc....20:29
rickspencer3So the last bit about quickly-widgets is about Grids and Filters and stuff20:29
rickspencer3before I do that, any questions so far?20:29
ClassBotstevec33 asked: Why is it best to avoid threads?20:30
rickspencer3 because the implentation in Python leaves a lot to be desired20:31
rickspencer3 like there is a global lock and scuh20:31
rickspencer3 they are not true threads that get deployed and run seperately on CPUs and such20:31
rickspencer3 but mostly, it's really hard to write code that does not have bad bugs in it20:31
rickspencer3this is especially true with PyGtk20:32
rickspencer3you have to call threads_enter() and threads_leave() and all this when updating the UI20:32
rickspencer3or it goes quite haywire20:32
rickspencer3ok20:33
rickspencer3on to grids20:33
rickspencer3lots of the code in quickly-widgets is about presenting data to users in a TreeView20:33
rickspencer3in PyGtk, gtk.TreeView handles both displaying grid data and data in trees20:33
rickspencer3quickly-widgets focuses on the Grid20:33
rickspencer3and totally ignores the tree case20:33
rickspencer3trees are UI elements where there are nested nodes with those little disclosure triangles and such20:34
rickspencer3so, grids20:34
rickspencer3the essentially scenario is that you have some tabular data to display20:34
rickspencer3gtk.TreeView can let you display this in any manner you like20:34
rickspencer3so long as you:20:34
rickspencer31. Create a TreeView20:34
rickspencer32. Cerate a treeview model store of some kind20:34
rickspencer33. create columns20:34
rickspencer34. create cellrenders for each column20:34
rickspencer35. popluate the treeview model20:34
rickspencer3each of these steps taking multiple lines of code *per column*20:35
rickspencer3and this does not include letting users change the values in the grid20:35
rickspencer3filtering20:35
rickspencer3adding data after it is created, etc...20:35
rickspencer3from quickly.widgets.dictionary_grid import DictionaryGrid tries to handle this for you in essentially, one line of code20:35
rickspencer3the basic interaction is that you create a DictionaryGrid by handing it a list of dictionary, and it makes a TreeView for you20:35
rickspencer3you just show it and add it to your form20:36
rickspencer3Here's a bit from the dictionary grid test program20:36
rickspencer3first, a list of dictionaries20:36
rickspencer3dicts = [{"key?": True, "price":0.00,"tags" : "aaa bbb ccc","_foo":"bar","bing count":20},20:36
rickspencer3                 {"ID": 11, "key?": False, "price":2.00,"tags" : "bbb ccc ddd","_foo":"bar"},20:36
rickspencer3                 {"key?": True, "price":33.00,"tags" : "ccc ddd eee","_foo":"bar","bing count":15},20:36
rickspencer3                 {"ID": 3, "tags" : "ddd eee fff","_foo":"bar"},20:36
rickspencer3                 {"ID": 4, "price":5.00,"_foo":"bar"}]20:36
rickspencer3then, create the DictionaryGrid:20:36
rickspencer3grid = DictionaryGrid(dicts)20:36
rickspencer3seriously, that;s all it takes to show the data in the dictionaries to a user20:36
rickspencer3if you want the user to be able to edit the grid, set it to editable:20:36
rickspencer3grid.editable = True20:37
rickspencer3note that setting some of the properties, including editable will cause the grid to reset itself20:37
rickspencer3if it's editable, the user can change the data in the dictionary20:37
rickspencer3there are some properties that you can use to extract the data20:37
rickspencer3like20:37
rickspencer3grid.rows20:37
rickspencer3this gives you all the rows20:38
rickspencer3where as20:38
rickspencer3grid.selected_rows gives you the currently selected row20:38
rickspencer3some handy functions you get for free, like20:38
rickspencer3grid.remove_selected_rows()20:38
rickspencer3remove_selected_rows20:39
rickspencer3oops20:39
rickspencer3you can add to your grid by appending rows20:39
rickspencer3grid.append_row(my_dict)20:39
rickspencer3if you want to add an empty row20:39
rickspencer3append_row({})20:39
rickspencer3then if the grid is editable, the user can fill itin20:39
rickspencer3by default, the grid will display a column for every key it encounters UNLESS that key starts with "__" (two underscores), in which case it will be ignored20:40
rickspencer3if you want to control the keys displayed, you can do this when you create it:20:40
rickspencer3grid = DictionaryGrid(dicts,list_of_keys)20:40
rickspencer3or you can set the keys later20:40
rickspencer3grid.keys = list_of_keys20:40
rickspencer3this causes the grid to reset, btw20:40
rickspencer3Columns will sort properly most of the time20:40
rickspencer3this is accomplished by having each column be a certain type20:40
rickspencer3there is the default StingColumn, but there is also IntegerColumn, CurrencyColumn, TagsColumn, and CheckColumn20:40
rickspencer3by "extending" GridColumn you can create your own column types if you need to20:41
rickspencer3DictionaryGrid tries to guess the right column type to use based on the name of the key20:41
rickspencer3So if you choose your key names correctly, you can get a lot of good functionality for free20:41
rickspencer3for example, and key that ends with "?" DictionaryGrid will assume it is a boolean, and use CheckBoxes to show the values20:41
rickspencer3and provide the appropriate sortign for you20:41
rickspencer3the key "price" is assumed to be currency20:41
rickspencer3anything ending in count will be an IntegerColumn, same with a key called "id"20:41
rickspencer3a key called "tags" will be a tags column20:41
rickspencer3tags columns are mostly important for filtering, which I will discuss in a moment20:41
rickspencer3you can control the columntypes manually if you want, by passing in "Type Hints"20:42
rickspencer3here's some code from the tests:20:42
rickspencer3        keys = ["id","price","bool?","foo"]20:42
rickspencer3        hints = {"id":StringColumn, "price":IntegerColumn,20:42
rickspencer3                 "bool?":CurrencyColumn,"foo":CheckColumn}20:42
rickspencer3        dicts = [{"price":100,"id":"asdfas","bool?":10.01,"foo":True}]20:42
rickspencer3        grid = DictionaryGrid(dicts, keys, hints)20:42
rickspencer3in this case hints are overriding the defaults20:42
rickspencer3so I should talk about filtering next, but first, questions?20:42
rickspencer3I hope there are no question be my content is so riveting, and the clarity is so profound20:43
rickspencer3:)20:43
rickspencer3moving on ...20:43
rickspencer3so one cool thing about gtk.TreeView is the filtering capabilities20:43
rickspencer3Filtering even pretty long lists works really fast20:44
rickspencer3but this is a TON of work in PyGtk20:44
rickspencer3from quickly.widgets.grid_filter import GridFilter makes a filter UI for you20:44
rickspencer3this will let the user add filters to filter columns20:44
rickspencer3if you've seen the bughugger UI, then you have seen GridFilter and DictionaryGrid in action20:44
rickspencer3you just need to hand it a Grid to filter20:44
rickspencer3it will pick up filter types from the GridColumns in the Grid20:44
rickspencer3So for example columns with strings will get a filter with "contains substring" while a column with numbers will get ">,<.=", etc...20:44
rickspencer3a tags column gets "contains one of these tags", "contains all of these tags", etc...20:45
rickspencer3all this just by creating it:20:45
rickspencer3filt = GridFilter(grid)20:45
rickspencer3filt.show()20:45
rickspencer3if you want to override the default filter types, you can pass in hints20:45
rickspencer3this works pretty much like in the grid20:45
rickspencer3you pass in a dictionary that matches up keys to filter types20:45
rickspencer3well, actually to filter combos, but that's a bit more detail than necessary20:45
rickspencer3there are StringFitlerCombo, TagsFilterCombo, CheckFilterCombo etc...20:45
rickspencer3there is also blank filter combo that you can use to easily make your own filters20:46
rickspencer3for example, in bughugger I created a custom filter to filter status and importance like this:20:46
rickspencer3  sw_filter2 = BlankFilterCombo()20:46
rickspencer3  sw_filter2.append("=",lambda x,y: convert_to_num(x) == float(y) )20:46
rickspencer3  sw_filter2.append("<",lambda x,y: convert_to_num(x) < float(y) )20:46
rickspencer3  sw_filter2.append(">",lambda x,y: convert_to_num(x) > float(y) )20:46
rickspencer3  sw_filter2.append("<=",lambda x,y: convert_to_num(x) <= float(y) )20:46
rickspencer3  sw_filter2.append(">=",lambda x,y: convert_to_num(x) >= float(y) )20:46
rickspencer3filter_hints = {"status":sw_filter,"importance":sw_filter2}20:46
rickspencer3each call to append adds a string and a function call20:46
rickspencer3the function gets called when the users changes the filter in some way20:46
rickspencer3the function should return True to show the row20:47
rickspencer3or False to hide the row20:47
rickspencer3lastly I'll discuss CouchGrid20:47
rickspencer3but first, Questions?20:47
* rickspencer3 tap tap20:47
rickspencer3is this thing on?20:47
ClassBottgalati4 asked: Besides bughugger and photobomb, any other apps using quidgets that we can use for reference?20:48
rickspencer3I don't know20:48
rickspencer3I get a lot of questions about using the widgets20:48
rickspencer3but I haven't tracked what folks are doing with it20:48
rickspencer3sorry :/20:48
rickspencer3ok20:48
rickspencer3before we break, I'll touch on CouchGrid20:49
rickspencer3the flagship of the quickly-widgets package20:49
rickspencer3I feel this has been talked about a lot20:49
rickspencer3In Lucid, a CouchGrid is a DictionaryGrid20:49
rickspencer3this is different than the CouchGrid that was desktopcouch.records.couch_grid import CouchGrid20:49
rickspencer3in Lucid you get all the sorting and filtering of DictionaryGrid, plus persistance in desktopcouch20:50
rickspencer3you need to define a database and a record type20:50
rickspencer3if you want, you can pass in a dictionary with some starter data as well20:50
rickspencer3here is some code from the GridFilter test app20:50
rickspencer3    database_name = "couch_widget_test"20:50
rickspencer3    record_type = "couch_grid_filter_test"20:50
rickspencer3    hints = {}20:50
rickspencer3    grid = CouchGrid(database_name, record_type=record_type, dictionaries=dicts)20:50
rickspencer3    grid.show()20:50
rickspencer3    filt = GridFilter(grid,hints)20:50
rickspencer3    filt.show()20:50
rickspencer3this sets up a database for you20:50
rickspencer3if the databaes is there and there are records already20:50
rickspencer3it displays those for you!20:50
rickspencer3if there are new records it persists them for you20:51
rickspencer3so, that20:51
rickspencer3s the last bit of content I had planned20:51
rickspencer3Questions?20:51
rickspencer3okay20:53
rickspencer3so, if you're hacking and have questions, want to contribute20:53
rickspencer3etc...20:53
rickspencer3join #quickly any time and ask away20:54
rickspencer3again, the project is early, so feedback and contributions can have a big impact at this point20:54
rickspencer3this is community developed software, so it's there to be molded by the community :)20:54
ClassBottgalati4 asked: What's on the roadmap on quidgets?  What's the burning next todo item?20:54
rickspencer3thanks for the question tgalati420:55
rickspencer3next step is to get some feedback on the Grid related stuff20:55
rickspencer3and fix bugs20:55
rickspencer3I think that saves the most work there20:55
rickspencer3also, I'd like to make the web cam button good20:55
rickspencer3someone yesterday suggest gstreamer, I should give that a try20:56
rickspencer3also, there may be more file chooser dialogs for the prompts20:56
rickspencer3I'd like to add any widgets that folks like that they would like to find an upstream home for20:56
rickspencer3but one of the most immediate burning things for me is to write documentation20:56
rickspencer3please note that there is a fair amount of documentation already in the code itself20:58
rickspencer3and you can access this with pydocs20:58
rickspencer3thanks everyone!20:59
rickspencer3I'm looking forward to working with folks to make quickly-widgets more functional and more easy and more fun20:59
rickspencer3:)20:59
=== ChanServ changed the topic of #ubuntu-classroom to: Welcome to the Ubuntu Classroom - http://wiki.ubuntu.com/Classroom || Support in #ubuntu || Upcoming Schedule: http://is.gd/8rtIi
malevhey, where does the talks logs are stored?21:03
malevwhere are store the chat logos? (better this way)21:03
ausimagemalev there linked from the wiki paage with the schedule21:04
malevausimage: thanks!21:05
ausimageno21:05
ausimagenp21:05
ausimage:/21:05
ausimagefingers :S21:05
=== enli is now known as enli|away
=== jw is now known as Guest61922

Generated by irclog2html.py 2.7 by Marius Gedminas - find it at mg.pov.lt!