Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 153 lines (135 sloc) 5.967 kb
8acd9c9 @urschrei Now using tweepy and Python 2.x syntax
authored
1 #!/usr/bin/python
2 # coding=utf-8
6272d51 @urschrei Added some more error handling (table creation, setting line position to...
authored
3 # This is useful: http://openbookproject.net//thinkCSpy/
4 # This, too: http://www.devshed.com/c/a/Python/Using-SQLite-in-Python/
5
4c189e4 @urschrei Tidying up
authored
6 # twitter: robo_dante/beatrice
7 # gmail: alighieribot2010/beatrice1265
8
829aa8e @urschrei renamed
authored
9 import sys
10 import os
11 import sqlite3
af39fda @urschrei Now handles coming to the end of the text file
authored
12 import datetime
a56e304 @urschrei Roughed in some error logging
authored
13 import logging
14 LOG_FILENAME = '/Users/sth/library/logs/python.log'
15 logging.basicConfig(filename=LOG_FILENAME,level=logging.ERROR)
8a28d9a @urschrei A trivial bit of error handling
authored
16
8ada174 @urschrei Was grabbing the ID from the table (row[0]) as opposed to the line posit...
authored
17 # tweepy stuff
2efd1aa @urschrei Tidying, editing readme
authored
18 import tweepy
8ada174 @urschrei Was grabbing the ID from the table (row[0]) as opposed to the line posit...
authored
19 auth=tweepy.BasicAuthHandler('robo_dante', 'beatrice')
20 api=tweepy.API(auth)
2f23e06 @urschrei Yet more tidying
authored
21
258beb7 @urschrei Now checking that the correct number of arguments is being passed on the...
authored
22 if len(sys.argv) < 3:
23 print "Not enough arguments. Please call the script like this: bookbyline.py filename.txt header"
af39fda @urschrei Now handles coming to the end of the text file
authored
24 now=datetime.datetime.now()
25 logging.error(now.strftime("%Y-%m-%d %H:%M") + " " + str(sys.argv[0]) + " " + "Not enough arguments")
258beb7 @urschrei Now checking that the correct number of arguments is being passed on the...
authored
26 sys.exit()
2f23e06 @urschrei Yet more tidying
authored
27
9d1011b @urschrei There is now a "Book" object, which has various class methods and proper...
authored
28 class Book:
b5f2674 @urschrei We now get our filename and header line from command-line input
authored
29 """ Create a Book object from a text file. Takes two arguments:
30 1. a filename, from which text will be read
31 2. a string used to identify header lines
32 A sqlite3 connection object is created, and an attempt it made to
5eab135 @urschrei Tidying up
authored
33 retrieve a row matching from a DB matching that of the filename which was passed. If no db is found, a new
34 DB is created and a table containing default values is inserted """
b5f2674 @urschrei We now get our filename and header line from command-line input
authored
35 def __init__(self, fname=None, hid=None):
9d1011b @urschrei There is now a "Book" object, which has various class methods and proper...
authored
36 self.name = fname
b5f2674 @urschrei We now get our filename and header line from command-line input
authored
37 self.header_id = hid
9d1011b @urschrei There is now a "Book" object, which has various class methods and proper...
authored
38 s = self.name.split(".")
39 self.db_name = str(s[0]) + ".db"
40 # create a SQLite connection, or create a new db and table
41 self.connection=sqlite3.connect(self.db_name)
42 self.cursor=self.connection.cursor()
43 try:
44 self.cursor.execute('SELECT * FROM position ORDER BY POSITION DESC LIMIT 1')
45 except sqlite3.OperationalError:
46 print "Couldn't find the specified table. Creating…"
47 # set up a new blank table, and insert a row which starts off at line 0
48 self.cursor.execute('CREATE TABLE position (id INTEGER PRIMARY KEY, position INTEGER, off_set INTEGER)')
49 db_lastline=0
50 self.cursor.execute('INSERT INTO position VALUES (null, ?, ?)',(db_lastline, 0))
51 try:
52 self.cursor.execute('SELECT * FROM position ORDER BY POSITION DESC LIMIT 1')
53 except sqlite3.OperationalError:
54 print "Still couldn't execute the SQL query, even though I created a new table. Giving up."
55 # close the SQLite connection, and quit
56 self.connection.commit()
57 self.connection.close()
58 sys.exit()
59 # get the highest page number, and the line display offset
60 row=self.cursor.fetchone()
61 self.db_lastline=row[1]
62 self.db_curpos=row[1]
63 self.off_set=row[2]
64 get_lines = list()
65 try:
5eab135 @urschrei Tidying up
authored
66 # try to open the specified text file for reading
9d1011b @urschrei There is now a "Book" object, which has various class methods and proper...
authored
67 with open(self.name, "r") as t_file:
68 for a_line in t_file:
69 if not a_line.strip():
70 continue
5eab135 @urschrei Tidying up
authored
71 # if we encounter a blank line, skip it, and carry on
9d1011b @urschrei There is now a "Book" object, which has various class methods and proper...
authored
72 else:
73 get_lines.append(a_line)
74 # would it be more efficient to open, read one line, and store byte position?
75 except IOError:
76 print "Couldn't open the text file for reading. Exiting."
77 sys.exit()
af39fda @urschrei Now handles coming to the end of the text file
authored
78 # Check that we haven't reached the end of the file
79 try:
80 self.lastline = get_lines[self.db_lastline]
81 except IndexError:
82 now=datetime.datetime.now()
83 logging.error(now.strftime("%Y-%m-%d %H:%M") + " " + str(sys.argv[0]) + " " + "Reached " + self.name + " EOF")
84 sys.exit()
85 try:
86 self.nextline = get_lines[self.db_lastline + 1]
87 except IndexError:
88 self.nextline=""
5eab135 @urschrei Tidying up
authored
89 # the poem starts on line 1, not line 0, so increase by 1, then subtract offset from 'real' line display
9d1011b @urschrei There is now a "Book" object, which has various class methods and proper...
authored
90 self.displayline=(self.db_lastline + 1) - self.off_set
91
92
93
3e61fa4 @urschrei We're now correctly handling an error in which the DB can't be updated, ...
authored
94 def format_tweet(self,newvals):
9d1011b @urschrei There is now a "Book" object, which has various class methods and proper...
authored
95 """ Properly format an input string based on whether it's a header line, or a poetry line
3e61fa4 @urschrei We're now correctly handling an error in which the DB can't be updated, ...
authored
96 If the current line begins with "CANTO", it's a header, so instead of displaying a line number,
97 we join the next line and increment both the line number and the line offset by 1. This means the
98 line numbers don't jump when a header is encountered, as the offset is subtracted from the display line.
99
100 Prints a properly-formatted string, either a canto, or a poetry line. """
9d1011b @urschrei There is now a "Book" object, which has various class methods and proper...
authored
101 #pattern='^CANTO'
102 #if re.search(pattern, input_string):
b5f2674 @urschrei We now get our filename and header line from command-line input
authored
103 if self.lastline.startswith(self.header_id):
3e61fa4 @urschrei We're now correctly handling an error in which the DB can't be updated, ...
authored
104 self.db_lastline += 1
105 newvals.append(self.db_lastline)
106 self.off_set += 1
107 newvals.append(self.off_set)
108 message = str(self.lastline) + str(self.nextline)
109 newvals.append(message)
9d1011b @urschrei There is now a "Book" object, which has various class methods and proper...
authored
110 else:
3e61fa4 @urschrei We're now correctly handling an error in which the DB can't be updated, ...
authored
111 newvals.append(self.db_lastline)
112 newvals.append(self.off_set)
113 message = 'l. ' + str(self.displayline) + ': ' + self.lastline
114 newvals.append(message)
115 return newvals
9d1011b @urschrei There is now a "Book" object, which has various class methods and proper...
authored
116 # what if it's neither a header nor a poetry line?
117
118
119
120 def emit_tweet(self):
af39fda @urschrei Now handles coming to the end of the text file
authored
121 now=datetime.datetime.now()
3e61fa4 @urschrei We're now correctly handling an error in which the DB can't be updated, ...
authored
122 """ First call the format_tweet() function, which correctly formats the current object's lastline and thisline
123 properties, depending on what they are, and then prints / tweets them. It then writes the updated last line
5eab135 @urschrei Tidying up
authored
124 printed and line display offset values the DB
125
126 Returns a list of values which are used to output the message and update the DB """
3e61fa4 @urschrei We're now correctly handling an error in which the DB can't be updated, ...
authored
127 # updates() will be filled with values which will be emitted following a successful DB update
128 updates=list()
129 self.format_tweet(updates)
130 # don't print the line unless the DB is updateable
9d1011b @urschrei There is now a "Book" object, which has various class methods and proper...
authored
131 try:
132 with self.connection:
5eab135 @urschrei Tidying up
authored
133 self.cursor.execute('UPDATE position SET position=?,off_set=? WHERE position=?',(updates[0] + 1, updates[1] \
134 , self.db_curpos))
3e61fa4 @urschrei We're now correctly handling an error in which the DB can't be updated, ...
authored
135 try:
136 print str(updates[2])
5eab135 @urschrei Tidying up
authored
137 # api.update_status(str(updates[2]))
3e61fa4 @urschrei We're now correctly handling an error in which the DB can't be updated, ...
authored
138 except:
139 print "Couldn't output the message."
af39fda @urschrei Now handles coming to the end of the text file
authored
140 logging.error(now.strftime("%Y-%m-%d %H:%M") + " " + str(sys.argv[0]) + " " + "Couldn't output the message")
9d1011b @urschrei There is now a "Book" object, which has various class methods and proper...
authored
141 except sqlite3.OperationalError:
142 print "Wasn't able to update the DB."
af39fda @urschrei Now handles coming to the end of the text file
authored
143 logging.error(now.strftime("%Y-%m-%d %H:%M") + " " + str(sys.argv[0]) + " " + "Couldn't update the DB")
9d1011b @urschrei There is now a "Book" object, which has various class methods and proper...
authored
144 # logging.error("Something went wrong, and the tweet couldn't be sent")
145 self.connection.close()
146
147
af39fda @urschrei Now handles coming to the end of the text file
authored
148
b5f2674 @urschrei We now get our filename and header line from command-line input
authored
149 # first argument (argv[0]) is always the filename – not what we want
150 b=Book(sys.argv[1],sys.argv[2])
9d1011b @urschrei There is now a "Book" object, which has various class methods and proper...
authored
151 b.emit_tweet()
152
Something went wrong with that request. Please try again.