From alan at balclutha.org Fri Dec 30 07:44:42 2005 From: alan at balclutha.org (Alan Milligan) Date: Fri, 30 Dec 2005 17:44:42 +1100 Subject: [icalendar-dev] util.py/tools.py uid patches Message-ID: <43B4D75A.5090005@balclutha.org> Hi, I've just been making some efforts to port PloneiCalendar to this python-icalendar library (as available at https://linux.last-bastion.net/RPC2/up2date/plope/item949227908). I've attached some patches for some changes to the uid generation which was quite broken. To tell you the truth, I think I'll probably port this to using the uuidgen utility that comes with e2fsprogs as we don't really care about non-unix server environments and this is a fairly industry-strength implementation. Something else I have noted in this port is the non-transparency in doing datetime arithmetic :( Specifically, datetime.date objects (or rather vDDDatetime objects with underlying datetime.date representations) are created quite readily but these do not allow timedelta creations when applied to datetime.datetime instances (ie TypeError when doing datetime.date - datetime.datetime). While one could argue that there should be methods available within datetime.date and datetime.time to promote these to datetime.datetime instances, but I'm having to do some ugly conversions in places. Similarly, the vDatetime stuff could also support these __add__ and __sub__ features to behave as full first-class citizens (a __len__ function would also help in this regard). Any thoughts on getting these into the next release?? Alan -------------- next part -------------- A non-text attachment was scrubbed... Name: iCalendar-uuidgen.patch Type: text/x-patch Size: 1563 bytes Desc: not available Url : http://codespeak.net/pipermail/icalendar-dev/attachments/20051230/c4b2ea2b/attachment.bin From maxm at mxm.dk Fri Dec 30 12:27:02 2005 From: maxm at mxm.dk (Max M) Date: Fri, 30 Dec 2005 12:27:02 +0100 Subject: [icalendar-dev] util.py/tools.py uid patches In-Reply-To: <43B4D75A.5090005@balclutha.org> References: <43B4D75A.5090005@balclutha.org> Message-ID: <43B51986.4020405@mxm.dk> Alan Milligan wrote: >Similarly, the vDatetime stuff could also support these __add__ and >__sub__ features to behave as full first-class citizens (a __len__ >function would also help in this regard). Any thoughts on getting these >into the next release?? > I tried that approach at first, but it wasn't practical. datetime arithmetic returns subclasses of the same type as itself. So to be able to do datetime arithmetic in vDateTime, vDate, vDuration etc. they would need to subclass their corresponding datetime classes, and overwrite all the arithmetic methods, just to do the arithemtic. And then they would still need to be converted to datetime in most cases. And if you need to do arithmetic with objects of a third type you cannot do that either. So for each kind of datetime subclass you will need to do those conversions. Which makes it a squared problem to the number of different datetime types. so I decided that it would be smarter to simply return datetime objects and then do the arithmetic in those. I think that the simplest and most pratical approach would be to make a small library of functions, or perhapse better, an adapter for doing arithmetics and conversions for objects supporting the datetime interfaces. That library should then allways return straight datetime types. Pseudocode:: >>> dt1 = DTWrapper(vDateTime()) >>> dt2 = DTWrapper(SomeOtherSubclass()) >>> dt1 + dt2 datetime.datetime() -- hilsen/regards Max M, Denmark http://www.mxm.dk/ IT's Mad Science From alan at balclutha.org Fri Dec 30 16:43:48 2005 From: alan at balclutha.org (Alan Milligan) Date: Sat, 31 Dec 2005 02:43:48 +1100 Subject: [icalendar-dev] util.py/tools.py uid patches In-Reply-To: <43B51986.4020405@mxm.dk> References: <43B4D75A.5090005@balclutha.org> <43B51986.4020405@mxm.dk> Message-ID: <43B555B4.10803@balclutha.org> Max M wrote: > Alan Milligan wrote: > >> Similarly, the vDatetime stuff could also support these __add__ and >> __sub__ features to behave as full first-class citizens (a __len__ >> function would also help in this regard). Any thoughts on getting these >> into the next release?? >> > > I tried that approach at first, but it wasn't practical. datetime > arithmetic returns subclasses of the same type as itself. > > So to be able to do datetime arithmetic in vDateTime, vDate, vDuration > etc. they would need to subclass their corresponding datetime classes, > and overwrite all the arithmetic methods, just to do the arithemtic. And > then they would still need to be converted to datetime in most cases. > And if you need to do arithmetic with objects of a third type you cannot > do that either. So for each kind of datetime subclass you will need to > do those conversions. Which makes it a squared problem to the number of > different datetime types. I must say, I don't see the problem you're describing. That would be somewhat synonymous with multiple dispatch in a statically typed language - see Scott Myer's classic "More Effective C++" for an excellent treatise on this ;) Besides, this is a closed system - unless someone is considering describing geological or quantum physics timeframes of course, we have all the types we expect ;) > > so I decided that it would be smarter to simply return datetime objects > and then do the arithmetic in those. Well, we definitely need proper arithmetic for the future. For example, adding a vDuration to a vEvent would be fairly common in any project management application. Similarly, one could wish to know how long 50% of a vEvent represented as a vDuration say ... However, there is no clean API returning these datetime objects yet. In many cases, I'm being surprised by the dt member being of an incompatible datetime type, and I'd rather call API methods than rely upon an implementation artifact in the first place. > > I think that the simplest and most pratical approach would be to make a > small library of functions, or perhapse better, an adapter for doing > arithmetics and conversions for objects supporting the datetime > interfaces. That library should then allways return straight datetime > types. Pseudocode:: > > >>>> dt1 = DTWrapper(vDateTime()) >>>> dt2 = DTWrapper(SomeOtherSubclass()) >>>> dt1 + dt2 > datetime.datetime() > I don't think that this is necessary, nor advisable, as we've excellent run-time dispatch working for us in Python and DTWrapper is going to have the same ugly construct you'd write in existing classes anyway. I actually took the effort to do a quick UML scribble for the icalendar Date/Time classes and have some suggestions for moving ahead. Firstly, there is an anomaly within the vTime class directly inheriting from time. In many respects, all of these classes could inherit from their datetime equivalent, and it's certainly necessary to provide an icalendar abstraction layer over these classes. I have a preference for the containment model you've mostly used, simply because we might find ourselves surprised by default arithmetic operations in these superclasses, which would also need to be overridden to return correct types regardless. I'd suggest making vTime contain a time instance for consistency more than anything ;) vDate, vDateTime, vTime, vDDDTypes all should implement an as_datetime() function from which to provide common implementation to perform arithmetic. vDuration, vPeriod should have an as_timedelta() function similarly (maybe even start_datetime, end_datetime for vPeriod). With these, one can explicitly map to/from icalendar to datetime API's if required. If one was to be a little lazy, one could implement a base class for vDate, vDateTime, vTime, vDDDTypes with: def __sub__(self, other): return vDuration(self.as_datetime(), other.as_datetime()) But I think things may be more subtle than that, and stronger type checking may be a good thing. I've made a cursory mapping of the kinds of arithmetic I see as worthy of implementing immediately: vDate - vDate = vDuration vTime - vTime = vDuration vDatetime -[vDatetime|vDate|vTime] = vDuration vDDDType - [vDDDType|vDatetime|vDate|vTime] = vDuration vDate +- vDuration = vDate || TypeError vDatetime +- vDuration = vDatetime vTime +- vDuration = vTime || TypeError vDDDType +- vDuration = vDDDType vDuration +- vDuration = vDuration vDuration */ [int/float/decimal] = vDuration vUTCOffset +- vUTCOffset = vUTCOffset vUTCOffset */ [int/float/decimal] = vUTCOffset ?? vPeriod */ [int/float/decimal] = vPeriod ?? I'm sure that there are other useful arithmetic interations with other types, but I'm quite confident that *meaningful* results from operations with other types apply for a *very* limited group of types (which can be discovered and extended over time). Seeing this well-described in (admittedly rather ugly if isinstance.. then.. elif ... else raise TypeError constructs) the class definitions would provide the basic contract for these features. I currently have a lot of ugliness in PloneiCalendar because of the vDDDType - vDDDType stuff requiring hacked into this code to determine event durations for display on calendars. I'd be happy to provide patches for something along the lines of what I've outlined here, incorporating the thoughts of participants on this list of course. I know its early days for this library, but we do need to evolve this type of functionality so it can elegantly express a wide range of calendaring problem domains. Thoughts? Alan