1 #!/usr/bin/env python 2 3 """ 4 Output context common functionality. 5 6 Copyright (C) 2018, 2023 Paul Boddie <paul@boddie.org.uk> 7 8 This program is free software; you can redistribute it and/or modify it under 9 the terms of the GNU General Public License as published by the Free Software 10 Foundation; either version 3 of the License, or (at your option) any later 11 version. 12 13 This program is distributed in the hope that it will be useful, but WITHOUT 14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 15 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 16 details. 17 18 You should have received a copy of the GNU General Public License along with 19 this program. If not, see <http://www.gnu.org/licenses/>. 20 """ 21 22 import codecs 23 24 class Output: 25 26 "A common output context abstraction." 27 28 default_encoding = "utf-8" 29 30 def __init__(self, metadata): 31 32 "Initialise the output context with the 'metadata'." 33 34 self.metadata = metadata 35 36 # Obtain essential metadata. 37 38 self.encoding = metadata.get("output_encoding", self.default_encoding) 39 self.reset() 40 41 def reset(self): 42 43 "Set up an output collector and output state." 44 45 self.output = [] 46 self.indent = "" 47 48 def encode(self, text): 49 50 "Encode 'text' using the configured encoding." 51 52 return encode(text, self.encoding) 53 54 def out(self, text): 55 56 "Add 'text' to the output collector." 57 58 self.output.append(text) 59 60 # Page characteristics. 61 62 def parent(self, pagename): 63 64 "Return the parent of 'pagename'." 65 66 return "/" in pagename and pagename.rsplit("/", 1)[0] or None 67 68 # Serialisation methods. 69 70 def to_string(self): 71 72 "Return the output as a single Unicode string." 73 74 s = u"".join(self.output) 75 self.reset() 76 return s 77 78 def can_write(self): 79 80 "Return whether this context supports page writing." 81 82 return False 83 84 def writefile(self, text, filename, encoding=None): 85 86 """ 87 Write 'text' to the file having the given 'filename'. If the 88 optional 'encoding' is specified, override the general encoding. 89 90 Subclasses need to override this method for it to have an effect. 91 """ 92 93 pass 94 95 def writepage(self, text, pagename, encoding=None): 96 97 """ 98 Write 'text' to the file having the given 'pagename' and optional 99 'encoding'. 100 """ 101 102 return self.writefile(text, self.to_filename(pagename), encoding) 103 104 # Output methods. 105 106 def writepath(self, text, filename, encoding=None): 107 108 """ 109 Write 'text' to the file having the given 'filename'. If the 110 optional 'encoding' is specified, override the general encoding. 111 """ 112 113 f = codecs.open(filename, "w", encoding=encoding or self.encoding) 114 try: 115 f.write(text) 116 finally: 117 f.close() 118 119 def encode(s, encoding): 120 121 "Encode 's' using 'encoding' if Unicode." 122 123 if isinstance(s, unicode): 124 return s.encode(encoding) 125 else: 126 return s 127 128 # vim: tabstop=4 expandtab shiftwidth=4