PyCON 2024 in Pittsburgh experience
I am a regular visitior of PyCON US conference since 2001 and I visited most
It is a common project requirement to extend the Plone user memberdata schema. The common approach is perhaps documented here (https://pypi.python.org/pypi/collective.examples.userdata). The additional fields of the memberdata must be defined as a zope.schema. Nothing special - same as definining forms using z3c.form or writing content-types with Dexterity. In a recent project we had a working memberdata extender and had to extend it with two schema.List fields. Both fields were added to the schema together with the following (working) adapter implementation:
from plone.app.users.browser.personalpreferences import UserDataPanelAdapter class EnhancedUserDataPanelAdapter(UserDataPanelAdapter): """ Adapter for extended user schema """ def __init__(self, context): super(EnhancedUserDataPanelAdapter, self).__init__(context) self.add_property('academic') self.add_property('gender') self.add_property('phone') self.add_property('academic') self.add_property('expertise') self.add_property('title') self.add_property('firstname') self.add_property('lastname') self.add_property('position') self.add_property('phone') self.add_property('db_projects') self.add_property('specialties') self.add_property('institution') self.add_property('institution_location') self.add_property('memberships') self.add_property('projects') self.add_property('gender') self.add_property('birthday') self.add_property('cooperation_interests') self.add_property('locations') def add_property(self, name, value=None): fget = lambda self: self._get_property(name) fset = lambda self, value: self._set_property(name, value) setattr(self.__class__, name, property(fget, fset)) setattr(self, '_' + name, value) def _set_property(self, name, value): return self.context.setMemberProperties({name: value}) def _get_property(self, name): return self.context.getProperty(name, None)
After restarting Plone, the @@user-information view crashed directly with the following non-speaking traceback:
Module ZPublisher.Publish, line 138, in publish Module ZPublisher.mapply, line 77, in mapply Module ZPublisher.Publish, line 48, in call_object Module zope.formlib.form, line 795, in __call__ Module five.formlib.formbase, line 50, in update Module zope.formlib.form, line 758, in update Module plone.fieldsets.form, line 30, in setUpWidgets Module zope.formlib.form, line 402, in setUpEditWidgets Module zope.formlib.form, line 332, in _createWidget Module zope.component._api, line 107, in getMultiAdapter Module zope.component._api, line 120, in queryMultiAdapter Module zope.component.registry, line 238, in queryMultiAdapter Module zope.interface.adapter, line 532, in queryMultiAdapter Module zope.component.security, line 77, in factory Module zope.formlib.itemswidgets, line 52, in CollectionInputWidget Module zope.component._api, line 109, in getMultiAdapter ComponentLookupError: ((, None, ), , u'')
What is the problem here from the programmer's prospective: no information about the real problem, no information about the schema field causing the problem. Further investigations using the Python debugger then showed that the problem is related to the two new schema.List fields. "Related" means that we still don't know the reason for the real problem after two or three hours debugging with two persons. Bad programmer experience because we do not get reasonable information from the underlaying view or call it user-information subsystem.
What makes the memberdata extension mechanism even more complicated:
From the high-level prospective: the schema definition of the extender should be complete enough for defining the memberdata extender. A programmer must be not be confronted with two or three levels of complexity for common tasks. In a perfect world this complexity would be hidden behind some reasonable API providing some reasonable consistency checks and error handling. Right now half-talented programmers are exposed to the full evil of the Zope Component Architecture. Key point of a programmer friendly environment are reasonable APIs. The Zope Component Architecture is not an API, it is an framework. In a perfect world a programmer must not know about the ZCA.plone.api is a step in the right direction however partly half-baked and not well-defined.