The Artima Developer Community
Sponsored Link

Python Buzz Forum
Magic and Backtracing Code

0 replies on 1 page.

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 0 replies on 1 page
Ian Bicking

Posts: 900
Nickname: ianb
Registered: Apr, 2003

Ian Bicking is a freelance programmer
Magic and Backtracing Code Posted: Nov 8, 2005 5:41 PM
Reply to this message Reply

This post originated from an RSS feed registered with Python Buzz by Ian Bicking.
Original Post: Magic and Backtracing Code
Feed Title: Ian Bicking
Feed URL: http://www.ianbicking.org/feeds/atom.xml
Feed Description: Thoughts on Python and Programming.
Latest Python Buzz Posts
Latest Python Buzz Posts by Ian Bicking
Latest Posts From Ian Bicking

Advertisement

SQLObject actually has, in its history, a great deal of similarity to other Python ORMs. Not just the whole wraps-a-database-thing (which it obviously should have in common), but little implementation details. For instance, like PyDO and Django, it used to have a list of columns (instead of using attribute assignment). All of those projects have changed since then... and probably in a similar way you can lingering artifacts of that past implementation detail.

One of the ways is how the class is actually constructed. This history often reflects a past when a class was a mostly-dumb holder of a data definition. Then some outside code (the ORM itself) looks at the class definition for special attributes, and constructs a bunch of stuff. So, for instance, though you do name = StringCol() in SQLObject, StringCol is just a description of the column. It doesn't actually do anything, and if you later fetch MyClass.name you won't get back anything related to StringCol. Because what is actually happening is that those descriptions are collected, then the class is built.

This is something I'm trying to move away from in SQLObject, and I think 0.8 will have some significant progress here. One of the goals of that progress is to make a distinction between SQLObject and ActiveRecord, (and, less direction, from Django's ORM). Because -- admitting that this is a judgemental and subjective term -- I want SQLObject to be the most Pythonic of these options. Where Pythonic doesn't just mean fits-the-language (can't expect a Ruby library to want to fit into Python) but is a more generic term for Everything That Is Good In Programming.

In this case, there's a specific feature of Python I want to maintain: backtracking. Python's namespaces and tendency towards functions and imperative code means that it's fairly easy, given a local bit of code, to figure out what that code is doing in terms of the larger system. You can read code inside out, instead of having to figure everything out up front. Metaprogramming on the whole tends to break that, because you don't even understand the dialect of code you are reading, not to mention where methods are implemented and what side effects they might have. So SQLObject already breaks backtracking; my goal is to mitigate that.

One instance is joins, which have some annoying surprises in SQLObject exactly because of the legacy of treatment of classes as declaration. I have a refactoring of joins (not yet checked in) that will hopefully clear things up and generally simplify things. Over on the TurboGears list people wanted syntax similar to Django's for adding instances, and it would have meant:

class Person(SQLObject):
    addresses = MultipleJoin('Address')
p = Person.get(1)
p.addAddress(street='123 W 12th', ...)

I.e., the presence of that join would cause the addAddress method to be created. Seeing addAdress in code, how would you figure out what that did? Well, you'd just have to be familiar with how the code works, because addAddress simply won't exist in any other fashion. But that's what I want to get away from; what will actually go into SQLObject will be:

class Person(SQLObject):
    addresses = OneToMany('Address')
p = Person.get(1)
p.addresses.create(street='123 W 12th', ...)

If you want to know what's going on, you look up OneToMany.create(). Well... sadly it won't be that easy, as OneToMany is a descriptor, and it actually returns an object that delegates to SelectResults. There's still a lot to keep track of, and the challenge I'll have is to figure out a way to present a wider set of core concepts than is currently in the documentation (for instance, SelectResults is a really important class, but it's not documented and it's always instantiated for you). I'm thinking SQLObject docs should move towards a casual overview, with deep links into generated documentation that is more complete.

Read: Magic and Backtracing Code

Topic: Sad conflicting packages Previous Topic   Next Topic Topic: Repetition Javascript Library

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use