3

So I'm writing a script to keep track of my correspondence. It takes the name of someone who emailed me, looks for its associated 'Friend object' in a shelved dictionary of Friend instances (or creates itself a new instance and stores it in the dictionary), then appends the current time to that instance's list of timestamps.

So for example, if the script runs with 'John Citizen' as the input, it finds the key 'John Citizen' in the dictionary, gets the instance associated with that key, goes to that instance's list and appends to that list a timestamp.

This is all working as I want it to, except for the appending.

Here's the friend object:

class Friend():
    def __init__(self, name):
        self.name = name
        self.timestamps = []

    def add_timestamp(self, timestamp):
        self.timestamps.append(timestamp)   

Here's the global function that processes the input into a name string. (The input comes from AppleScript and is always in this format:

Input: "First [Middles] Last <emailaddress@email.com>"



def process_arguments():

    parser = argparse.ArgumentParser()
    parser.add_argument("sender", help="The output from AppleScript")
    args = parser.parse_args()
    full_name = args.sender

    ## gets just the name
    words = full_name.split(' ')
    words.pop()
    full_name = ' '.join(words)

    ## takes away all the non alpha characters, newlines etc.
    alpha_characters = []
    for character in full_name:
        if character.isalpha() or character == " ":
            alpha_characters.append(character)
    full_name = ''.join(alpha_characters)   
    return full_name

And then here's the script handling that full_name string.

  ## Get the timestamp and name
now = datetime.datetime.now()
full_name = process_arguments()

## open the shelf to store and access all the friend information

shelf = shelve.open('/Users/Perrin/Library/Scripts/friend_shelf.db')

if full_name in shelf:
    shelf[full_name].add_timestamp(now)
    shelf.close
else:
    shelf[full_name] = Friend(full_name)
    shelf.close

I've tried to debug it and full_name in shelf evaluates to True and the problem is still happening.

I just can't seem to get that self.timestamps list to populate. I would really appreciate any help!

  • As an aside from your question. Wouldn't you want to append a time stamp in the initial creation of the Friend object? – Paul Rooney May 10 '15 at 09:26
  • 1
    where's the problem? – Liam May 10 '15 at 09:26
  • If I run the script with "John Citizen", it goes into the 'else' path and creates the object and stores it fine. If I run it again, it goes into the 'if' path, but I just can't get anything to go into that self.timestamps list. – Pez Picacious May 10 '15 at 09:28
  • Also are you sure `if full_name in shelf` is doing what you expect? There is a `has_key` method. Might this be the correct way to check if the key is present? – Paul Rooney May 10 '15 at 09:29
  • @PaulRooney That would be sensible, but I want to use this script again and again, generating a list of timestamps. The object won't be created every time, just found in the shelved dictionary. Also, yes, I'm sure that "if full_name in shelf" is evaluated as True. – Pez Picacious May 10 '15 at 09:29
  • Lookng at the shelve docs. Don't you need to extract the Friend instance, mutate it ( add time stamp) and set it back to the key? I'm looking [here](https://docs.python.org/2/library/shelve.html#example) – Paul Rooney May 10 '15 at 09:33
  • @PaulRooney Good thought, let me try. Edit: Yep, that was it. Thanks for the help, I didn't realise Shelve worked that way! – Pez Picacious May 10 '15 at 09:35
  • Or use writeback=True in shelve.open. – Paul Rooney May 10 '15 at 09:35

2 Answers2

1

You need to extract, mutate and store the object back in the shelf to persist it.

e.g

# extract
this_friend = shelf[full_name]
# mutate
this_friend.add_timestamp(now)
# re-add
shelf[full_name] = this_friend
shelf.close()

You can see an example of this in the python docs.

The other option is pass the writeback parameter as True to shelve.open and it will allow you to write to the keys directly.

Paul Rooney
  • 20,879
  • 9
  • 40
  • 61
0

@paulrooney answered this.

Objects in the shelf need to be removed from the shelf, assigned to a name, mutated (to add time stamp), then put back in the shelf. This code works fine.

shelf = shelve.open('/Users/Perrin/Library/Scripts/friend_shelf.db')

if full_name in shelf:
    this_friend = shelf[full_name]
    this_friend.add_timestamp(now)
    shelf[full_name] = this_friend
    print shelf[full_name].timestamps
    shelf.close

else:
    shelf[full_name] = Friend(full_name)
    this_friend = shelf[full_name]
    this_friend.add_timestamp(now)
    shelf[full_name] = this_friend
    shelf.close