--- 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:
--- 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()
--- 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)
--- 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'</optgroup>')
+ 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)