# HG changeset patch # User Sylvain Thénault # Date 1307365380 -7200 # Node ID 1090724f28ed7b736a34f42dff8fbe1a9b861e40 # Parent d5705c9bbe827d60ce5516363b883a7fe7e5d214# Parent 84046395d2cdba606459032ec6985fc09c871644 backport stable diff -r d5705c9bbe82 -r 1090724f28ed selectors.py --- a/selectors.py Fri May 27 13:57:25 2011 +0200 +++ b/selectors.py Mon Jun 06 15:03:00 2011 +0200 @@ -1342,7 +1342,7 @@ @lltrace def __call__(self, cls, req, rset=None, row=None, col=0, **kwargs): - if not req.cnx: + if not getattr(req, 'cnx', True): # default to True for repo session instances return 0 user = req.user if user is None: diff -r d5705c9bbe82 -r 1090724f28ed server/session.py --- a/server/session.py Fri May 27 13:57:25 2011 +0200 +++ b/server/session.py Mon Jun 06 15:03:00 2011 +0200 @@ -75,6 +75,25 @@ return req.is_internal_session +class transaction(object): + """context manager to enter a transaction for a session: when exiting the + `with` block on exception, call `session.rollback()`, else call + `session.commit()` on normal exit + """ + def __init__(self, session, free_cnxset=True): + self.session = session + self.free_cnxset = free_cnxset + + def __enter__(self): + pass + + def __exit__(self, exctype, exc, traceback): + if exctype: + self.session.rollback(free_cnxset=self.free_cnxset) + else: + self.session.commit(free_cnxset=self.free_cnxset) + + class hooks_control(object): """context manager to control activated hooks categories. @@ -237,6 +256,16 @@ return '<%ssession %s (%s 0x%x)>' % ( self.cnxtype, unicode(self.user.login), self.id, id(self)) + def transaction(self, free_cnxset=True): + """return context manager to enter a transaction for the session: when + exiting the `with` block on exception, call `session.rollback()`, else + call `session.commit()` on normal exit. + + The `free_cnxset` will be given to rollback/commit methods to indicate + wether the connections set should be freed or not. + """ + return transaction(self, free_cnxset) + def set_tx_data(self, txid=None): if txid is None: txid = threading.currentThread().getName() diff -r d5705c9bbe82 -r 1090724f28ed server/sources/storages.py --- a/server/sources/storages.py Fri May 27 13:57:25 2011 +0200 +++ b/server/sources/storages.py Mon Jun 06 15:03:00 2011 +0200 @@ -173,13 +173,15 @@ entity.cw_edited.edited_attribute(attr, Binary(fpath)) # Mark the old file as useless so the file will be removed at # commit. - DeleteFileOp.get_instance(entity._cw).add_data(oldpath) + if oldpath is not None: + DeleteFileOp.get_instance(entity._cw).add_data(oldpath) return binary def entity_deleted(self, entity, attr): """an entity using this storage for attr has been deleted""" fpath = self.current_fs_path(entity, attr) - DeleteFileOp.get_instance(entity._cw).add_data(fpath) + if fpath is not None: + DeleteFileOp.get_instance(entity._cw).add_data(fpath) def new_fs_path(self, entity, attr): # We try to get some hint about how to name the file using attribute's @@ -199,13 +201,16 @@ return fspath def current_fs_path(self, entity, attr): + """return the current fs_path of the tribute. + + Return None is the attr is not stored yet.""" sysource = entity._cw.cnxset.source('system') cu = sysource.doexec(entity._cw, 'SELECT cw_%s FROM cw_%s WHERE cw_eid=%s' % ( attr, entity.__regid__, entity.eid)) rawvalue = cu.fetchone()[0] if rawvalue is None: # no previous value - return self.new_fs_path(entity, attr) + return None return sysource._process_value(rawvalue, cu.description[0], binarywrap=str) diff -r d5705c9bbe82 -r 1090724f28ed web/formwidgets.py --- a/web/formwidgets.py Fri May 27 13:57:25 2011 +0200 +++ b/web/formwidgets.py Mon Jun 06 15:03:00 2011 +0200 @@ -435,6 +435,7 @@ an unicode string, or a list of unicode strings. """ vocabulary_widget = True + default_size = 5 def __init__(self, attrs=None, multiple=False, **kwargs): super(Select, self).__init__(attrs, **kwargs) @@ -442,11 +443,10 @@ def _render(self, form, field, renderer): curvalues, attrs = self.values_and_attributes(form, field) - if not 'size' in attrs: - attrs['size'] = self._multiple and '5' or '1' options = [] optgroup_opened = False - for option in field.vocabulary(form): + vocab = field.vocabulary(form) + for option in vocab: try: label, value, oattrs = option except ValueError: @@ -466,6 +466,12 @@ options.append(tags.option(label, value=value, **oattrs)) if optgroup_opened: options.append(u'') + if not 'size' in attrs: + if self._multiple: + size = unicode(min(self.default_size, len(vocab) or 1)) + else: + size = u'1' + attrs['size'] = size return tags.select(name=field.input_name(form, self.suffix), multiple=self._multiple, options=options, **attrs)