On Jan 12, 4:49 pm, Chris Nelson <[email protected]> wrote: > > He's my use case. TracPM defines > > class ITaskScheduler(Interface): > # Schedule each the ticket in ticketsByID with consideration for > # dependencies, estimated work, hours per day, etc. > # > # ticketsByID is a dictionary, indexed by numeric ticket ID, each > # ticket contains at least the fields returned by queryFields() > # and the whole list was processed by postQuery(). > # > # On exit, each ticket has t['calc_start'] and t['calc_finish'] > # set (FIXME - we should probably be able to configure those field > # names.) and can be accessed with TracPM.start() and finish(). > def scheduleTasks(self, options, ticketsByID): > """Called to schedule tasks""" > > and > > # tickets is an unordered list of tickets. Each ticket contains > # at least the fields returned by queryFields() and the whole list > # was processed by postQuery(). > def computeSchedule(self, options, tickets): > > computeSchedule() takes a list of tickets because that's the natural way > for other code to handle the data (as returned from a query, used to > display a Gantt, etc.) ITaskScheduler takes a dictionary because it had > to create one interinally anyway and I can have computeSchedule() build > it for all schedulers and use that as an opportunity to isolate the > caller of computeSchedule() from the vagaries of the scheduler (which > might want to update tickets in weird ways). > > So, my implementation of computeSchedule is: > > # Convert list to dictionary, making copies so schedule can > # mess with the tickets. > ticketsByID = {} > for t in tickets: > # FIXME - deepcopy fails here but with only copy, if the > # scheduler updates fields, those updates are visible to > # the caller. > ticketsByID[t['id']] = copy.copy(t) > > # Schedule the tickets > self.scheduler.scheduleTasks(options, ticketsByID) > > # Copy back the schedule results > for t in tickets: > for field in [ 'calc_start', 'calc_finish']: > t[field] = ticketsByID[t['id']][field] > > but it doesn't work, the caller still sees the changes to other fields > that the scheduler makes. > > > However, I can elaborate on the original topic of making a copy of the > > ticket values: > > > I left you a clue when I said that t.values will contain all the > > actual ticket data - the strings, datateime and integers that makes up > > the ticket data. > > I guess my clue detector is on the fritz. Sorry. > > > As these are all immutable values, there is no need > > > > > to deepcopy - a straight copy would suffice: > > > ticket_values = {} > > for t in tickets: > > ticket_values[t.id] = t.values.copy() > > > Or if you don't want to store it in a dict with ID as key but instead > > need to retain the order in a list, you need to include the ticket id > > in the values as it is not stored in values. So this should make a > > simplified copy of the tickets with just the values: > > > ticket_values = [] > > for t in tickets: > > t_vals = t.values.copy() > > t_vals['id'] = t.id > > ticket_values.append(t_vals) > > So, something like: > > # tickets is an unordered list of tickets. Each ticket contains > # at least the fields returned by queryFields() and the whole list > # was processed by postQuery(). > def computeSchedule(self, options, tickets): > # Convert list to dictionary, making copies so schedule can > # mess with the tickets. > ticketsByID = {} > for t in tickets: > ticketsByID[t['id']] = t.values.copy() > > # Schedule the tickets > self.scheduler.scheduleTasks(options, ticketsByID) > > # Copy back the schedule results > for t in tickets: > for field in [ 'calc_start', 'calc_finish']: > t[field] = ticketsByID[t['id']][field] > > ?
Yes, something like that looks like it should work. But if done like that, I still don't understand why you wouldn't just pass the tickets to your scheduler? Your code comments say you pass a copy so that schedulers can "mess" with the ticket data, but any Trac and plugin code should really be trusted to do the right thing with objects they get passed. I don't see the reason for building structures to hide and protect data when all is available anyway. It is Python after all... But, your code - you decide :-) :::simon -- You received this message because you are subscribed to the Google Groups "Trac Development" group. To post to this group, send email to [email protected]. To unsubscribe from this group, send email to [email protected]. For more options, visit this group at http://groups.google.com/group/trac-dev?hl=en.
