from peak.persistence import Persistent from peak.api import * from datetime import datetime def sql_equals(data, clauses=(), sep=' AND ', pre=' WHERE '): clauses = [c for c in clauses if c] params = [] for k,v in data.items(): clauses.append(k+'=?') params.append(v) sql = sep.join(clauses) if sql: sql = pre+sql return sql, params def sqlSET(data, clauses=()): return sql_equals(data, clauses, ', ', ' SET ') def sqlWHERE(data, clauses=()): return sql_equals(data, clauses) class SQL_DM(storage.EntityDM): db = binding.Obtain('db') table = binding.Require('table name') key = binding.Require('primary key column') _select = binding.Make(lambda self: "select * from "+self.table) _filter = '' def _load(self, oid, ob): for row in self._where({self.key:oid}): return self.stateForRow(row) else: raise storage.InvalidKeyError def _where(self, args): where, what = sqlWHERE(args, [self._filter]) return self.db(self._select + where, what) def where(self, **kw): key = self.key state = self.stateForRow for row in self._where(kw): yield self.preloadState(row[key], state(row)) def _save(self, ob): for tbl,values,wheres in self.rowsForOb(ob): sWhere, what = sqlWHERE(wheres) sSet, values = sqlSET(values) self.db('UPDATE '+tbl+sSet+sWhere, values+what) class Base(Persistent): class __metaclass__(binding.Activator, Persistent.__class__): pass class Item(Base): """An item that's editable in CityDesk""" def __setstate__(self, state): self.__class__ = item_types[state['_itemType']] self._p_changed = False super(Item,self).__setstate__(state) path = binding.Make( lambda self: (self.parent and self.parent.path+'/' or '') + self.publishAs + self.ext ) absLink = binding.Make(lambda self: self.path + self.ext) parent = None ext = '' # XXX class Folder(Item): """A Folder""" class File(Item): """A File""" class Article(Item): """An article""" def __repr__(self): return "Article(%s)" % (self.__dict__,) _article = binding.Make( lambda self: ~self._p_jar.db( "select * from tblArticle where ixArticle=?", (self._articleNo,) ) ) body = binding.Make(lambda self: str(self._article.sArticle).decode('utf16')) headline = binding.Obtain("_article/sHeadline") teaser = binding.Obtain("_article/sTeaser") sidebar = binding.Obtain("_article/sSidebar") about = binding.Obtain("_article/sAboutTheAuthor") extra1 = binding.Obtain("_article/sExtra1") extra2 = binding.Obtain("_article/sExtra2") ext = binding.Delegate("template") # get the extension from the template item_types = { 1.0: Folder, 2.0: Article, 3.0: File, } class Template(Base): """A CityDesk template""" class TemplateDM(SQL_DM): resetStatesAfterTxn = False defaultClass = Template table = 'tblTemplate' key = 'ixTemplateStructure' ixFamily = binding.Obtain('ixFamily') _filter = binding.Make( lambda self: 'fDeleted=0 and ixTemplateFamily=%d' % self.ixFamily ) def stateForRow(self, row): return dict(ext = row.sExt, body = row.utf8Template) class ItemDM(SQL_DM): resetStatesAfterTxn = False defaultClass = Item table = 'tblStructure' key = 'ixStructure' _filter = 'fDeleted=0' ixLanguage = binding.Obtain('ixLanguage') templateDM = binding.Obtain('templateDM') def stateForRow(self, row): state = dict( _itemType = row.iType, _itemNo = row.ixItem, name = row.sName, publishAs = row.sPublishAs, ) if row.ixParent: state['parent'] = self[row.ixParent] if row.iType==2.0: state = self.articleState(**state) return state def articleState(self, _itemType, _itemNo, name, publishAs, parent=None): filed,effective,retire = ~self.db( "select dtFiled, dtEffective, dtRetire from tblArticleSet" " where ixSet=?", (_itemNo,) ) modified, _articleNo, author, keywords, template = ~self.db( "select dtModified,ixArticle,sAuthor,sKeywords,ixTemplateStructure" " from tblArticle where ixSet=? and ixLanguage=?", (_itemNo, self.ixLanguage) ) now = datetime.now(); template = self.templateDM[template] active = ( (effective is None or effective<=now) and (retire is None or retire >=now) ) del now, self return locals() def rowsForOb(self, ob): yield ( 'tblStructure', dict(sName=ob.name, sPublishAs=ob.publishAs), dict(ixStructure=ob._p_oid) ) if isinstance(ob,Article): yield ( "tblArticleSet", dict( dtFiled=ob.filed, dtEffective=ob.effective, dtRetire=ob.retire ), dict(ixSet=ob._itemNo) ) yield ( 'tblArticle', dict( sExtra1=ob.extra1, sExtra2=ob.extra2, sTeaser=ob.teaser, sHeadline=ob.headline, sSidebar=ob.sidebar, sAboutTheAuthor=ob.about ), dict(ixArticle=ob._articleNo) )