--- a/common/__init__.py Wed Apr 15 17:00:58 2009 +0200
+++ b/common/__init__.py Wed Apr 15 17:30:03 2009 +0200
@@ -2,7 +2,7 @@
hg stserver side and on the client side
:organization: Logilab
-:copyright: 2001-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
"""
--- a/cwctl.py Wed Apr 15 17:00:58 2009 +0200
+++ b/cwctl.py Wed Apr 15 17:30:03 2009 +0200
@@ -4,7 +4,7 @@
%s"""
import sys
-from os import remove, listdir, system, kill, getpgid
+from os import remove, listdir, system, kill, getpgid, pathsep
from os.path import exists, join, isfile, isdir
from logilab.common.clcommands import register_commands, pop_arg
@@ -176,7 +176,7 @@
print ' ', line
print
try:
- cubesdir = cwcfg.cubes_dir()
+ cubesdir = pathsep.join(cwcfg.cubes_search_path())
namesize = max(len(x) for x in cwcfg.available_cubes())
except ConfigurationError, ex:
print 'No cubes available:', ex
--- a/cwvreg.py Wed Apr 15 17:00:58 2009 +0200
+++ b/cwvreg.py Wed Apr 15 17:30:03 2009 +0200
@@ -122,11 +122,11 @@
return
# remove vobjects that don't support any available interface
implemented_interfaces = set()
- for classes in self.get('etypes', {}).values():
- for cls in classes:
- for iface in cls.__implements__:
- implemented_interfaces.update(iface.__mro__)
- implemented_interfaces.update(cls.__mro__)
+ for etype in self.schema.entities():
+ cls = self.etype_class(etype)
+ for iface in cls.__implements__:
+ implemented_interfaces.update(iface.__mro__)
+ implemented_interfaces.update(cls.__mro__)
for obj, ifaces in self._needs_iface.items():
ifaces = frozenset(isinstance(iface, basestring)
and iface in self.schema
--- a/devtools/test/data/views/bug.py Wed Apr 15 17:00:58 2009 +0200
+++ b/devtools/test/data/views/bug.py Wed Apr 15 17:30:03 2009 +0200
@@ -1,6 +1,7 @@
"""only for unit tests !"""
-from cubicweb.common.view import EntityView
+from cubicweb.view import EntityView
+from cubicweb.selectors import implements
HTML_PAGE = u"""<html>
<body>
@@ -11,7 +12,7 @@
class SimpleView(EntityView):
id = 'simple'
- accepts = ('Bug',)
+ __select__ = implements('Bug',)
def call(self, **kwargs):
self.cell_call(0, 0)
@@ -21,7 +22,7 @@
class RaisingView(EntityView):
id = 'raising'
- accepts = ('Bug',)
+ __select__ = implements('Bug',)
def cell_call(self, row, col):
raise ValueError()
--- a/entities/__init__.py Wed Apr 15 17:00:58 2009 +0200
+++ b/entities/__init__.py Wed Apr 15 17:30:03 2009 +0200
@@ -306,7 +306,7 @@
"""
if self.req.use_fckeditor() and self.e_schema.has_metadata(attr, 'format'):
if self.has_eid() or '%s_format' % attr in self:
- return self.attribute_metadata(attr, 'format') == 'text/html'
+ return self.attr_metadata(attr, 'format') == 'text/html'
return self.req.property_value('ui.default-text-format') == 'text/html'
return False
--- a/entities/authobjs.py Wed Apr 15 17:00:58 2009 +0200
+++ b/entities/authobjs.py Wed Apr 15 17:30:03 2009 +0200
@@ -13,15 +13,16 @@
class EGroup(AnyEntity):
id = 'EGroup'
fetch_attrs, fetch_order = fetch_config(['name'])
+ fetch_unrelated_order = fetch_order
def db_key_name(self):
"""XXX goa specific"""
return self.get('name')
-
class EUser(AnyEntity):
id = 'EUser'
fetch_attrs, fetch_order = fetch_config(['login', 'firstname', 'surname'])
+ fetch_unrelated_order = fetch_order
# used by repository to check if the user can log in or not
AUTHENTICABLE_STATES = ('activated',)
--- a/entities/test/unittest_base.py Wed Apr 15 17:00:58 2009 +0200
+++ b/entities/test/unittest_base.py Wed Apr 15 17:30:03 2009 +0200
@@ -32,25 +32,6 @@
def test_type(self):
self.assertEquals(self.member.dc_type(), 'euser')
-
- def test_custom_widget(self):
- class EUser2(EUser):
- widgets = {
- 'login' : 'AutoCompletionWidget',
- }
- clear_cache(self.vreg, 'etype_class')
- self.vreg.register_vobject_class(EUser2)
- p = self.entity('EUser U WHERE U login "member"')
- self.failUnless(isinstance(p, EUser2))
- w = p.get_widget('login')
- self.failUnless(isinstance(w, AutoCompletionWidget))
-
- def test_format_vocabulary(self):
- card = self.add_entity('Card', title=u"hello")
- self.assertEquals(card.default_content_format(), 'text/html')
- self.execute('INSERT EProperty X: X pkey "ui.default-text-format", X value "text/rest", X for_user U WHERE U login "admin"')
- self.commit()
- self.assertEquals(card.default_content_format(), 'text/rest')
def test_entity_meta_attributes(self):
@@ -258,20 +239,6 @@
self.failUnless(e.matching_groups(('xyz', 'managers')))
self.failIf(e.matching_groups(('xyz', 'abcd')))
- def test_subject_in_state_vocabulary(self):
- # on a new entity
- e = self.etype_instance('EUser')
- rschema = e.e_schema.subject_relation('in_state')
- states = list(e.subject_in_state_vocabulary(rschema))
- self.assertEquals(len(states), 1)
- self.assertEquals(states[0][0], u'activated') # list of (combobox view, state eid)
- # on an existant entity
- e = self.entity('Any X WHERE X is EUser')
- self.assertEquals(e.in_state[0].name, 'activated')
- states = list(e.subject_in_state_vocabulary(rschema))
- self.assertEquals(len(states), 1)
- self.assertEquals(states[0][0], u'deactivated') # list of (combobox view, state eid)
-
def test_workflow_base(self):
e = self.create_user('toto')
self.assertEquals(e.state, 'activated')
@@ -295,6 +262,7 @@
def test_nonregr_subclasses_and_mixins_interfaces(self):
class MyUser(EUser):
__implements__ = (IMileStone,)
+ self.vreg._loadedmods[__name__] = {}
self.vreg.register_vobject_class(MyUser)
self.failUnless(implements(EUser, IWorkflowable))
self.failUnless(implements(MyUser, IMileStone))
@@ -315,6 +283,7 @@
#self.assertEquals(eclass.__bases__, (AnyEntity,))
# build class from most generic to most specific and make
# sure the most specific is always selected
+ self.vreg._loadedmods[__name__] = {}
for etype in ('Company', 'Division', 'SubDivision'):
class Foo(AnyEntity):
id = etype
--- a/entity.py Wed Apr 15 17:00:58 2009 +0200
+++ b/entity.py Wed Apr 15 17:30:03 2009 +0200
@@ -278,9 +278,8 @@
return selection, orderby, restrictions
def __init__(self, req, rset, row=None, col=0):
- AppRsetObject.__init__(self, req, rset)
+ AppRsetObject.__init__(self, req, rset, row, col)
dict.__init__(self)
- self.row, self.col = row, col
self._related_cache = {}
if rset is not None:
self.eid = rset[row][col]
@@ -398,7 +397,7 @@
needcheck = False
return mainattr, needcheck
- def attribute_metadata(self, attr, metadata):
+ def attr_metadata(self, attr, metadata):
"""return a metadata for an attribute (None if unspecified)"""
value = getattr(self, '%s_%s' % (attr, metadata), None)
if value is None and metadata == 'encoding':
@@ -425,14 +424,14 @@
# description...
if props.get('internationalizable'):
value = self.req._(value)
- attrformat = self.attribute_metadata(attr, 'format')
+ attrformat = self.attr_metadata(attr, 'format')
if attrformat:
return self.mtc_transform(value, attrformat, format,
self.req.encoding)
elif attrtype == 'Bytes':
- attrformat = self.attribute_metadata(attr, 'format')
+ attrformat = self.attr_metadata(attr, 'format')
if attrformat:
- encoding = self.attribute_metadata(attr, 'encoding')
+ encoding = self.attr_metadata(attr, 'encoding')
return self.mtc_transform(value.getvalue(), attrformat, format,
encoding)
return u''
--- a/rtags.py Wed Apr 15 17:00:58 2009 +0200
+++ b/rtags.py Wed Apr 15 17:30:03 2009 +0200
@@ -27,6 +27,11 @@
assert role in ('subject', 'object'), role
self._tagdefs[(str(rtype), role, str(stype), str(otype))] = tag
+ def del_rtag(self, rtype, role, stype='*', otype='*'):
+ assert not self.use_set
+ assert role in ('subject', 'object'), role
+ del self._tagdefs[(str(rtype), role, str(stype), str(otype))]
+
def rtag(self, rtype, role, stype='*', otype='*'):
assert not self.use_set
for key in reversed(self._get_keys(rtype, role, stype, otype)):
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/data/cubes/file/__pkginfo__.py Wed Apr 15 17:30:03 2009 +0200
@@ -0,0 +1,54 @@
+# pylint: disable-msg=W0622
+"""cubicweb-file packaging information"""
+
+distname = "cubicweb-file"
+modname = distname.split('-', 1)[1]
+
+numversion = (1, 4, 3)
+version = '.'.join(str(num) for num in numversion)
+
+license = 'LGPL'
+copyright = '''Copyright (c) 2003-2009 LOGILAB S.A. (Paris, FRANCE).
+http://www.logilab.fr/ -- mailto:contact@logilab.fr'''
+
+author = "Logilab"
+author_email = "contact@logilab.fr"
+web = ''
+
+short_desc = "Raw file support for the CubicWeb framework"
+long_desc = """CubicWeb is a entities / relations bases knowledge management system
+developped at Logilab.
+.
+This package provides schema and views to store files and images in cubicweb
+applications.
+.
+"""
+
+from os import listdir
+from os.path import join
+
+CUBES_DIR = join('share', 'cubicweb', 'cubes')
+try:
+ data_files = [
+ [join(CUBES_DIR, 'file'),
+ [fname for fname in listdir('.')
+ if fname.endswith('.py') and fname != 'setup.py']],
+ [join(CUBES_DIR, 'file', 'data'),
+ [join('data', fname) for fname in listdir('data')]],
+ [join(CUBES_DIR, 'file', 'wdoc'),
+ [join('wdoc', fname) for fname in listdir('wdoc')]],
+ [join(CUBES_DIR, 'file', 'views'),
+ [join('views', fname) for fname in listdir('views') if fname.endswith('.py')]],
+ [join(CUBES_DIR, 'file', 'i18n'),
+ [join('i18n', fname) for fname in listdir('i18n')]],
+ [join(CUBES_DIR, 'file', 'migration'),
+ [join('migration', fname) for fname in listdir('migration')]],
+ ]
+except OSError:
+ # we are in an installed directory
+ pass
+
+
+cube_eid = 20320
+# used packages
+__use__ = ()
--- a/test/unittest_cwconfig.py Wed Apr 15 17:00:58 2009 +0200
+++ b/test/unittest_cwconfig.py Wed Apr 15 17:30:03 2009 +0200
@@ -11,7 +11,7 @@
def unabsolutize(path):
parts = path.split(os.sep)
for i, part in reversed(tuple(enumerate(parts))):
- if part in ('cubicweb', 'cubes', 'cubes'):
+ if part.startswith('cubicweb') or part == 'cubes':
return '/'.join(parts[i+1:])
raise Exception('duh? %s' % path)
@@ -20,6 +20,9 @@
self.config = ApptestConfiguration('data')
self.config._cubes = ('email', 'file')
+ def tearDown(self):
+ os.environ.pop('CW_CUBES_PATH', None)
+
def test_reorder_cubes(self):
# jpl depends on email and file and comment
# email depends on file
--- a/test/unittest_entity.py Wed Apr 15 17:00:58 2009 +0200
+++ b/test/unittest_entity.py Wed Apr 15 17:30:03 2009 +0200
@@ -183,28 +183,25 @@
def test_entity_unrelated(self):
p = self.add_entity('Personne', nom=u'di mascio', prenom=u'adrien')
e = self.add_entity('Tag', name=u'x')
- rschema = e.e_schema.subject_relation('tags')
related = [r.eid for r in e.tags]
self.failUnlessEqual(related, [])
- unrelated = [reid for rview, reid in e.vocabulary(rschema, 'subject')]
+ unrelated = [r[0] for r in e.unrelated('tags', 'Personne', 'subject')]
self.failUnless(p.eid in unrelated)
self.execute('SET X tags Y WHERE X is Tag, Y is Personne')
e = self.entity('Any X WHERE X is Tag')
- unrelated = [reid for rview, reid in e.vocabulary(rschema, 'subject')]
+ unrelated = [r[0] for r in e.unrelated('tags', 'Personne', 'subject')]
self.failIf(p.eid in unrelated)
def test_entity_unrelated_limit(self):
e = self.add_entity('Tag', name=u'x')
self.add_entity('Personne', nom=u'di mascio', prenom=u'adrien')
self.add_entity('Personne', nom=u'di mascio', prenom=u'gwen')
- rschema = e.e_schema.subject_relation('tags')
- self.assertEquals(len(e.unrelated(rschema, 'Personne', 'subject', limit=1)),
+ self.assertEquals(len(e.unrelated('tags', 'Personne', 'subject', limit=1)),
1)
def test_new_entity_unrelated(self):
e = self.etype_instance('EUser')
- rschema = e.e_schema.subject_relation('in_group')
- unrelated = [reid for rview, reid in e.vocabulary(rschema, 'subject')]
+ unrelated = [r[0] for r in e.unrelated('in_group', 'EGroup', 'subject')]
# should be default groups but owners, i.e. managers, users, guests
self.assertEquals(len(unrelated), 3)
--- a/test/unittest_vregistry.py Wed Apr 15 17:00:58 2009 +0200
+++ b/test/unittest_vregistry.py Wed Apr 15 17:30:03 2009 +0200
@@ -12,6 +12,8 @@
class YesSchema:
def __contains__(self, something):
return True
+
+WEBVIEWSDIR = join(BASE, 'web', 'views')
class VRegistryTC(TestCase):
@@ -20,10 +22,11 @@
self.vreg = CubicWebRegistry(config)
config.bootstrap_cubes()
self.vreg.schema = config.load_schema()
-
+
def test_load(self):
- self.vreg.load_file(join(BASE, 'web', 'views'), 'euser.py')
- self.vreg.load_file(join(BASE, 'web', 'views'), 'baseviews.py')
+ self.vreg.init_registration([WEBVIEWSDIR])
+ self.vreg.load_file(join(WEBVIEWSDIR, 'euser.py'), 'cubicweb.web.views.euser')
+ self.vreg.load_file(join(WEBVIEWSDIR, 'baseviews.py'), 'cubicweb.web.views.baseviews')
fpvc = [v for v in self.vreg.registry_objects('views', 'primary')
if v.__module__ == 'cubicweb.web.views.euser'][0]
fpv = fpvc(None, None)
@@ -31,8 +34,9 @@
self.assertRaises(AttributeError, fpv.render_entity_attributes, None, None)
def test_load_interface_based_vojects(self):
- self.vreg.load_file(join(BASE, 'web', 'views'), 'idownloadable.py')
- self.vreg.load_file(join(BASE, 'web', 'views'), 'baseviews.py')
+ self.vreg.init_registration([WEBVIEWSDIR])
+ self.vreg.load_file(join(WEBVIEWSDIR, 'idownloadable.py'), 'cubicweb.web.views.idownloadable')
+ self.vreg.load_file(join(WEBVIEWSDIR, 'baseviews.py'), 'cubicweb.web.views.baseviews')
# check loading baseviews after idownloadable isn't kicking interface based views
self.assertEquals(len(self.vreg['views']['primary']), 2)
@@ -57,6 +61,7 @@
class MyCard(Card):
__implements__ = (IMileStone,)
self.vreg.reset()
+ self.vreg._loadedmods[__name__] = {}
self.vreg.register_vobject_class(MyCard)
self.vreg.register_objects([join(BASE, 'web', 'views', 'iprogress.py')])
# check progressbar isn't kicked
--- a/web/form.py Wed Apr 15 17:00:58 2009 +0200
+++ b/web/form.py Wed Apr 15 17:30:03 2009 +0200
@@ -388,7 +388,7 @@
msg = kwargs.pop('submitmsg', None)
super(EntityFieldsForm, self).__init__(*args, **kwargs)
if self.edited_entity is None:
- self.edited_entity = self.complete_entity(self.row)
+ self.edited_entity = self.complete_entity(self.row, self.col)
self.form_add_hidden('__type', eidparam=True)
self.form_add_hidden('eid')
if msg is not None:
@@ -486,14 +486,14 @@
entity = self.edited_entity
if field.eidparam and entity.e_schema.has_metadata(field.name, 'format') and (
entity.has_eid() or '%s_format' % field.name in entity):
- return self.edited_entity.attribute_metadata(field.name, 'format')
+ return self.edited_entity.attr_metadata(field.name, 'format')
return self.req.property_value('ui.default-text-format')
def form_field_encoding(self, field):
entity = self.edited_entity
if field.eidparam and entity.e_schema.has_metadata(field.name, 'encoding') and (
entity.has_eid() or '%s_encoding' % field.name in entity):
- return self.edited_entity.attribute_metadata(field.name, 'encoding')
+ return self.edited_entity.attr_metadata(field.name, 'encoding')
return super(EntityFieldsForm, self).form_field_encoding(field)
def form_field_error(self, field):
--- a/web/formrenderers.py Wed Apr 15 17:00:58 2009 +0200
+++ b/web/formrenderers.py Wed Apr 15 17:30:03 2009 +0200
@@ -20,24 +20,35 @@
class FormRenderer(object):
"""basic renderer displaying fields in a two columns table label | value
"""
+ display_fields = None # None -> all fields
+ display_label = True
+ display_help = True
+ display_progress_div = True
button_bar_class = u'formButtonBar'
- def __init__(self, display_fields=None, display_label=True,
- display_help=True, button_bar_class=None):
- self.display_fields = display_fields # None -> all fields
- self.display_label = display_label
- self.display_help = display_help
- if button_bar_class is not None:
- self.button_bar_class = button_bar_class
-
+ def __init__(self, **kwargs):
+ if self._set_options(kwargs):
+ raise ValueError('unconsumed arguments %s' % kwargs)
+
+ def _set_options(self, kwargs):
+ for key in ('display_fields', 'display_label', 'display_help',
+ 'display_progress_div', 'button_bar_class'):
+ try:
+ setattr(self, key, kwargs.pop(key))
+ except KeyError:
+ continue
+ return kwargs
+
# renderer interface ######################################################
def render(self, form, values):
+ self._set_options(values)
form.add_media()
data = []
w = data.append
w(self.open_form(form, values))
- w(u'<div id="progress">%s</div>' % form.req._('validating...'))
+ if self.display_progress_div:
+ w(u'<div id="progress">%s</div>' % form.req._('validating...'))
w(u'<fieldset>')
w(tags.input(type=u'hidden', name=u'__form_id',
value=values.get('formvid', form.id)))
--- a/web/formwidgets.py Wed Apr 15 17:00:58 2009 +0200
+++ b/web/formwidgets.py Wed Apr 15 17:30:03 2009 +0200
@@ -203,19 +203,19 @@
input will be generated for each possible value.
"""
type = 'radio'
- setdomid = False # by default, don't set id attribute on radio input
def render(self, form, field):
name, curvalues, attrs = self._render_attrs(form, field)
+ domid = attrs.pop('id', None)
options = []
- for label, value in field.vocabulary(form):
+ for i, (label, value) in enumerate(field.vocabulary(form)):
+ iattrs = attrs.copy()
+ if i == 0 and domid is not None:
+ iattrs['id'] = domid
if value in curvalues:
- tag = tags.input(name=name, type=self.type, value=value,
- checked='checked', **attrs)
- else:
- tag = tags.input(name=name, type=self.type, value=value, **attrs)
- tag += label + '<br/>'
- options.append(tag)
+ iattrs['checked'] = u'checked'
+ tag = tags.input(name=name, type=self.type, value=value, **iattrs)
+ options.append(tag + label + '<br/>')
return '\n'.join(options)
@@ -269,11 +269,11 @@
def init_ajax_attributes(attrs, wdgtype, loadtype=u'auto'):
try:
- attrs[u'klass'] += u' widget'
+ attrs['klass'] += u' widget'
except KeyError:
- attrs[u'klass'] = u'widget'
- attrs.setdefault(u'cubicweb:wdgtype', wdgtype)
- attrs.setdefault(u'cubicweb:loadtype', loadtype)
+ attrs['klass'] = u'widget'
+ attrs.setdefault('cubicweb:wdgtype', wdgtype)
+ attrs.setdefault('cubicweb:loadtype', loadtype)
class AjaxWidget(FieldWidget):
@@ -282,7 +282,7 @@
super(AjaxWidget, self).__init__(**kwargs)
init_ajax_attributes(self.attrs, wdgtype)
if inputid is not None:
- self.attrs[u'cubicweb:inputid'] = inputid
+ self.attrs['cubicweb:inputid'] = inputid
def render(self, form, field):
self.add_media(form)
@@ -342,7 +342,7 @@
<input type="text" id="newopt" />
<a href="javascript:noop()" id="add_newopt"> </a></div>
'''
-
+
# buttons ######################################################################
class Button(Input):
--- a/web/test/test_views.py Wed Apr 15 17:00:58 2009 +0200
+++ b/web/test/test_views.py Wed Apr 15 17:30:03 2009 +0200
@@ -45,6 +45,7 @@
self.failUnless('jquery.tablesorter.js' in self.view('table', rset))
def test_js_added_only_once(self):
+ self.vreg._loadedmods[__name__] = {}
self.vreg.register_vobject_class(SomeView)
rset = self.execute('EUser X')
source = self.view('someview', rset).source
--- a/web/test/unittest_form.py Wed Apr 15 17:00:58 2009 +0200
+++ b/web/test/unittest_form.py Wed Apr 15 17:30:03 2009 +0200
@@ -1,7 +1,7 @@
from logilab.common.testlib import unittest_main, mock_object
from cubicweb import Binary
from cubicweb.devtools.testlib import WebTest
-from cubicweb.web.form import EntityFieldsForm, FormRenderer
+from cubicweb.web.form import EntityFieldsForm, FieldsForm, FormRenderer
from cubicweb.web.formfields import (IntField, StringField, RichTextField,
DateTimeField, DateTimePicker,
FileField, EditableFileField)
@@ -9,6 +9,16 @@
from cubicweb.web.views.workflow import ChangeStateForm
+class FieldsFormTC(WebTest):
+
+ def test_form_field_format(self):
+ form = FieldsForm(self.request(), None)
+ self.assertEquals(form.form_field_format(None), 'text/html')
+ self.execute('INSERT EProperty X: X pkey "ui.default-text-format", X value "text/rest", X for_user U WHERE U login "admin"')
+ self.commit()
+ self.assertEquals(form.form_field_format(None), 'text/rest')
+
+
class EntityFieldsFormTC(WebTest):
def setUp(self):
@@ -17,6 +27,44 @@
self.entity = self.user(self.req)
self.renderer = FormRenderer()
+ def test_form_field_vocabulary_unrelated(self):
+ b = self.add_entity('BlogEntry', title=u'di mascii code', content=u'a best-seller')
+ t = self.add_entity('Tag', name=u'x')
+ form1 = EntityFieldsForm(self.request(), None, entity=t)
+ unrelated = [reid for rview, reid in form1.subject_relation_vocabulary('tags')]
+ self.failUnless(b.eid in unrelated, unrelated)
+ form2 = EntityFieldsForm(self.request(), None, entity=b)
+ unrelated = [reid for rview, reid in form2.object_relation_vocabulary('tags')]
+ self.failUnless(t.eid in unrelated, unrelated)
+ self.execute('SET X tags Y WHERE X is Tag, Y is BlogEntry')
+ unrelated = [reid for rview, reid in form1.subject_relation_vocabulary('tags')]
+ self.failIf(b.eid in unrelated, unrelated)
+ unrelated = [reid for rview, reid in form2.object_relation_vocabulary('tags')]
+ self.failIf(t.eid in unrelated, unrelated)
+
+ def test_form_field_vocabulary_new_entity(self):
+ e = self.etype_instance('EUser')
+ form = EntityFieldsForm(self.request(), None, entity=e)
+ unrelated = [rview for rview, reid in form.subject_relation_vocabulary('in_group')]
+ # should be default groups but owners, i.e. managers, users, guests
+ self.assertEquals(unrelated, [u'guests', u'managers', u'users'])
+
+ def test_subject_in_state_vocabulary(self):
+ # on a new entity
+ e = self.etype_instance('EUser')
+ form = EntityFieldsForm(self.request(), None, entity=e)
+ states = list(form.subject_in_state_vocabulary('in_state'))
+ self.assertEquals(len(states), 1)
+ self.assertEquals(states[0][0], u'activated') # list of (combobox view, state eid)
+ # on an existant entity
+ e = self.user()
+ form = EntityFieldsForm(self.request(), None, entity=e)
+ states = list(form.subject_in_state_vocabulary('in_state'))
+ self.assertEquals(len(states), 1)
+ self.assertEquals(states[0][0], u'deactivated') # list of (combobox view, state eid)
+
+
+
# form view tests #########################################################
def test_massmailing_formview(self):
--- a/web/test/unittest_views_editforms.py Wed Apr 15 17:00:58 2009 +0200
+++ b/web/test/unittest_views_editforms.py Wed Apr 15 17:30:03 2009 +0200
@@ -2,12 +2,21 @@
from cubicweb.devtools.apptest import EnvBasedTC
from cubicweb.devtools.testlib import WebTest
from cubicweb.web.views.editforms import AutomaticEntityForm as AEF
-
+from cubicweb.web.formwidgets import AutoCompletionWidget
def rbc(entity, category):
return [(rschema.type, x) for rschema, tschemas, x in AEF.erelations_by_category(entity, category)]
class AutomaticEntityFormTC(EnvBasedTC):
+ def test_custom_widget(self):
+ AEF.rwidgets.set_rtag(AutoCompletionWidget, 'login', 'subject', 'EUser')
+ form = self.vreg.select_object('forms', 'edition', self.request(), None,
+ entity=self.user())
+ field = form.field_by_name('login')
+ self.assertIsInstance(field.widget, AutoCompletionWidget)
+ AEF.rwidgets.del_rtag('login', 'subject', 'EUser')
+
+
def test_euser_relations_by_category(self):
#for (rtype, role, stype, otype), tag in AEF.rcategories._tagdefs.items():
# if rtype == 'tags':
--- a/web/views/editcontroller.py Wed Apr 15 17:00:58 2009 +0200
+++ b/web/views/editcontroller.py Wed Apr 15 17:30:03 2009 +0200
@@ -205,19 +205,23 @@
# submitted, since it will think the attribute is not modified
elif isinstance(value, unicode):
# file modified using a text widget
- value = Binary(value.encode(entity.attribute_metadata(attr, 'encoding')))
+ encoding = entity.attr_metadata(attr, 'encoding')
+ value = Binary(value.encode(encoding))
else:
- # (filename, mimetype, stream)
+ # value is a 3-uple (filename, mimetype, stream)
val = Binary(value[2].read())
if not val.getvalue(): # usually an unexistant file
value = None
else:
val.filename = value[0]
- if entity.e_schema.has_metadata(attr, 'format'):
- key = '%s_format' % attr
- formparams[key] = value[1]
- self.relations.append('X %s_format %%(%s)s'
- % (attr, key))
+ # ignore browser submitted MIME type since it may be buggy
+ # XXX add a config option to tell if we should consider it
+ # or not?
+ #if entity.e_schema.has_metadata(attr, 'format'):
+ # key = '%s_format' % attr
+ # formparams[key] = value[1]
+ # self.relations.append('X %s_format %%(%s)s'
+ # % (attr, key))
# XXX suppose a File compatible schema
if entity.e_schema.has_subject_relation('name') \
and not formparams.get('name'):
--- a/web/views/editforms.py Wed Apr 15 17:00:58 2009 +0200
+++ b/web/views/editforms.py Wed Apr 15 17:30:03 2009 +0200
@@ -118,7 +118,8 @@
cssstyle='display: none',
onsubmit=self.onsubmit % locals())
renderer = FormRenderer(display_label=False, display_help=False,
- display_fields=(rtype,), button_bar_class='buttonbar')
+ display_fields=(rtype,), button_bar_class='buttonbar',
+ display_progress_div=False)
self.w(tags.div(value, klass='editableField', id=divid,
ondblclick=self.ondblclick % locals()))
self.w(form.form_render(renderer=renderer))
--- a/web/views/eproperties.py Wed Apr 15 17:00:58 2009 +0200
+++ b/web/views/eproperties.py Wed Apr 15 17:30:03 2009 +0200
@@ -108,6 +108,8 @@
req = self.req
_ = req._
w(u'<h1>%s</h1>\n' % _(self.title))
+ # we don't want this in each sub-forms
+ w(u'<div id="progress">%s</div>' % self.req._('validating...'))
for label, group, form in sorted((_(g), g, f)
for g, f in mainopts.iteritems()):
status = css_class(self._group_status(group))
@@ -173,7 +175,7 @@
form.form_add_hidden('__redirectpath', path)
for key in keys:
self.form_row(form, key, splitlabel)
- return form.form_render()
+ return form.form_render(display_progress_div=False)
def form_row(self, form, key, splitlabel):
entity = self.entity_for_key(key)
--- a/web/views/tableview.py Wed Apr 15 17:00:58 2009 +0200
+++ b/web/views/tableview.py Wed Apr 15 17:30:03 2009 +0200
@@ -326,4 +326,3 @@
class EditableInitialTableTableView(InitialTableView):
id = 'editable-initialtable'
finalview = 'editable-final'
-
--- a/web/views/wdoc.py Wed Apr 15 17:00:58 2009 +0200
+++ b/web/views/wdoc.py Wed Apr 15 17:30:03 2009 +0200
@@ -16,7 +16,7 @@
from cubicweb.selectors import match_form_params
from cubicweb.view import StartupView
-from cubicweb.utils import strptime
+from cubicweb.utils import strptime, todate
from cubicweb.common.uilib import rest_publish
from cubicweb.web import NotFound
@@ -192,6 +192,7 @@
title = self.req._(self.title)
restdata = ['.. -*- coding: utf-8 -*-', '', title, '='*len(title), '']
w = restdata.append
+ today = date.today()
for fpath in self.config.locate_all_files(rid):
cl = ChangeLog(fpath)
encoding = 'utf-8'
@@ -205,9 +206,9 @@
w(unicode(line, encoding))
for entry in cl.entries:
if entry.date:
- edate = strptime(entry.date, '%Y-%m-%d')
+ edate = todate(strptime(entry.date, '%Y-%m-%d'))
else:
- edate = date.today()
+ edate = today
messages = []
for msglines, submsgs in entry.messages:
msgstr = unicode(' '.join(l.strip() for l in msglines), encoding)
@@ -225,7 +226,7 @@
fdate = self.format_date(edate)
w(u'\n%s' % fdate)
w('~' * len(fdate))
- latestdate = date
+ latestdate = edate
for msg in messages:
w(u'* %s' % msg)
i += 1
--- a/web/widgets.py Wed Apr 15 17:00:58 2009 +0200
+++ b/web/widgets.py Wed Apr 15 17:30:03 2009 +0200
@@ -409,7 +409,7 @@
entity.req.fckeditor_config()
if with_format:
if entity.has_eid():
- format = entity.attribute_metadata(self.name, 'format')
+ format = entity.attr_metadata(self.name, 'format')
else:
format = ''
frname = eid_param(self.name + '_format', entity.eid)
@@ -513,14 +513,14 @@
def _edit_render(self, entity):
wdgs = [self._file_wdg(entity)]
- if entity.attribute_metadata(self.name, 'format') in ('text/plain', 'text/html', 'text/rest'):
+ if entity.attr_metadata(self.name, 'format') in ('text/plain', 'text/html', 'text/rest'):
msg = self._edit_msg(entity)
wdgs.append(u'<p><b>%s</b></p>' % msg)
twdg = TextWidget(self.vreg, self.subjtype, self.rschema, self.objtype)
twdg.rname = self.rname
data = getattr(entity, self.name)
if data:
- encoding = entity.attribute_metadata(self.name, 'encoding')
+ encoding = entity.attr_metadata(self.name, 'encoding')
try:
entity[self.name] = unicode(data.getvalue(), encoding)
except UnicodeError: