Thanks for all the responses. I'm using this both as an opportunity to
learn and to create something that does exactly what I want it to so
that's why I want to write my own program.

I decided to go with a flat list in the end. Now I have a working
implementation but it's not as nice as I think it could be. This is
what I need:

Each task has a set of attributes. Some of these attribute values have
an internal and an external value or representation (for example the
attribute deadline, which is a datetime internally and a formatted
string externally).

The list of tasks should be sortable, filterable, and searchable on
any of the attributes. This needs to be done on the internal
attributes. The list of tasks should also be easily displayed with the
attributes as formatted strings.

My attempt is pasted below. My question now is whether this is a
tenable implementation, what's wrong with it if not, and at which
point something like this is better done using a relational backend
with SQL. To me it seems like the operations that I want to be able to
do are more easily implemented in SQL (perhaps because I don't know
enough python...) but what are the drawbacks of such an approach?

The code:

#! /usr/bin/python
# vim: tabstop=4 expandtab shiftwidth=4
"""Flat implementation of tasklist."""

import cPickle as pickle
import datetime
import parsedatetime.parsedatetime

import pdb

class TaskList(object):
        defaults = ['rgtd','backend','testing 1','tomorrow',1,'open']
        def __init__(self):
                """Create an empty instance"""
                self.tasks = []
                self.modified = False

        def addTask(self,args):
                """Add a task."""
                args = args + self.defaults[len(args):]
                task = Task(args)
                self.tasks.append(task)
                self.modified = True
        
        def clear(self):
                """Delete all tasks."""
                self.tasks = []
                self.modified = True
        
        def removeTask(self,index):
                try:
                        task = self.tasks.pop(index)
                        self.modified = True
                        result = 'Removed task %i\t%s'  (index,task.__str__())
                except:
                        result = 'Removing task %i failed.' % index
                return result

        def setStatus(self,index,status):
                self.tasks[int(index)].status = str(status)
                self.modified=True

        def save(self, filename='.rgtddb'):
                """Save tasklist to file using pickle."""
                file = open(filename,'wb')
                pickle.dump(self,file)
                file.close()
                self.modified = False

        def sorted(self,field='int_deadline',ascending=False):
                """Return tasks sorted on int_deadline.
                Adapted from Python Cookbook 2ed Recipe 5.3.
                """
                intermed = [ (getattr(x, field), i, x) for i, x in 
enumerate(self.tasks) ]
                intermed.sort(reverse=ascending)
                return [x[-1] for x in intermed]
        
        def sort(self,field='int_deadline',ascending=False):
                self.tasks[:] = self.sorted(field,ascending)

        def output(self,displaymask=False):
                row = ''
                
                # Set displaymask to all fields in sortorder if no mask is 
supplied.
                if not displaymask:
                        displaymask = 
['status','deadline','cost','project','area','task']
                
                # Sort tasks
                self.sort()

                # Produce output string
                for index, task in enumerate(self.tasks):
                        row = row + '%i\t%s\n' % (index, 
'\t'.join([getattr(task,field)for
field in displaymask]))
                return row

class Task(object):
        def __init__(self,args):
                """Set all task attributes from an argument list in correct 
order."""
                self.project = args[0]
                self.area = args[1]
                self.task = args[2]
                self.deadline = args[3]
                self.cost = args[4]
                self.status = args[5]
        
        def setDeadline(self, value):
                """Use parsedatetime.parsedatetime to parse human-readable
                deadline entry to a datetime object.
                """
                parsedatetime.parsedatetime._debug=False
                calendar = parsedatetime.parsedatetime.Calendar()
                self.__deadline = 
datetime.datetime(*calendar.parse(value)[0][0:7])
                # datetime object is also stored in for internal use (sorting)
                self.int_deadline = 
datetime.datetime(*calendar.parse(value)[0][0:7])

        def getDeadline(self):
                """Return deadline as a string in the format day-month."""
                return self.__deadline.strftime('%d-%m %H')

        def setCost(self,value):
                """Set cost to a timedelta object."""
                self.__cost = datetime.timedelta(hours=int(value))
                # datetime object is also stored for internal use (sorting)
                self.int_cost = datetime.timedelta(hours=int(value))    
        
        def getCost(self):
                """Return a cost as a formatted string.
                Adapted from 
http://www.nabble.com/Formatting-timedelta-objects-td14259934.html
                """
                hours = self.__cost.seconds // 3600
                #minutes = (self.__cost.seconds % 3600) // 60
                return '%sh' % (hours)

        
        # Task properties that use overloading for setting and getting.
        deadline = property(getDeadline,setDeadline)
        cost = property(getCost,setCost)

#############################
# Methods that have not been
# encapsulated in TaskList.
#############################

def load(filename=False):
        """Load tasklist from disk using pickle."""
        if not filename:
                filename = '.rgtddb'
        ts = False
        try:
                ts = pickle.load(open(filename,'rb'))
                ts.modified = False
        except IOError:
                print 'The file %s does not exist.' % filename
        return ts

Best,

Alexander


On 1/18/08, Alan Gauld <[EMAIL PROTECTED]> wrote:
>
> "Tiger12506" <[EMAIL PROTECTED]> wrote in message
> news:[EMAIL PROTECTED]
> >>    def recursive_print(self, level=0):
> >>        print "\t"*level + self.cargo
> >>        for x in self.children:
> >>          recursive_print(x,level+1)
> >
> > Whoops. should be
> >
> > for x in self.children:
> >    x.recursive_print(level+1)
>
> Ah, you already caught it, my gmane feed ruinning a bit slow...
>
> Alan G
>
>
> _______________________________________________
> Tutor maillist  -  Tutor@python.org
> http://mail.python.org/mailman/listinfo/tutor
>
_______________________________________________
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor

Reply via email to