1 # Part of Objavi2, which turns html manuals into books
3 # Copyright (C) 2009 Douglas Bagnall
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 2 of the License, or
8 # (at your option) any later version.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License along
16 # with this program; if not, write to the Free Software Foundation, Inc.,
17 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 General utility functions.
25 from subprocess
import Popen
, PIPE
27 #from objavi.fmbook import log
28 from objavi
import config
30 #general, non-cgi functions
32 """Try to redirect stderr to the log file. If it doesn't work,
33 leave stderr as it is."""
34 if config
.REDIRECT_LOG
:
35 logfile
= os
.path
.join(config
.LOGDIR
, 'objavi.log')
37 size
= os
.stat(logfile
).st_size
38 if size
> config
.LOG_ROTATE_SIZE
:
39 oldlog
= os
.path
.join(config
.LOGDIR
, time
.strftime('objavi-%Y-%m-%d+%H-%M-%S.log'))
40 f
= open(logfile
, 'a')
41 print >> f
, "CLOSING LOG at size %s, renaming to %s" % (size
, oldlog
)
43 os
.rename(logfile
, oldlog
)
45 log(e
) # goes to original stderr
47 f
= open(logfile
, 'a')
49 os
.dup2(f
.fileno(), sys
.stderr
.fileno())
50 # reassign the object as well as dup()ing, in case it closes down out of scope.
52 except (IOError, OSError), e
:
56 def log(*messages
, **kwargs
):
57 """Send the messages to the appropriate place (stderr, or syslog).
58 If a <debug> keyword is specified, the message is only printed if
59 its value is in the global DEBUG_MODES."""
60 if 'debug' not in kwargs
or config
.DEBUG_ALL
or kwargs
['debug'] in config
.DEBUG_MODES
:
63 print >> sys
.stderr
, m
65 print >> sys
.stderr
, repr(m
)
68 def log_types(*args
, **kwargs
):
69 """Log the type of the messages as well as their value (size constrained)."""
70 size
= kwargs
.get('size', 50)
79 log("%s: %s" % (type(a
), s
[:size
]))
81 def make_book_name(book
, server
, suffix
='.pdf', timestamp
=None):
82 lang
= guess_lang(server
, book
)
83 book
= ''.join(x
for x
in book
if x
.isalnum())
85 timestamp
= time
.strftime('%Y.%m.%d-%H.%M.%S')
86 return '%s-%s-%s%s' % (book
, lang
,
90 def guess_lang(server
, book
):
92 server
= config
.DEFAULT_SERVER
93 lang
= config
.SERVER_DEFAULTS
[server
].get('lang')
94 if lang
is None and '_' in book
:
95 lang
= book
[book
.rindex('_') + 1:]
98 def guess_text_dir(server
, book
):
100 dir = config
.SERVER_DEFAULTS
[server
]['dir']
103 if dir not in ('LTR', 'RTL'):
104 log("server %s, book %s: no specified dir (%s)" %(server
, book
, dir))
106 lang
= book
[book
.rindex('_') + 1:]
107 dir = config
.LANGUAGE_DIR
.get(lang
, 'LTR')
109 lang
= server
[:server
.index('.')]
110 dir = config
.LANGUAGE_DIR
.get(lang
, 'LTR')
113 log("server %s, book %s: found dir %s" %(server
, book
, dir))
118 p
= Popen(cmd
, stdout
=PIPE
, stderr
=PIPE
)
119 out
, err
= p
.communicate()
121 log("Failed on command: %r" % cmd
)
123 log("%s\n%s returned %s and produced\nstdout:%s\nstderr:%s" %
124 (' '.join(cmd
), cmd
[0], p
.poll(), out
, err
))
127 def shift_file(fn
, dir, backup
='~'):
128 """Shift a file and save backup (only works on same filesystem)"""
129 log("shifting file %r to %s" % (fn
, dir))
130 base
= os
.path
.basename(fn
)
131 dest
= os
.path
.join(dir, base
)
132 if backup
and os
.path
.exists(dest
):
133 os
.rename(dest
, dest
+ backup
)
134 shutil
.move(fn
, dest
)
137 class ObjaviError(Exception):
141 def decode_html_entities(text
):
142 for encoding
in ('ascii', 'utf-8', 'iso-8859-1'):
144 text
= text
.decode(encoding
)
146 except UnicodeDecodeError:
151 if entity
[:3] == "&#x":
152 return unichr(int(entity
[3:-1], 16))
153 elif entity
[:2] == "&#":
154 return unichr(int(entity
[2:-1]))
156 log("ignoring bad entity %s" % entity
)
158 return re
.sub("&#?[0-9a-fA-F]+;", fixup
, text
).encode('utf-8')