neděle 9. prosince 2012

Python SyntaxError: unexpected EOF while parsing

This error just popped on me after my development virtual machine crashed (grr). 
All I needed to do was remove all *.pyc and *.pyo files from my project (or at least from the package which fails to import). Everything was alright then.
You can use pyclean program which is usually installed together with python on debian / ubuntu.

sobota 1. prosince 2012

Python exception handling

Exceptions are a very useful and powerful tool. But they must be used carefully, especially in the Python. Recently, my python program stopped working. Hmm. Not exactly stopped. No exception was raised, but all values that should be correclty loaded from database were set to default value. 

After few hours of debugging and head scratching, I realized that the problem is in "pythonic" approach of setting default value for object attributes that do not exist.

Instead of testing object with hasattr, we can just try to access the searched attribute directly and catch the AttributeException if it does not exist. (btw. this is exactly what hasattr does, so it is more effective approach to do it directly)

The problems occurs when you implement data descriptors __getattr__ or __getattribute__ in your objects and underlying business code raise unexpected AttributeError (or it´s subclass) during data descriptor call.



In example above, if AttributeError (or it´s subclass) is raised during self.business.do method (line 4), except statement on line 8. will catch it and the error will disappear silently. 

Of course it is logical and understandable behavior. But! If you will not wrap your implementation of __getattr__ or __getattribute__ in try ... except AttributeError (which can re raise exception other than AttributeException), you will spend a lot of time in debugging later :-)

My last tip on the Python exceptions for today: Always specify most concrete exception class that you are willing do catch. If you decide to catch all ValueErrors intead of some concrete class YourBusinessValueException(ValueError), you have to count on with possibility that not only YourBusinessValueException will be raised and catched in your try ... except statement! That except statement can catch any exception which is subclass of ValueError. There can be plenty of them!

I hope I helped you. Feel free to leave comment!

středa 22. srpna 2012

Psycopg2 UnicodeEncodeError when using "psycopg2.extensions.adapt"

Just a little trick. If you are using Psycopg2´s adapt method to adapt your classes for usage in SQL statements (like this), you may run into problems with unicode strings.

Let´s say you have object which you would like to map to some composite PG type. Any string attribute which will contain unicode chars may give you exception like this (when called adapt and getquoted on it):

       .... some traceback .... 

       return adapted.getquoted()
UnicodeEncodeError: 'latin-1' codec can't encode characters in position 40-44: ordinal not in range(256)

It gave me few moments, but I found solution in this discussion. Because the encoding is passed through by connection object, it is necessary to call prepare methods on all adapted items (by adapted, I mean this: adapted = psycopg2.extensions.adapt(value)). 

When your class for adaptation is passed to psycopg´s execute, psycopg first try to call prepare if available. So in your class, you get real connection object by prepare method. Then, after calling adapt on attribute values, you can call prepare on them too. 

Little example. 


   1 from psycopg2.extensions import adapt, ISQLQuote
   2 
   3 class FooBarComposite:
   4         
   5         def __init__(self, foo, bar):
   6                 self.foo = foo
   7                 self.bar = bar
   8                 
   9         def __conform__(self, protocol):
  10                 if protocol is ISQLQuote:
  11                         return self
  12         
  13         def prepare(self, conn):
  14                 self._conn = conn
  15         
  16         def getquoted(self):
  17                 
  18                 adapted_foo = adapt(self.foo)
  19                 if hasattr(adapted_foo, 'prepare'):
  20                         adapted_foo.prepare(self._conn)
  21                 
  22                 adapted_bar = adapt(self.bar)
  23                 if hasattr(adapted_bar, 'prepare'):
  24                         adapted_bar.prepare(self._conn)
  25                 
  26                 result = adapt((adapted_foo, adapted_bar))
  27                 if hasattr(result, 'prepare'):
  28                         result.prepare(self._conn)
  29                 
  30                 return result.getquoted()


Now, class FooBarComposite can be used directly as an parameter of SQL statements and unicode attributes will work properly.

čtvrtek 19. dubna 2012

Recursive DOM walk with Dojo

Ever wanted to recursively walk all children of some DOM node? As far as I was looking for it, DOJO does not support this feature for now. 


With extend function from dojoj/_base/lang I was able to extend Nodelist class, so whenever I use dojo's brilliant query function, I have my custom walk method available.


Just save this as a module wherever you want and include (require) it when you need it.  

define(["dojo/query", "dojo/_base/lang", "dojo/NodeList-traverse",], function(query, lang) {

var NodeList = query.NodeList;

lang.extend(NodeList, {

_walk: function (node, func) {
func(node);
node = query(node).children().first()[0];
while(node) {
this._walk(node, func);
node = query(node).next()[0];
}
},

walk:  function (func) {
this.forEach(function (node) {
this._walk(node, func);
}, this);
}
});

return NodeList;
});

Example of usage:

define([
"dojo/query",
"dojo/NodeList-traverse",
"./NodeList-walk", // !!! your NodeList-walk module
], function(query) {
query('.selector').walk(function(elm) {
console.log(elm)
});
});


Hope you like it! If you find any bug, just let me know in comments.


You can test this on http://jsfiddle.net/joshuaboshi/qpvMn/

středa 18. dubna 2012

Setting "blockNodeForEnter" for EnterKeyHandling plugin of Dijit/Editor

You might run into a problem when you would like to change default behaviour of Dijit Editor. By default, when user presses enter key in Dijit Editor, only <br /> tag is generated. What if you want to encapsulate text into <p> tags or <div> tags?


Writing post filter was not helpful (probably because EnterKeyHandling plugin processing was fired after post filter, but I am not sure about this). So I opened /dijit/_editor/plugins/EnterKeyHandling.js and the solution was right in front of me:
// This plugin has three modes:
//
// * blockNodeForEnter=BR
// * blockNodeForEnter=DIV
// * blockNodeForEnter=P
//
// In blockNodeForEnter=P, the ENTER key starts a new
// paragraph, and shift-ENTER starts a new line in the current paragraph.
Now the only problem: How to change default mode from BR to P? Where can it be done?


Constructor of EnterKeyHandling states:

if("blockNodeForEnter" in args){
args.blockNodeForEnter = args.blockNodeForEnter.toUpperCase();
}
We are close to finish! How to pass custom args when invoking this plugin? The Dijit Editor has array "plugins" in which are stored all plugins for editor. Invocation of these plugins is done in "addPlugin" method.


The magic is done on this line:
var args=lang.isString(plugin)?{name:plugin}:lang.isFunction(plugin)?{ctor:plugin}:plugin;
This line can be translated as: if passed plugin is string, us it as plugin name (for plugins like "bold", "italic" etc.). If passed plugin is function, it is considered to be dojo Class and is used as constructor ({ctor:plugin} part). And anything else is just passed as is.
The args variable is passed to plugin constructor few lines later. 


So! We can add custom object to plugins array of editor that will look somehow like this:

{
ctor: EnterKeyHandlingPlugin,
blockNodeForEnter: 'P'
}
Easy huh? Very unfortunate that this is undocumented or not easy to find :/
Complete example:


require([
"dijit/Editor",
"dijit/_editor/plugins/EnterKeyHandling",
        "dijit/_editor/plugins/LinkDialog",
        "dijit/_editor/plugins/FullScreen"
], function( DijitEditor, DijitEditorEnterKeyHandling) {
var editorConfig = {
plugins: [
"bold",
"italic",
"|",
"cut",
"copy",
"paste",
"|",
"createLink",
"fullscreen",
{
ctor: DijitEditorEnterKeyHandling,
blockNodeForEnter: 'P'
}
]
};
var editor = new DijitEditor(editorConfig);
}); 



čtvrtek 5. dubna 2012

Extending dojo standard modules

New dojo 1.7 is awesome. I really enjoy working with it. The new AMD modules let you do things easy and straightforward in javascript.


When you will developing some webapp, you will come across the situation when you will need to extend some dojo basic functionality.  For example I needed function for removing items from array at one particular index.


My first attempt was pretty straightforward and dumb.  I created new function in the module where I needed it:


define([
"dojo/_base/lang",
"dojo/_base/array",
...
], function(lang, array, ...) {

function removeFromArray(array, index) {
/* implementation */
}

/* rest of the module */

});

Few moment later, I needed same function in another module. Copy/paste is not a good idea, not even saying, that it is not good to have this kind of function in absolutely unrelated module. The solution is pretty elegant and easy. I just created a new module "my/extendedArray" that looked like this:


define([
"dojo/_base/lang",
"dojo/_base/array",
], function(lang, array) {

lang.mixin(array, {
remove: function (arr, indexToRemove) {
/* implementation */
}
});

return array;
});

Now, whenewer I need these extensions, I just switch "dojo/array" for "my/extendedArray" in the define or require. Anything else from "dojo/_base/array" works normally and I have available my own extensions in array module!

Of course, you can extend anything in dojo by this way. You just have to pick right extension mechanism - mixin, extend, or classy inheritance :-)



úterý 14. února 2012

Rady pro budoucí vysokoškoláky obecně a studenty VUT FIT zejména

Často si říkávám, že jsem spoustu věcí co se týče studia měl udělat jinak. Jsou to věci, které vám nikdo většinou neřekne... no, a pokud řekne, stejně mu nevěříte. S tím druhým nepomůžu, ale s tím prvním se alespoň můžu pokusit něco udělat.

Rada 1.
Alespoň rok strávit na kolejích. Na privátě je to taky super, ale není to ono. Já šel v prváku rovnou na privát s bývalými spolužáky ze střední. Hned o příležitost míň se s někým novým seznámit... a upřímně, na VUT FIT už těch příležitostí později moc není. Na privát se stejně jednou z koleje odstěhuješ. Cenově to vyjde většinou úplně nastejno.
Rada 2.
V průběhu studia si nehledat práci ani brigádu. Peníze jsou jak droga. Jak si jednou zvyknete na něco víc než příděl od rodičů, budete těžko přežívat. Já měl v prváku od rodičů stovku na den (na jídlo a další věci). Nic moc, ale dalo se to přežít. No a když se šlo chlastat, tak sem pak byl o hladu nebo poprosil o zvláštní příděl :D Prostě to nějak šlo. Po prvním roce jsem si našel práci. Krásný peníze. Ale jak zase postupně začala škola, projekty, cvičení, zkoušky, musel sem si pořád snižovat úvazek (z plnýho na poloviční, z polovičního na dohodu s X hodinami týdně). Na přednášky jsem přestal chodit, škola mě přestala bavit, neměl jsem páru o čem se vlastně snažím učit a těch peněz už taky nebylo tolik jak jsem byl zvyklý z prvních výplat. Ale asi nejhorší je volný čas. Skoro žádný mi nezbýval. Pokud jsem nedělal projekty, pracoval jsem a pokud jsem ani nepracoval, byl jsem většinou tak akorát zralej do postele. Kvůli spěchu do práce jsem zameškal podle mnohých nejlepší roky života :( Fuuuuu. 
Asi si můžeš myslet že vystudovat bez praxe není zrovna dobrý, ale na praxi je času dost. Ať už v magisterským studiu, nebo ještě později. A navíc, studenti VUT FIT o práci vážně nouzi nemají a prakticky každá firma vezme absolventa bez praxe. 
Rada 3.
Nejspíš u každého studenta nastane období, kdy ztratí motivaci pokračovat. Důvodů může být více. Člověk začne myslet na to, že bývalí spolužáci se základky a střední (kteří nešli studovat) už mají pomalu založené rodiny, jezdí ve vlastních autech, bydlí ve vlastních bytech či domech... a ti úspěšnější podnikají, nevědí co s penězi a několikrát do roka jezdí na dovolenou atd. To člověku dokáže vážně rozhodit morálku. 
Nebo člověk zjistí, že mu ten titul, za kterým se tak urputně žene, bude ve výsledku vlastně na nic. Nebo ještě hůře, že těžce vydřený titul bude ve výsledku úplně stejný jako titul ze soukromé školy, kde se tituly prodávají bez práce. 
V tuhle chvilku je na každém, najít si tu správnou motivaci, která přebije všechny ty závistivé hlasy volající po spravedlnosti. Pokud člověk neporušil radu č. 2 a žije důkladný studentský život, je to určitě vhodný argument pro pokračování ve studiu, protože něco takového už nikdy v životě nebude mít příležitost zažívat. Mě už teď zbývá si jen říkat "ty roky dřiny a nervů nezahodíš".
Rada 4.
Nevázat se. Ať už prací, nebo domácím mazlíčkem nebo čímkoliv jiným. Studium na vš je jedinečná příležitost cestovat. Když se vám podaří zkoušky v prvních termínech, můžete mít až 4 měsíce letních prázdnin. Ale i více, pokud v zimním semestru nejsou cvičení a přednášky jsou nepovinný. Ideální příležitost procestovat Ameriku nebo jinou zemi s work and travel (kde si na náklady většinou vyděláte). Taky má každý student možnost studovat jeden semestr (nebo i dva) na zahraničních školách díky programu ERASMUS. Studenti VUT FIT mají kvůli nízkému zájmu prakticky neomezený výběr škol a vezmou většinou kohokoliv kdo má zájem.  A celej tenhle super výlet vyjde docela levně protože na to škola slušně přispívá. Nevyužít těchhle příležitostí ať už kvůli strachu z neznámého, nebo kvůli nějakým závazkům je vážně hloupost.
Rada 5.
Nenechat se zlákat možností opravných termínů. Tohle je na VŠ opravdu čiré zlo. Na každou zkoušku jsou většinou 3 pokusy. Pokud nedáte ani na třetí pokus, předmět opakujete a máte znovu 3 pokusy. Pokud nedáte ani ty 3 pokusy  - konec zvonec. Zdá se to hodně - 6 pokusů. A možná to zbytečně hodně opravdu je. Protože to pak člověka láká. 
Pokud se jako každý jiný učí teprve pár dní před zkouškou a už je vážně unavený, není nic jednoduššího než si říct - však jsou ještě 2 termíny, to nějak dám. Tenhle přístup většinou praktikují studenti na školách kde se zkoušky píší (nezkouší se ústně) a tedy neriskují, že ze sebe udělají voly před zkoušejícím. 
Tenhle přístup má mouchy. 1) Většinou jsou první termíny jednodušší než další termíny. 2) alespoň na VUT FIT platí že každý další školní rok musí být prestižnější než ten předchozí. A tady se velice jednoduše může stát, že z předmětu který byl v pohodě (kvůli lenosti ho opakujete), se stane zabiják studentů kvůli aktualizovaným osnovám, závěrečným zkouškám atp. 3) pokud se nahromadí několik opakovaných předmětů, vzniknou problémy o kterých člověk dopředu moc nepřemýšlí - musí se znovu dělat ty samé projekty, laboratoře, vychází více zkoušek v jeden den. Důsledky můžou být katastrofální - vyhazov. Jen FIŤákům bych chtěl poznamenat, že při opakování projektů je musíte udělat opravdu celé znovu! Nelze odevzdat projekt z minulého roku. Což je fakt opruz. Abych to ještě uvedl na pravou míru - projekty si lze také nechat uznat, ale většinou je stanoven minimální počet bodů který je uznáván. 
Rada 6.
Souvisí s radou 5. Neplýtvejte s časem, který vám stát dal na bezplatné studium. Studium bakaláře je státem hrazeno po dobu 4 let. Bakalářské studium trvá 3 roky. Tedy rok rezerva. Do toho času se ale započítávají i veškerá předchozí neúspěšná studia. Vyplýtvat tedy podporu není až tak nereálné. Já jsem první rok bakaláře studoval na VUT FEKT, po roce jsem znovu zkusil přihlášku na VUT FIT. Tedy mi zbývaly jen 3 roky podpory na bakaláře. Tento semestr jsem si jako čtvrťák poprvé platil zimní semestr - něco přes 9000,- a ještě budu platit letní semestr (znovu 9000,-). Další věc, kterou si také člověk uvědomí až později: vaši bývalí ZŠ, SŠ spolužáci většinou již budou mít Bc. a budou pracovat na diplomové práci (aspoň ti co šli studovat). A to je otrava. Nakonec, je docela možné, že si stejně jako já začnete připadat trochu staří na to všechno okolo. Nikdy předtím jsem si svůj věk neuvědomoval jako teď a připadá mi, že vším proplouvám strašně rychle a vše co jsem někdy chtěl mít na dosah se mi spíš vzdaluje. Mám ale dojem že tohle je dáno především tím, jak jsem si to všechno stihl podělat a taky z části samotným FITem, který na projektech sežere hodně času.
Rada 7.
Zejména pro FIŤáky. Dávejte si bacha na týmové projekty. Na bakaláři VUT FIT je (nebo alespoň za mě bylo) několik předmětů s týmovými projekty. Už je to skoro klišé, ale - pohlídejte si svého kolegu / své kolegy. V okamžiku kdy se vám bude zdát, že někdo svou roli nezvládá, okamžitě to řešte. Já sám jsem kvůli týmovému projektu (IFJ) málem vyletěl a několik mojich kolegů dokonce doopravdy vyletělo. Nejhorší na tom je, že to není vyhazov kvůli vaší chybě, ale kvůli chybě někoho jiného a nikoho z profesorů to většinou moc nezajímá. 
Rada 8.
By měla být naprosto zřejmá - dostatečně dopředu si zjistěte informace o zapsaných předmětech a podle toho se přizpůsobte. Nehodláte chodit na přednášky? Ok, ale pak se ujistěte že se budete mít z čeho učit na zkoušky (tzn. existence kvalitní a aktuální opory / skript, dostupné záznamy přednášek). Zjistěte si (např. z minuloroční úspěšnosti) jak náročný je předmět (jak těžké je získat zápočet, jak náročné jsou jednotlivé termíny zkoušky atp.) - není nic horšího, než věnovat příliš mnoho času lehkému / nenáročnému předmětu na úkor nějakého náročnějšího (vyhazovacího).
Rada 9.
Soukromá studentská fóra (fituška pro FIT) bývají největším zdrojem dezinformací. Je to super mít možnost společně řešit loňská zadání zkoušek. Ale jak už se mi mnohokrát potvrdilo, jeden student napíše blobost a dalších 20 mu to s klidem potvrdí. Připravovat se pouze a jen na základě informací z takového fóra je často cesta do pekel a mě se to již několikrát vymstilo.  


To bude prozatím vše. Doufám, že sem další rady vycházející z mých chyb už nebudu muset připisovat :-)