On Wed, Aug 15, 2012 at 2:24 PM, Christopher Nelson <
[email protected]> wrote:
> Right. But I could create a pmDate class that had getter and setter
> methods and pass that around.
>
You would want to create a pmTask class, not a pmDate class. The getter
and setter will manipulate a piece of data on the class that has the getter
and setter: they'll be a getter and setter for the "date" aspect of the
"task" object.
The key to understanding this is that the getter and setter magic are
really just syntactic sugar for certain kinds of methods on class
instances. Once you have a class with .get_foo() and .set_foo(val)
methods, you can use the syntactic sugar to reduce calls to those methods
to what looks like attribute access and assignment.
A task is a hash of ticket attributes, not quite a whole ticket.
>
Okay, that seems feasible then -- presumably you control the code where
these "task" objects are instantiated. You can't put properties on a hash
or any other built-in data type, so you'll need to create a full class for
your "task" objects. When you instantiate these "task" objects, you'll
just create instances of your pmTask class and pass in the necessary hash
of ticket data. The class definition will then contain the syntactic sugar
for accessing and mutating the magic "start" and "finish" properties.
Right now, my TracPM code adds a '_calc_start' entry to the dictionary
> so `TracPM.start(t)` really just masks the name of the index with
> something not a lot more complicated than `return t['_calc_start']`.
>
So I think you'd want a class definition like
{{{
class pmTask(object):
def __init__(self, ticket_data):
self.ticket_data = ticket_data
def _get_start(self):
return self.ticket_data['_calc_start']
def _set_start(self, start):
self.ticket_data['_calc_start'] = start
start = property(_get_start, _set_start)
def _get_finish(self):
[etc]
}}}
Just to spell out fully what's happening here, this is all straightforward
non-magical code until you get to the ``start = property(_get_start,
_set_start) line`` -- which defines an attribute ``pmTask.start`` that
secretly calls pmTask._set_start() when assignment occurs and
pmTask._get_start() when access occurs.
TracPM would then set start and finish by invoking the setter like so
(assuming "t" is now an instance of pmTask)
{{{
t.start = somedate
t.finish = someotherdate
}}}
Note that this is completely equivalent to ``t._set_start(somedate)`` which
itself just reduces to ``t.ticket_data['_calc_start'] = somedate``.
And caller code would invoke the getter like:
{{{
for t in tasks:
start = t.start # under the hood Python is just treating this like
``start = t._get_start()``
}}}
The downside of defining the pmTask class in this way is that every *other*
piece of ticket data now has to be accessed via the t.ticket_data dict --
t.ticket_data['id'] instead of just t['id'] and so on. To clean this up,
it's actually possible for your pmTask class to just be a subclass of the
built-in dict type instead:
class pmTask(dict):
def _get_start(self):
return self['_calc_start'] # ``self`` is now dict-like in all respects,
so we can just use the magic key in the ``self`` dict
def _set_start(self, start):
self['_calc_start'] = start
start = property(_get_start, _set_start)
You'd then instantiate the objects by passing in a dict, and you'd be able
to treat them just like dicts in all circumstances but with the added bonus
of having this magic ``.start`` property that hides the details of how
"start" is generated.
Hope this helps,
Ethan
--
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.