Never been to DZone Snippets before?

Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world

About this user

Korakot Chaovavanich http://korakot.stumbleupon.com

« Newer Snippets
Older Snippets »
Showing 1-2 of 2 total  RSS 

ORM for pys60

I have asked for this a few months.
Here's my own first version for an ORM.
It's adapted from SQLAlchemy and SQLObject.
(and whatever library I have searched)

You need to create a database manually first.
My previous snippets (shell, SQL) may help.
   1  
   2  from __future__ import generators
   3  import e32db, re
   4  db = e32db.Dbms()
   5  dbv = e32db.Db_view()
   6  db.open(u'C:\\test.db')
   7  
   8  # Some helping classes (need more in next version)
   9  class String:
  10      pass
  11  
  12  class Integer:
  13      pass
  14  
  15  class Float:
  16      pass
  17  
  18  class column:
  19      def __init__(self, coltype):
  20          self.coltype = coltype

Here's the mother of all your classes that map to database tables.
   1  
   2  class Mapper(object):
   3      def __init__(self, id=None, **kw):
   4          if id is None:
   5              self.id = self._insert(**kw)
   6          else:
   7              self.id = id
   8      def _insert(self, **kw):
   9          names = ','.join(kw.keys())
  10          values = ','.join([self.quote(k,v) for k,v in kw.items()])
  11          tablename = self.__class__.__name__
  12          q = u"INSERT INTO %s(%s) VALUES (%s)" % (tablename, names, values)
  13          db.execute(q)
  14          # get last insert ID
  15          dbv.prepare(db, u'SELECT id FROM '+tablename+' ORDER BY id DESC')
  16          dbv.first_line()
  17          dbv.get_line()
  18          return dbv.col(1)
  19      def __getattr__(self, name):
  20          if name in self.mapping.__dict__:
  21              q = 'SELECT '+name+' FROM '+self.__class__.__name__
  22              q += ' WHERE id='+str(self.id)
  23              dbv.prepare(db, unicode(q))
  24              dbv.first_line()
  25              dbv.get_line()
  26              return dbv.col(1)
  27          else:
  28              return self.__dict__[name]
  29      def __repr__(self):
  30          return '<%s id=%d>' % (self.__class__.__name__, self.id)
  31      def quote(self, name, value):
  32          if self.mapping.__dict__[name].coltype == String:
  33              return "'%s'" % value.replace("'", "''")  # encode single quote
  34          else:
  35              return str(value)
  36      def __setattr__(self, name, value):
  37          if name in self.mapping.__dict__:
  38              q = 'UPDATE '+self.__class__.__name__+' SET '+name+'='
  39              q += self.quote(name, value) + " WHERE id=" + str(self.id)
  40              db.execute(unicode(q))
  41          else:
  42              self.__dict__[name] = value
  43      def set(self, **kw):
  44          q = "UPDATE "+self.__class__.__name__+" SET "
  45          for k, v in kw.items():
  46              q += k+'='+self.quote(k,v)+','
  47          q = q[:-1]+" WHERE id=%s" % self.id
  48          db.execute(unicode(q))
  49      def delete(self):
  50          q = 'DELETE FROM '+self.__class__.__name__+" WHERE id=" + str(self.id)
  51          db.execute(unicode(q))
  52          self.id = None
  53      def dict(self):
  54          names = [k for k in self.mapping.__dict__.keys() if not k.startswith('__')]
  55          q = 'SELECT '+','.join(names)+' FROM '+self.__class__.__name__
  56          q += ' WHERE id=' + str(self.id)
  57          dbv.prepare(db, unicode(q))
  58          dbv.first_line()
  59          dbv.get_line()
  60          dct = {'id': self.id}
  61          for i in range(dbv.col_count()):
  62              dct[names[i]] = dbv.col(i+1)
  63          return dct
  64      def select(cls, where=None, orderby=None):
  65          q = 'SELECT id FROM '+cls.__name__
  66          if where:
  67              q += ' WHERE '+where
  68          if orderby:
  69              q += ' ORDER BY '+orderby
  70          dbv = e32db.Db_view()  # need its own cursor
  71          dbv.prepare(db, unicode(q))
  72          dbv.first_line()
  73          for i in range(dbv.count_line()):
  74              dbv.get_line()
  75              yield cls(dbv.col(1))
  76              dbv.next_line()
  77      select = classmethod(select)

Here's how you create your class.
   1  
   2  class Person(Mapper):
   3      class mapping:
   4          # doesn't need id = column(Integer)
   5          name = column(String)
   6          age = column(Integer)

Declarative metaclass

Metaclass is like a black magic in python.
I wouldn't learn it if not necessary to read someone's code.
SqlObject uses it. So, if I want to port it to pys60 Dbms,
I need to learn metaclass.

Fortunately, this one is not too much to understand.
   1  
   2  class DeclarativeMeta(type):
   3      def __new__(meta, class_name, bases, new_attrs):
   4          cls = type.__new__(meta, class_name, bases, new_attrs)
   5          if new_attrs.has_key('__classinit__'):
   6              cls.__classinit__ = staticmethod(cls.__classinit__.im_func)
   7          cls.__classinit__(cls, new_attrs)
   8          return cls

When you use it you do this
   1  
   2  class YourClass(object):
   3      __metaclass__ = DeclarativeMeta
   4      # ... and other class variables
   5      def __classinit__(cls, new_attrs):
   6          # do whatever you want with the new class
   7          # ...
   8      def __init__(self):
   9          # do whatever you want with the new instance

You use this when you want a subclass to have some magic
done to it when it is first defined. What you say in
__classinit__ will get done to the new subclass, eg.
create more methods, properties, etc.
« Newer Snippets
Older Snippets »
Showing 1-2 of 2 total  RSS