Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Various issues with plone.app.event 1.2 #147

Closed
zopyx opened this issue Mar 7, 2014 · 15 comments
Closed

Various issues with plone.app.event 1.2 #147

zopyx opened this issue Mar 7, 2014 · 15 comments

Comments

@zopyx
Copy link
Member

zopyx commented Mar 7, 2014

We are using plone.app.event 1.2 with Dexterity and Plone 4.3.2 in a migration project.
start and end dates are generated during from DateTime instances using

start = datetime.fromtimestamp(start_date_old.timeTime()
....

The @@edit view of the related event instances works.
Trying to save an event fails with this:

2014-03-07 09:03:54 ERROR Zope.SiteErrorLog 1394179434.560.952354709109 http://dev1.veit-schiele.de:5080/eteaching/news/tagungen/ilias_2008/@@edit
Traceback (innermost last):
Module ZPublisher.Publish, line 138, in publish
Module ZPublisher.mapply, line 77, in mapply
Module ZPublisher.Publish, line 48, in call_object
Module plone.z3cform.layout, line 66, in call
Module plone.z3cform.layout, line 50, in update
Module plone.dexterity.browser.edit, line 54, in update
Module plone.z3cform.fieldsets.extensible, line 59, in update
Module plone.z3cform.patch, line 30, in GroupForm_update
Module z3c.form.group, line 141, in update
Module plone.app.z3cform.csrf, line 21, in execute
Module z3c.form.action, line 98, in execute
Module z3c.form.button, line 315, in call
Module z3c.form.button, line 170, in call
Module plone.dexterity.browser.edit, line 25, in handleApply
Module z3c.form.group, line 97, in extractData
Module z3c.form.group, line 64, in extractData
Module z3c.form.form, line 146, in extractData
Module z3c.form.field, line 324, in extract
Module z3c.form.field, line 216, in validate
Module z3c.form.validator, line 201, in validate
Module z3c.form.validator, line 206, in validateObject
Module zope.interface.interface, line 590, in validateInvariants
Module plone.app.event.dx.behaviors, line 141, in validate_start_end
Module z3c.form.validator, line 175, in getattr
Module z3c.form.datamanager, line 71, in get
Module plone.app.event.dx.behaviors, line 342, in start
Module plone.app.event.dx.behaviors, line 399, in _prepare_dt_get
AttributeError: timezone

Calling the default view of an event fails with this:

2014-03-07 09:09:12 ERROR Zope.SiteErrorLog 1394179752.30.182035064437 http://dev1.veit-schiele.de:5080/eteaching/news/tagungen/ilias_2008/event_view
Traceback (innermost last):
Module ZPublisher.Publish, line 138, in publish
Module ZPublisher.mapply, line 77, in mapply
Module ZPublisher.Publish, line 48, in call_object
Module Products.Five.browser.metaconfigure, line 479, in call
Module Products.Five.browser.pagetemplatefile, line 125, in call
Module Products.Five.browser.pagetemplatefile, line 59, in call
Module zope.pagetemplate.pagetemplate, line 132, in pt_render
Module zope.pagetemplate.pagetemplate, line 240, in call
Module zope.tal.talinterpreter, line 271, in call
Module zope.tal.talinterpreter, line 343, in interpret
Module zope.tal.talinterpreter, line 888, in do_useMacro
Module zope.tal.talinterpreter, line 343, in interpret
Module zope.tal.talinterpreter, line 533, in do_optTag_tal
Module zope.tal.talinterpreter, line 518, in do_optTag
Module zope.tal.talinterpreter, line 513, in no_tag
Module zope.tal.talinterpreter, line 343, in interpret
Module zope.tal.talinterpreter, line 954, in do_defineSlot
Module zope.tal.talinterpreter, line 343, in interpret
Module zope.tal.talinterpreter, line 533, in do_optTag_tal
Module zope.tal.talinterpreter, line 518, in do_optTag
Module zope.tal.talinterpreter, line 513, in no_tag
Module zope.tal.talinterpreter, line 343, in interpret
Module zope.tal.talinterpreter, line 858, in do_defineMacro
Module zope.tal.talinterpreter, line 343, in interpret
Module zope.tal.talinterpreter, line 954, in do_defineSlot
Module zope.tal.talinterpreter, line 343, in interpret
Module zope.tal.talinterpreter, line 533, in do_optTag_tal
Module zope.tal.talinterpreter, line 518, in do_optTag
Module zope.tal.talinterpreter, line 513, in no_tag
Module zope.tal.talinterpreter, line 343, in interpret
Module zope.tal.talinterpreter, line 954, in do_defineSlot
Module zope.tal.talinterpreter, line 343, in interpret
Module zope.tal.talinterpreter, line 533, in do_optTag_tal
Module zope.tal.talinterpreter, line 518, in do_optTag
Module zope.tal.talinterpreter, line 513, in no_tag
Module zope.tal.talinterpreter, line 343, in interpret
Module zope.tal.talinterpreter, line 946, in do_defineSlot
Module zope.tal.talinterpreter, line 343, in interpret
Module zope.tal.talinterpreter, line 533, in do_optTag_tal
Module zope.tal.talinterpreter, line 518, in do_optTag
Module zope.tal.talinterpreter, line 513, in no_tag
Module zope.tal.talinterpreter, line 343, in interpret
Module zope.tal.talinterpreter, line 858, in do_defineMacro
Module zope.tal.talinterpreter, line 343, in interpret
Module zope.tal.talinterpreter, line 533, in do_optTag_tal
Module zope.tal.talinterpreter, line 518, in do_optTag
Module zope.tal.talinterpreter, line 513, in no_tag
Module zope.tal.talinterpreter, line 343, in interpret
Module zope.tal.talinterpreter, line 533, in do_optTag_tal
Module zope.tal.talinterpreter, line 518, in do_optTag
Module zope.tal.talinterpreter, line 513, in no_tag
Module zope.tal.talinterpreter, line 343, in interpret
Module zope.tal.talinterpreter, line 620, in do_insertText_tal
Module Products.PageTemplates.Expressions, line 225, in evaluateText
Module zope.tales.tales, line 696, in evaluate

  • URL: /home/ajung/.buildout/eggs/plone.app.event-1.2-py2.7.egg/plone/app/event/browser/event_view.pt
  • Line 19, Column 6
  • Expression: <PathExpr standard:u'data/start/isoformat'>
  • Names:
    {'args': (),
    'container': <Event at /eteaching/news/tagungen/ilias_2008>,
    'context': <Event at /eteaching/news/tagungen/ilias_2008>,
    'default': <object object at 0x7ff3f25f3b80>,
    'here': <Event at /eteaching/news/tagungen/ilias_2008>,
    'loop': {},
    'nothing': None,
    'options': {},
    'repeat': <Products.PageTemplates.Expressions.SafeMapping object at 0x7ff3d6cf6cb0>,
    'request': <HTTPRequest, URL=http://dev1.veit-schiele.de:5080/eteaching/news/tagungen/ilias_2008/event_view>,
    'root': ,
    'template': <Products.Five.browser.pagetemplatefile.ViewPageTemplateFile object at 0x7ff3d64ebdd0>,
    'traverse_subpath': [],
    'user': <PropertiedUser 'admin'>,
    'view': <Products.Five.metaclass.SimpleViewClass from /home/ajung/.buildout/eggs/plone.app.event-1.2-py2.7.egg/plone/app/event/browser/event_view.pt object at 0x7ff3d6b46090>,
    'views': <Products.Five.browser.pagetemplatefile.ViewMapper object at 0x7ff3d6b4fc90>}
    Module zope.tales.expressions, line 217, in call
    Module Products.PageTemplates.Expressions, line 147, in _eval
    Module zope.tales.expressions, line 124, in _eval
    Module Products.PageTemplates.Expressions, line 97, in trustedBoboAwareZopeTraverse
    Module zope.traversing.adapters, line 136, in traversePathElement
  • traceback_info: (None, 'isoformat')
    Module zope.traversing.adapters, line 50, in traverse
  • traceback_info: (None, 'isoformat', [])
    LocationError: (None, 'isoformat')

The instance dict of an event looks like this

pprint.pprint( app.eteaching.news.tagungen.ilias_2008.dict)
{'_Access_contents_information_Permission': ('Manager',
'Owner',
'Editor',
'Reader',
'Contributor',
'Site Administrator'),
'_Change_portal_events_Permission': ('Manager',
'Owner',
'Editor',
'Site Administrator'),
'_Modify_portal_content_Permission': ('Manager',
'Owner',
'Editor',
'Site Administrator'),
'_View_Permission': ('Manager',
'Owner',
'Editor',
'Reader',
'Contributor',
'Site Administrator'),
'ac_local_roles': {'crenz': ('Owner',)},
'provides': <zope.interface.Provides object at 0x8b0b090>,
'_owner': (['eteaching', 'acl_users'], 'crenz'),
'_plone.uuid': '1e735a0ea694470eb532efd691da0dc1',
'cmf_uid': <Products.CMFUid.UniqueIdAnnotationTool.UniqueIdAnnotation object at 0x8b07aa0>,
'contact_email': '',
'contact_name': '',
'contact_phone': '',
'creation_date': DateTime('2014/03/07 08:50:32.752047 GMT+1'),
'creators': (u'crenz', 'admin'),
'description': 'Die 7. Internationale ILIAS-Konferenz findet gemeinsam mit dem Fernausbildungskongress der Bundeswehr an der Helmut-Schmidt-Universit\xc3\xa4t in Hamburg statt.',
'end': datetime.datetime(2008, 9, 10, 17, 0),
'id': 'ilias_2008',
'location_id': 0,
'modification_date': DateTime('2014/03/07 08:50:32.968889 GMT+1'),
'portal_type': 'Event',
'start': datetime.datetime(2008, 9, 9, 9, 0),
'title': '7. Internationale ILIAS Konferenz 2008',
'version_id': 0,
'workflow_history': {'simple_publication_workflow': ({'action': None, 'review_state': 'private', 'actor': 'admin', 'comments': '', 'time': DateTime('2014/03/07 08:50:32.757447 GMT+1')}, {'action': None, 'review_state': 'visible', 'actor': None, 'comments': 'Setting state to visible', 'time': DateTime('2014/03/07 08:50:32.962604 GMT+1')})}}

@thet
Copy link
Member

thet commented Mar 13, 2014

hmm... looks like you haven't set the timezone of the event.
when creating events, you have to set the start and end dates via the IEventBasic behavior adapter or simply by using the IEventAccessor (the accessor also has a create method you might use. i'm not sure, if i should deprecate that - optinions on that are welcome). after creating or modifying, an ObjectModifiedEvent should be fired, so that the data_postprocessing method is executed, which does some timezone related modifications.

look for https://github.com/plone/plone.app.event/blob/master/plone/app/event/dx/behaviors.py#L557
and https://github.com/plone/plone.app.event/blob/master/plone/app/event/dx/behaviors.py#L574
to see, how the IEventAccessor creates / edits events.

if you just want to upgrade, you can use the provided upgrade steps.
if you upgrade from old ATCT ATEvents, first use the upgrade steps provided here: https://github.com/plone/plone.app.event/blob/master/plone/app/event/at/upgrades/configure.zcml
then, to migrate to plone.app.contenttypes use the migration steps provided there.

hope that helps... please give some feedback, if this issue can be closed

@zopyx
Copy link
Member Author

zopyx commented Mar 13, 2014

The issue is unrelated to timezones and upgrade. The Plone is is created from scratch with content generated through invokeFactory().

Also the start and end date use timezones

event.start
datetime.datetime(2014, 3, 20, 8, 30, tzinfo=<DstTzInfo 'CET' CET+1:00:00 STD>)
event.end
datetime.datetime(2014, 3, 22, 13, 0, tzinfo=<DstTzInfo 'CET' CET+1:00:00 STD>)

When I place context/start and context/end inside event_view.pt (having removed all other
TAL code) then I see that start and end are set correctly

2014-03-20 08:30:00+01:00
2014-03-22 13:00:00+01:00

So there is obviously something bad inside the adapter magic.

@thet
Copy link
Member

thet commented Mar 13, 2014

it is related to plone.app.event's timezone handling, as the traceback shows: AttributeError: timezone
every event start/end date in plone.app.event has timezones. that was one assumption we made: "no timezone-naive datetimes for plone.app.event".
so, what you'd have to do is to create an event, then adapt it with the IEventBasic behavior and then set the start and end dates on it. roughly like so:

event = invokeFactory...
from plone.app.event.dx.behaviors import IEventBasic
behavior = IEventBasic(event)
behavior.start = datetime(...)
behavior.end = datetime(...)

or simply:

from plone.event.interfaces import IEventAccessor
acc = IEventAccessor(event)
acc.start = DateTime()
acc.end = DateTime()

i agree, it's not obvious to not set the start/end datetimes directly on the context or via invokeFactory. but that's the way, plone.app.event works at the moment.

don't forget to set the portal's timezone to the main timezone your events are created in. otherwise UTC will be used.

@zopyx
Copy link
Member Author

zopyx commented Mar 13, 2014

Please don't take it personally but this is broken-by-design and completely absurd. Do I have to check as a developer for every single attribute of a content-type it this field is introduced through a behavior or defined directly as part of the content-type schema?

@zopyx
Copy link
Member Author

zopyx commented Mar 13, 2014

But anyway, the proposed solution does not work

    if portal_type_ == 'Event':
        if k in ('start', 'end'):
            from plone.event.interfaces import IEventAccessor
            if isinstance(v, DateTime):
                acc = IEventAccessor(new_obj)
                v = datetime.fromtimestamp(v.timeTime(), pytz.timezone('CET'))
                setattr(acc, k, v)
                continue

The error remains the same.

@thet
Copy link
Member

thet commented Mar 13, 2014

i don't take it personally. this is the way dexterity behaviors work. you have to adapt them to be sure that some setter/getter code is executed and thats what we need in this case.

if you find another way to solve the timezone setting issue you're welcome to contribute and i would be happy to integrate that. i also don't like that part of plone.app.event too much.

@thet
Copy link
Member

thet commented Mar 13, 2014

if you could give a bit more context, that would be helpful. what exactly is v or new_obj?
i'll take a look later on, have to hurry now...

@zopyx
Copy link
Member Author

zopyx commented Mar 13, 2014

'new_obj' is clearly the plone.app.event instance created using invokeFactory('Event') and v is the given datetime instance with CET timezone.

@zopyx
Copy link
Member Author

zopyx commented Mar 13, 2014

The solution is set the 'timezone' explicitely on the obj

new_obj = invokeFactory('Event',..)
new_obj.timezone = 'CET'
acc = IEventAccessor(new_obj)
acc.start = datetime(...)
....

Why is there no default for 'timezone'?

@thet
Copy link
Member

thet commented Mar 13, 2014

there is, but apparently that doesn't apply when using invokeFactory, where no z3c.form is involved:
https://github.com/plone/plone.app.event/blob/master/plone/app/event/dx/behaviors.py#L160

should be fixed.

@davisagli
Copy link
Sponsor Member

You can probably fix this by setting up the default using a defaultFactory directly on the field, rather than a ComputedWidgetAttribute. Dexterity's getattr knows how to look up field defaults, but it doesn't know anything about widgets.

@thet
Copy link
Member

thet commented Apr 17, 2014

these issues should now be solved with plone.app.event 2.0.
until it replaces the current master branch, you can find it here: https://github.com/plone/plone.app.event/tree/2.0.x

relevant changes from the changelog:

  • Remove Timezone field from IEventBasic behavior. Instead, store timezone information directly in the tzinfo object on start and end datetime objects.
  • Remove data_postprocessing event subscriber.
  • Make use of new z3c.form DataExtractedEvent and register the data_postprocessing_handler for this event. This adjusts the start and end date according to whole_day and open_end.
  • Use default_timezone DatetimeWidget property. All datetime objects from plone.app.widgets' DatetimeWidget now have this timezone, if not otherwise set by the user.
  • Use default and defaultFactory properties for behavior schema definitions to provide sane defaults for z3c.form and programmatically created Dexterity types (e.g. via plone.dextterity.utils.createContentInContainer). For that to work, remove the Behavior factory classes, use the default AttributeStorage and let IEventBasic and IEventRecurrence behaviors derive from IDXEvent resp. IDXEventRecurrence.

a how-to-use-it, which is hopefully quite complete, can be found here:
https://github.com/plone/plone.app.event/blob/2.0.x/docs/development.rst#setting-properties-directly-on-the-context

@thet thet closed this as completed Apr 17, 2014
@thet
Copy link
Member

thet commented Apr 17, 2014

i know, the "store timezone information directly on start / end properties" is discussed quite controversial. at wine/beer sprint @jensens , @regebro , @garbas and i were discussing this deeply and could not come up with any reason, why not to store the timezone information directly on these properties. with proper tzinfo objects, we can calculate from one timezone to another without any effort. we can also compare two datetimes with different timezones directly without having to convert them into the same base timezone.
given, we are using Python datetime and the pytz library, which we use both.
more on this here: https://github.com/plone/plone.app.event/blob/master/docs/designchoices.rst

@regebro
Copy link
Contributor

regebro commented Apr 17, 2014

It also makes import/export to iCalendar simpler.

@djowett
Copy link

djowett commented Oct 10, 2015

Was this resolved in 1.1.x branch? I'm getting this issue after using p.a.contenttypes migrator with plone.app.event 1.1.4

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants