Getting happier ;-), but wondering if I'm thinking pythonically
Graham Nicholls
graham at rockcons.co.uk
Tue May 20 16:10:29 EDT 2003
Hi, and thanks to everyone for their replies to my earlier thread.
The "Obfuscated Python" competition was a joke, BTW. I'm getting rsi from
replying to all the posts & email I've had, but I'm not complaining - I
appreciate it.
Anyway, heres something I'm writing - it will strip out the fonttable from
multiple rtf files, and eventually merge them, patchng up fornt references
later. Its so you can join several rtf files without losing font info.
The C version works, but is failing in some specific circumstances (I have
an _idea_ why). I thought I'd learn Python and do some useful coding at
the same time, but a couple of questions :
Firstly, is this in general, the right way? This is my second attempt - the
first program worked but didn't use classes, or optik, and was more limited
in scope. BTW is using external modules like optik a bad idea if you want
programs to be portable (doesn't matter for this program, but might)
second, I want to use split and a RE to split the fonttable at a pattern,
hence lines 99-109. This seems cumbersome - I'd like to do something like:
for (fnum,fdesc) in re.split(fntid_s,self.buff):
add_to_a dictionary
Anyway, thanks for looking - I hope I'm OK in posting this here?
Graham
1 #!/usr/bin/env python
2
3 # G.Nicholls
4 # Mon May 19 22:07:51 BST 2003
5 # Python script to build a common font table from a set of rtf files.
6
7 import string,os,sys
8 import re
9
10 # Use optik to handle command line.
11 from optik import OptionParser, OptionError
12
13 # Exit returns:
14 BAD_ARGS=1
15 OPEN_FAIL=2
16 CREAT_FAIL=3
17 NOT_RTF=4
18 FILE_ERR=5
19 INTERNAL_ERR=100
20
21 version = "0.2"
22
23 class rtffile:
24 def __init__(self,file_name):
25 """Create an instance of an rtffile object; calls
get_fonttbl"""
26 self.fname=file_name
27 try:
28 self.fhand=open(self.fname,"r")
29 except: # This seems to be deprecated - why?
30 print ("An error occurred opening the file %s" %
self.fname)
31 sys.exit(OPEN_FAIL)
32
33 # Read the file & then close it
34 self.buff=self.fhand.read()
35 self.fhand.close()
36 # Then may as well set up the "pointers" to the data (yes, I
know!)
37 self.get_fonttbl()
38 return
39
40 def __del__(self):
41 if options.debug:
42 print ("DEBUG: Destroying %s" % self.fname)
43
44 def get_fonttbl(self):
45 """Get the font definition from the font table creates a
fonttable instance"""
46 ftbl_id=r"\fonttbl"
47 if options.debug:
48 print ("DEBUG: Seeking to font table [%s] in %s " %
(ftbl_id,self.fname))
49 tbl_start=self.buff.find(ftbl_id)
50 if tbl_start == -1:
51 print ("File %s is not a properly formed rtf file" %
self.fname)
52 sys.exit(NOT_RTF)
53
54 len=find_len(self.buff[tbl_start:])
55
56 if options.debug:
57 print ("DEBUG: Found a font table of length %d at %d " %
(len,tbl_start))
58
59
60 # Make a new instance of fonttable.
61 self.font_table=fonttable(self.buff,tbl_start,len)
62
63 if options.debug:
64 print ("DEBUG: heres the font table:\n")
65 print self.font_table
66
67 # Hold the end position so when we start to look for font
references, we know where to start
68 self.ftable_end=tbl_start+len
69
70 self.font_table.write(options.opfhand)
71
72 pass
73
74 class fonttable:
75 def __init__(self,buff,start,len):
76 """Creates a new instance of a font table"""
77
78 if options.debug:
79 print ("DEBUG: Creating a new font table of %d bytes" %
len)
80
81 self.buff=buff[start-1:start+len] # start -1 to capture
the leading brace
82 self.start=start
83 self.len=len
84
85
86 def __del__(self):
87 if options.debug:
88 print ("DEBUG: Deleting font table")
89
90 def __repr__(self):
91 """Display the contents of a font table"""
92 return (self.buff)
93
94 def write(self,fhand):
95 """Write a nicely formatted font table to file handle fhand"""
96
97 fid_s=r'{\\f(\d+)' # re to match font identifier
98
99 fonts={}
100 fnum=0
101 i=0
102 for fontid in re.split(fid_s,self.buff):
103 if i % 2 == 1:
104 fnum=fontid
105 else:
106 fonts[fnum] = fontid
107 i+=1
108 for fontid in fonts.keys():
109 print ("\n%s : %s\n" % (fontid, fonts[fontid]))
110
111 pass
112
113 # End of class definitions
114
#######################################################################################################################################
115
116 def setup_args(arglist):
117 """Parse the command line and create the options list"""
118
119 global options # saves passing it around
120 usage="%%prog (-dv) -o[output_file]"
121 try:
122 parser=OptionParser(usage=usage,version="%%prog %s" %version)
123 parser.add_option("-o", "--outfile",dest="opfname",
help="Specifies output file", metavar="FILE")
124 parser.add_option("-d", "--debug",dest="debug",
help="Switches on debugging", action="store_true",default=0)
125 parser.add_option("-v", "--verbose",dest="verbose",
help="SWitches on verbose mode", action="store_true",default=0)
126 (options,args) = parser.parse_args(arglist)
127 except OptionError:
128 print ("Error in option handling - exiting")
129 sys.exit(INTERNAL_ERR)
130
131 try:
132 options.opfhand=open(options.opfname,"w")
133 except IOError, msg:
134 print ("Couldn't open output file %s : %s" % (options.opfname,
msg))
135 sys.exit(CREAT_FAIL)
136
137 if len(args) < 1 or options.opfname == None:
138 print parser.print_help()
139 sys.exit(BAD_ARGS)
140 return (args)
141
142
143 def main():
144 """build a font table from several rtf files"""
145
146 global progname
147 global version
148 progname=os.path.basename(sys.argv[0])
149 flist=setup_args(sys.argv[1:])
150
151 if len(flist) < 1:
152 print ("Need a filename!")
153 sys.exit(BAD_ARGS)
154
155 if options.verbose:
156 print ("%s version %s" % (progname,version))
157
158
159 rtflist={}
160 for fname in flist:
161 rtflist[fname]=rtffile(fname)
162 pass
163
164 def find_len(str):
165 """Find the length of the string up to a closing delimiter -
166 eg the length of a font definition"""
167
168 brace_ct=1 # We've skipped the opening brace
169 len=0
170
171 while brace_ct > 0:
172 try:
173 c=str[len]
174 except IndexError:
175 print ("Premature eof in %s possibly not a true rtf file?"
% str)
176 sys.exit(FILE_ERR)
177
178 if c == '{' :
179 brace_ct=brace_ct + 1
180 if c == '}' :
181 brace_ct=brace_ct - 1
182
183 len+=1
184 return (len)
185
186 if __name__ == '__main__': # ie we're _not_ a module
187 main()
188
--
Graham Nicholls
All round good guy.
More information about the Python-list
mailing list