Unkillable zombie blog

This blog just won't die

Oct 16, 2009

Django generic relations in test fixtures

Το Django framework περιλαμβάνει μια λειτουργικότητα που την ονομάζει content types. Το content types framework επιτρέπει, μεταξύ άλλων, στο Django να έχει λειτουργίες όπως τα generic relations

Ο τρόπος λειτουργίας είναι σχετικά απλός. Το content types framework βασικά λέει:

Για κάθε μοντέλο του ORM φτιάχνω μια εγγραφή στον πίνακα django_content_type που περιέχει ,μεταξύ άλλων, το όνομα του application και το όνομα του μοντέλου και φυσικά ένα ID.

Το generic relationship επιτρέπει σε ένα μοντέλο να έχει ένα foreign key σε ένα οποιοδήποτε άλλο μοντέλο στο django. Αυτό το επιτυγχάνει προσθέτοντας 2 πεδία στο μοντέλο που περιέχει το foreign key. Το content type και το id.

Έστω οτι έχουμε ένα μοντέλο Comment. Μιας και θέλουμε το Comment μπορεί να μπορεί να αναρτηθεί σε διάφορα μοντέλα (πχ Story, άλλα Comments, News, Product κλπ) χρησιμοποιούμε generic relations. Αν ονομάζαμε το πεδίο αυτό “commenting_on” τότε όταν ζητήσουμε απο το django να μας δώσει το object στο οποίο δείχνει το commenting_on, το Django θα δεί το content_type πεδίο, θα αναζητήσει την αντίστοιχη εγγραφή στον πίνακα django_content_types και θα βρεί το application και model στο οποίο αναφερόμαστε. Γνωρίζοντας αυτά, και αφού έχει και το id μπορεί έυκολα να μας επιστρέψει ένα instance του μοντέλου.

Εδώ πρέπει να αναφέρω μιά ακόμα τεχνολογία του django. Το serialization framework που μας επιτρέπει να κάνουμε serialize και να εξάγουμε τα δεδομένα μας σε αρχείο κειμένου (YAML,XML, JSON και άλλα) όπως και να τα εισάγουμε στην βάση μας απο ένα serialized αρχείο.

Τα serialization είναι εξαιρετικά χρήσιμο σε πάρα πολλές περιπτώσεις, με πιθανότατα πιο συχνή το Testing framework, όπου μας δίνει την δυνατότητα πριν απο κάθε test να φορτώνουμε κάποια γνωστά δεδομένα στην database.

Όταν κάνουμε serialize ένα μοντέλο που περιέχει generic foreign keys, οι serializers του Django απλά καταγράφουν το content_type_id και το object_id.

Εδώ δημιουργείται το πρόβλημα.

Τα content_types φτιάχνονται κατα το syncdb (κάτι που γίνεται στην αρχή του test runner ) και τα id που θα πάρουν εξαρτώνται απο την σειρά με την οποία θα διαβάσει τις εφαρμογές και τα μοντέλα το django. Τα test fixtures που φτιάξαμε νωρίτερα μεσω του serializer θα βγούν άχρηστα όταν για κάποιο λόγω αλλάξουν τα id των content types, και τα test μας θα αρχίσουν να σπάνε και χωρίς εμείς να ξέρουμε γιατί (αφού τα φόρτωσε χωρίς πρόβλημα).

Δυστυχώς δεν υπάρχει καλή λύση για αυτό το πρόβλημα.

Μια προσωρινή αλλα πολύ άσχημη λύση είναι στο test να κάνουμε lookup για το σωστό content type και να το αλλάζουμε on-the-fly. Yuck.

Είμαι γκαντέμης ή απλά άτυχος? :p

posted at 14:12  ·   ·  django  ellak  bug
Click to read and post comments

Aug 20, 2009

Newsletter με πολλούς παραλήπτες και privacy

Πρόσφατα έλαβα ένα ενημερωτικό email απο ένα ηλεκτρονικό κατάστημα με (πολύ) προκλητικά εσώρουχα. ( Όχι δεν έχω ψωνίσει. Το έχει φτιάξει φίλος μου και γράφτηκα για να δώ την υλοποίηση. Seriously )

Το email αυτό λοιπόν έχει πολλούς παραλήπτες στο Το: header και μπορώ να δώ ποιος άλλος το έλαβε. Απλά απαράδεκτο.

Μου ήταν πολύ απλό να πάρω μερικά email, να πάω στην αναζήτηση του Facebook και να βρω ποιος είναι πελάτης του συγκεκριμένου καταστήματος. Στην συγκεκριμένη περίπτωση δεν ήταν ποιός, αλλά ποιες και μάλιστα πολλές και καλές. Νομίζω οτι λάθος δουλειά κάνω. :-)

Αν δεν είχε ανάμιξη ο φίλος μου (δεν είχε στο email) θα τους έστελνα ένα καλό flame.

Είμαι βέβαιος οτι η ασχετοσύνη κυριαρχεί εδώ και όχι τίποτα πονηρό.

Click to read and post comments

May 04, 2009

Why PHP sucks.

Με αφορμή ένα facebook status message ενός φίλου (ναι, την μισεί και αυτός :p ), είπα να γράψω οτι είναι στραβό με την PHP κατα την γνώμη μου.

Εχουμε λοιπόν:

  1. Χιλιάδες functions στο default namespace.
    Είναι πραγματικά απίστευτο. Μέχρι πρόσφατα η PHP δεν υποστήριζε namespaces και υπάρχουν κυριολεκτικά χιλιάδες functions στο default namespace. Εντελώς απαράδεκτο.
  2. Unicode. Πού είναι? οεο!
    Έχουμε 2009 και η PHP δεν υποστηρίζει Unicode. Μοιάζει μα ανέκδοτο αλλά δεν είναι.
  3. Κανένα database abstraction.
    Πόσο δύσκολο είναι ένα καλύτερο API για database access που να μην είναι δεμένο σε μια συγκεκριμένη database? Υπάρχουν διάφορα modules/scripts κλπ για να το λύνουν αυτό , παρόλα αυτά πάρα πολλά project χρησιμοποιούν functions συγκεκριμένες σε μια μόνο database. Και δεν μιλάω για χρήση ORM. Απλά ένα DB API όπως της Python.
  4. Χάος με deprecated functions.
    Συχνά functions σπάνε την συμβατότητα, αλλάζουν όνομα και υπάρχουν διαφορετικές και ασύμβατες functions παράλληλα. Παράδειγμα: mysql_* με mysqli_* και mysql_escape_string vs mysql_real_escape_string.
  5. Δεν υπάρχουν στάνταρ στις functions.
    Η σειρά των παραμέτρων αλλάζει ανάμεσα σε string μεθόδους. Παράδειγμα
  6. Ασυνεπές περιβάλλον Με τα .ini αρχεία ο developer δεν μπορεί να γνωρίζει είναι διαθέσιμο και τι όχι.
    Επιπλέον, υπάρχουν functions όπως η money_format() που δεν είναι portable και χωρίς σημαντικό λόγο. Η money_format() δεν είναι fork() ή κάποιο system call δεμένο σε μια πλατφόρμα. Γιατί το υλοποίησαν με non-portable τρόπο?
  7. Βλαμμένες χακιές
    Πχ magic_quotes. Το magic quotes ήταν μια χαζή ιδέα γεμάτη προβλήματα. Η ιδέα εγκαταλείφθηκε αλλα άφησε τα απομεινάρια της. Ο developer δεν γνωρίζει αν είναι ενεργοποιημένα ή όχι, και πρέπει να ελέγχει με get_magic_quotes_gpc().
    Φυσικά έχουμε και το register_globals. Μια ακόμα βλαμμένη ιδέα που καταργήθηκε. Ήταν μια πηγή απο bugs και απο σοβαρά κενά ασφαλείας. Δείτε εδώ για περισσότερα.
  8. Δεν προάγει διαχωρισμό HTML , κώδικα και SQL.
    Υπάρχουν MVC frameworks αλλα η συντριπτική πλειοψηφία του PHP κώδικα είναι “όλα αχταρμάς”. Τα περισσότερα βιβλία και tutorial σε μαθαίνουν την λογική όλα μέσα. Για κάθε PHP project που είναι καλά σχεδιασμένο/γραμμένο υπάρχουν άλλα χίλια που θες να βγάλεις τα μάτια σου και να τα φάς.

Αυτή η λίστα περιλαμβάνει μόνο σοβαρά προβλήματα που έχω διαπιστώσει μόνος μου. Μια απλή αναζήτηση για PHP sucks θα φανερώσει πολλά ακόμα προβλήματα.

Η PHP είναι μια άναρχη γλώσσα που δεν σχεδιάστηκε απο την αρχή αλλά εξελίχθηκε βιαστικά και απρόσεκτα για να καλύψει τις ανάγκες των χρηστών της. Η ευκολία της τόσο στην εκμάθηση όσο και στο deployment την έκαναν πολύ δημοφιλή γλώσσα. Αυτό δεν σημαίνει οτι είναι καλή γλώσσα. Είναι μια γλώσσα γεμάτη κακές πρακτικές, bugs, κακό σχεδιασμό , ένα σωρό προβλήματα και παγίδες, ειδικά για νέους χρήστες.

posted at 15:11  ·   ·  php  sucks  rant  greek
Click to read and post comments

Mar 23, 2009

Applications meme

Ένα ενδιαφέρον blog meme απο εδώ:

Answer the following questions with less than 50 words each (mind, only desktop/gui applications):

  1. which desktop manager do you use more often ?
  2. which desktop application you would not like to see implemented again on linux? and why?
  3. which desktop application you definitely would like to see implemented on linux? describe it briefly or point out to a similar application.
  4. write the name of the last project (not the very best, the last!) that made you wish to thank their developers so you can thank them now! :-)
  5. (optional) Link the blogs of 1-3 people you’d like to take part to this meme. (no more than three). you can skip this question if you like.

Οι απαντήσεις μου:

  1. KDE αποκλειστικά.
  2. audio players. Έχουμε πολλούς και πολύ καλούς. Ας βελτιώσουμε αυτούς.
  3. Video editing. πχ Sony Vegas κλπ.
  4. Django. Thank you people. You’re super awesome.
  5. Whatever…
posted at 17:02  ·   ·  meme  linux  greek
Click to read and post comments

Feb 28, 2009

Δημιουργία ImageSurface στο pycairo με χρηση της PIL.

Πρόσφατα δοκίμαζα το cairo (με την χρήση των python bindings, pycairo). Μια 2D vector graphics βιβλιοθήκη γραμμένη σε C με bindings για πολλές γλώσσες.

Ήθελα να μπορώ να φορτώνω εικόνες απο αρχεία με διάφορα format και να τα βάζω στο canvas μου.

Η PIL (Python Imaging Library) είναι μια πολύ καλή βιβλιοθήκη που μας επιτρέπει να διαβάζουμε και να επεξεργαζόμαστε πολλά αρχεία είκόνας.

Η PIL μας δίνει την δυνατότητα να πάρουμε τα “raw” δεδομένα μιας εικόνας, το cairo μας επιτρέπει να φτιάξουμε ένα ImageSurface απο τα “raw” δεδομένα μιας εικόνας αρα το πρόβλημα θα έπρεπε να είναι απλό. Μετατρέπουμε μια εικόνα σε RGBA format (γιατί μπορεί πχ να είναι pallete ) , παίρνουμε τα raw δεδομένα και τα δίνουμε στο cairo. Δεν είναι ακριβώς έτσι όμως. Η PIL χρησιμοποιεί RGBA format στα raw δεδομένα ενώ η cairo ARGB. (δηλαδή πρώτα το alpha channel αντί για τελευταίο όπως στο RGBA). Το αποτέλεσμα είναι οτι αντιστρέφονται τα χρώματα στο B και R color bands.

Για να το λύσουμε αυτό πρέπει να αντιστρέψουμε τα B και R color bands (blue και Red δηλαδή). Το οτι χρειάζεται να γίνει αυτό, όπως και το πώς γίνεται το βρήκα με αρκετό ψάξιμο ψάξιμο στα intertubes και για αυτό το καταγράφω εδώ. Υπάρχει στο cookbook του cairo σχετικό θέμα αλλα δεν λύνει την μετατροπή RGBA->ARGB και αυτό που αναφέρει σαν λύση (οτι το PIL μπορεί να μετατρέψει ARGB) δεν δουλεύει.

Ορίστε λοιπόν:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
import Image
import cairo
import numpy

img = Image.open('our_file.jpg')
img = img.convert("RGBA")
r , g , b, a  = img.split()
img = Image.merge("RGBA"  ( b, g, r ,a ) )
buff = numpy.asarray(img)
buff.flags.writeable = True

width,height = img.size
stride = cairo.ImageSurface.format_stride_for_width(
                  cairo.FORMAT_ARGB32,width)

surface = cairo.ImageSurface.create_for_data(buff,
                    cairo.FORMAT_ARGB32, width,height,stride)

Εδώ χρησιμοποιώ την numpy για writeable buffer που χρειάζεται η μέθοδος create_for_data() αλλα γίνεται το ίδιο απλά και με το array module.

Click to read and post comments

Jan 30, 2009

Ubuntu is all about the community

Πολλά πράγματα μου συμβαίνουν αυτή την εποχή, και δυσάρεστα αλλα (μάλλον) και ευχάριστα οπότε δεν έχω χρόνο για το blog.

Για να σας θυμίσω οτι υπάρχω όμως, ορίστε κάτι που είχα φτιάξει πριν καιρό. Είχα πετύχει την αρχική φωτογραφία μέσω stumbleupon και μόλις την είδα αμέσως το συνδύασα με ubuntu και με 2 λεπτά Gimp hacking το έβαλα δίπλα στην λέξη ubuntu.

Προσοχή, δεν είναι για ανήλικους. (ποτέ όμως δεν είπα οτι το blog αυτό είναι σεμνό).

Ubuntu Porn

Ήθελα να σκεφτώ κάποιο κατάλληλο tagline για να προσθέσω αλλα ποτέ δεν το έκανα. Πχ κάτι σε στύλ “Ubuntu brings communities closer” ή κάτι σχετικό :p

posted at 17:32  ·   ·  ubuntu  logo  humor  greek  pr0n
Click to read and post comments

Dec 31, 2008

Το χάλι της Forthnet.

Ήμουν αρχικά πελάτης της Internet Helllas. Αυτή αγοράστηκε απο την Forthnet και μεταφέρθηκα αυτόματα εκεί. Απο τότε μέχρι σήμερα ήμουν πελάτης της Forthnet.

Πλήρωνα με πιστωτική κάρτα. Κάθε μήνα “τράβαγαν” τα χρήματα αυτόματα και όλα μια χαρά. Μέχρι που στις 29/12 ώρα 15:00 πέφτει η σύνδεσή μου και στα logs του modem βλέπω προσπάθεις για login με λάθος username/password.

Επειδή η πιστωτική κάρτα που χρησιμοποιώ ανανεώθηκε πρόσφατα (άρα άλλαξε ημερομηνία λήξης και CVV) και χρειάστηκε να την ενημερώσω σε πολλές υπηρεσίες (hosting/paypal κλπ) πήγε το μυαλό μου οτι κάτι τέτοιο συμβαίνει και έτσι μίλησα με το τμήμα πωλήσεων της Forthnet.

Αυτό είχε συμβεί και στο παρελθόν. Σε απενεργοποιούν και δεν μπορείς να κάνεις login. Τότε είχα πάρει τηλέφωνο τους έδωσα τα νέα στοιχεία τις κάρτα και όλα καλά.

Να σημειώσω πως και την προηγούμενη φορά, όπως και τώρα μου έκοψαν την σύνδεση χωρις προειδοποίηση. Κάτι που, αν θυμάμαι καλά, απαγορεύεται απο την ΕΕΤΤ. (και ο λογαριασμός δεν μετράει σαν προειδοποίηση. Ετσι και αλλιώς δεν λαμβάνω ,ομως, γιατί έχουν τα στοιχεία μου μπερδεμένα και δεν μπορούν τα τα φτιάξουν)

Στο τηλέφωνο μου λένε οτι υπάρχει ένα χρέος 7 τιμολόγια (7 μήνες δηλαδή). 2 τιμολόγια του 2005 (!?!) και τα υπόλοιπα του 2006! Όλα τα μεταγενέστερα τιμολόγια μέχρι σήμερα είναι πληρωμένα κανονικά! Κανένας δεν μπόρεσε να μου απαντήσει πώς προέκυψε αυτό το χρέος αφού πληρώνω με πιστωτική κάρτα. Στο τηλέφωνο μου λένε οτι δεν γίνεται να δώσω τα στοιχεία της κάρτας μου απο το τηλέφωνο για να πληρωθεί το χρέος (και να συνεχίσουν οι χρεώσεις) και πως πρέπει να πάω στο υποκατάστημα.

Στο υποκατάστημα (που πήγε η αδελφή μου) της λένε οτι μπορεί να πληρώσει μόνο τα τιμολόγια του 2006 και πως τα 2 τιμολόγια του 2005 δεν μπορούν να πληρωθούν γιατι δεν τα “δέχεται” το σύστημα τους. Πρέπει να πάω στην τράπεζα και να τους στείλω το αποδεικτικό κατάθεσης με fax (το σύστημά τους δέχεται αποδεικτικά κατάθεσης, αλλά όχι μετρητά? wtf?). Μιας και όλα αυτά γίνονται απόγευμα, αυτόματα το ξεμπλοκάρισμά μου πάει για την επόμενη ημέρα. Και όλα αυτά ενώ τους έχω εξηγήσει πολλές φορές οτι το internet το χρειάζομαι το συντομότερο δυνατόν για την δουλειά μου.

Την επόμενη ημέρα πάω στο υποκατάστημα και τους λέω:

  • Έχω το έρθει με μετρητά για χρέος που δεν ξερετε γιατί πρέπει να πληρώσω. Μπορώ να το πληρώσω εδώ?
  • Οχι, πρέπει να πάτε στην τράπεζα.
  • Ωραία, φέρτε μου έντυπο να καταργήσω την συνδρομή μου

Όπως και έκανα φυσικά.
Ούτε το ΙΚΑ και η Εφορία δεν είναι τόσο χάος.

Φυσικά θεώρησα αυτονόητο οτι αφού έχω γραμμή adsl απο τον ΟΤΕ και εξοπλισμό δικό μου θα μπορούσα να κάνω μια νέα σύνδεση μέσα σε λίγες ώρες. (username/password χρειαζόμουν μονο). Στα μαγαζιά που πήγα όμως μου είπαν οτι έχουν μονο πακέτα (που θέλουν 10-15 ημέρες) και για αυτό που ζητάω να πάρω τηλ. στον ISP που θέλω.

Παίρνω τηλέφωνο στην HOL και αφού τους εξηγώ την περίπτωσή μου, μου λέει οτι θέλει 7 ημέρες για να ενεργοποιηθεί. (Γιατί?)

Αφού απογοητεύομαι απο την HOL, πάω στην τελευταία επιλογή. Otenet. Και εκεί μου εξηγούν οτι θα κάνουν ότι μπορούν για να μου δώσουν τους κωδικούς το συντομότερο δυνατό. Έκανα την αίτηση απο το 134 στις 15:00 και στις 16:00 με πήραν τηλέφωνο στο κινητό (που δυστυχώς δεν το άκουσα και έτσι με πήραν την επόμενη ημέρα πρωί-πρωί ).

Η εταιρία απο την οποία περίμενα τα λιγότερα ήταν η πιο εξυπηρετική. Φυσικά δεν ασχολήθηκα καθόλου με Tellas και λοιπές εταιρίες επιπέδου Altec.

Πλέον είμαι πελάτης της Otent. Ελπίζω να μην το μετανιώσω. Για να δούμε….

Πάντως το σκηνικό των τηλεπικοινωνιών στην Ελλάδα είναι πολύ απογοητευτικό.

Σκέφτομαι τι θα είχα πάθει αν είχα βάλει και Forthnet Double Play :p

Click to read and post comments

Dec 26, 2008

Dec 14, 2008

Τhe Alexandros Grigoropoulos’s Diary Release

Αν και σπανίως βλέπω τηλεόραση, έχω δεί οτι η υπόθεση με την δολοφονία του 15χρονου Αλέξανδρου Γρηγορόπουλου έχει γίνει διεθνώς είδηση.
Δεν είχα συνειδητοποιήσει, όμως, πόσο έχει επηρεάσει την διεθνή κοινότητα μέχρι που στο community (planet βασικά) του Django είδα να ονομάζουν την νέα release του diario blogging software με τίτλο “The Alexandros Grigoropoulos’s Diary Release”

Οπως αναφέρουν στο project :

This version is a tribute to Alexandros Grigoropoulos, 15-year-old boy, libertarian, murdered by greek police in last week (2008-12-06).

Συνήθως η προγραμματιστική κοινότητα είναι πολύ απομακρυσμένη απο την πολιτική/κοινωνική επικαιρότητα, και σίγουρα αυτή η πρακτική δεν είναι κάτι συχνό.

Ενδιαφέρον…

(Βέβαια εδώ έχουν σπάσει και κάψει το σύμπαν και εγώ περιμένω ένα release άγνωστου software για να καταλάβω τι έχει γίνει? Έκαστος στο είδος του :p )

Click to read and post comments

Dec 03, 2008

Django CSRF tag for AJAX POST calls.

Το Django μας παρέχει (προαιρετικά) το CSRF middleware του οποίου η δουλειά είναι να αποτρέπει τις επιθέσεις CSRF. Για να το πετύχει αυτό, στα response object βρίσκει τις φόρμες με POST method και “εισάγει” ένα ακόμα κρυφό field που περιέχει ένα token μοναδικό για το session. Στα POST request επιβεβαιώνει οτι το token υπάρχει και είναι σωστό.

Όλα ωραία και καλά, αλλα αυτός ο τρόπος έχει το πρόβλημα ότι όταν θέλουμε να κάνουμε AJAX κλήσεις με POST requests δεν θα δουλέψουν γιατί το CSRF middelware δεν θα βρεί tokens.

Για να λύσω αυτό το πρόβλημα με τον πιό απλό τρόπο έφτιαξα ένα template tag που παρέχει ένα token στα template μου.

Έτσι, για παράδειγμα στο YUI όταν κάνω το request είναι κάπως έτσι:

1
2
3
4
{%csrf_token as token    %}
params = "ham="+ham+"&eggs="+eggs + "&csrfmiddlewaretoken={{token}}" ;
var transaction = YAHOO.util.Connect.asyncRequest("POST", {%url spam%},
    callback, params);

Μιας και βασίζεται στην ύπαρξη του sessionid στο cookie, αυτό το tag δεν θα μας δώσει token όταν ο χρήστης έχει απενεργοποιήσει τα cookies (κάτι που σπάει ένα σκασμό site οπότε δεν με πολυνοιάζει) και όταν είναι το πρώτο request στο site μας. (Μπορούμε όμως να ελέγξουμε αν υπάρχει το token και να πράξουμε κατάλληλα)

Ορίστε και το tag:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
from django.conf import settings
from django.utils.hashcompat import md5_constructor
import re

class CsrfNode(template.Node):
"""
Tag that provides a CSRF token in the context.
Usage: {% csrf_token as token %}
If the user has no cookies (cookies disabled, or this is
the first ever page view on the site, this tag will provide
an empty token. You can test that (eg to refresh the page)
"""

def __init__(self,var_name):
    self.var_name = var_name

def render(self,context):
    SESSION_COOKIE_NAME = getattr(settings,
            "SESSION_COOKIE_NAME","sessionid")
    sess_key = context['request'].COOKIES.get(SESSION_COOKIE_NAME,None)
    if not sess_key:
        # User has no cookie. Empty token.
        token = ""
    else:
        val = settings.SECRET_KEY + sess_key
        token = md5_constructor( val  ).hexdigest()
    context[self.var_name] = token
    return ''

@register.tag(name='csrf_token')
def do_csrf_token(parser,token):
    try:
        tag_name , params = token.contents.split(None,1)
    except ValueError:
        msg = "%r tag requires arguments" % token.contents.split()[0]
        raise template.TemplateSyntaxError(msg)
    m = re.search(r'^as (\w+)$', params)
    if not m:
        msg = "%r tag had invalid arguments" % tag_name
        raise template.TemplateSyntaxError(msg)
    var_name = m.groups()[0]
    return CsrfNode(var_name)

Ελπίζω να είναι bug free :p

Click to read and post comments
← Previous Next → Page 2 of 6