1 #!/usr/bin/env python 2 3 """ 4 Directory input context. 5 6 Copyright (C) 2018, 2019 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 from moinformat.input.common import Input 23 from moinformat.utils.directory import Directory 24 from os.path import join, sep 25 26 class DirectoryInput(Input): 27 28 "A directory input context." 29 30 name = "directory" 31 32 def __init__(self, metadata): 33 34 "Initialise the context with the given 'metadata'." 35 36 if not metadata.has_key("input_filename"): 37 raise ValueError, metadata 38 39 Input.__init__(self, metadata) 40 self.dir = Directory(metadata.get("input_filename")) 41 42 # Support an encoding of the level separator for the filesystem. 43 # Where it is the same as the directory separator, documents are stored 44 # using nested directories, not as a flat list. 45 46 self.level_sep = metadata.get("input_separator", sep) 47 48 # Search recursively in nested directories for pages. 49 50 self.nested = self.level_sep == sep 51 52 # Support attachments directories. 53 54 self.attachments_dir = metadata.get("attachments") 55 56 # Support a common attachments directory. 57 58 self.common_attachments = metadata.get("common_attachments") 59 60 def _get_attachments_dir(self, pagename): 61 62 "Return the attachments directory for 'pagename'." 63 64 if self.common_attachments: 65 return join(self.dir.filename, self.attachments_dir) 66 else: 67 return join(self.dir.filename, self.attachments_dir, pagename) 68 69 def all(self): 70 71 "Return all pages in the context." 72 73 # Ignore dotfiles. 74 75 return map(self.to_pagename, self.dir.select_files("[!.]*", self.nested)) 76 77 def all_attachments(self): 78 79 "Return all attachment filenames in the context." 80 81 return self.dir.select_files(join(self.attachments_dir, "*"), True) 82 83 def get_attachments(self, pagename): 84 85 """ 86 Return all attachment filenames for the given 'pagename'. Each filename 87 is relative to the appropriate attachment directory. 88 """ 89 90 return Directory(self._get_attachments_dir(pagename)).select_files("*") 91 92 # Page characteristics. 93 94 def subpage_filenames(self, pagename): 95 96 "Return the subpage filenames of 'pagename'." 97 98 pattern = self.to_filename("%s%s*" % (pagename, self.level_sep)) 99 return self.dir.select_files(pattern, self.nested) 100 101 def subpages(self, pagename): 102 103 "Return the subpages of 'pagename'." 104 105 return map(self.to_pagename, self.subpage_filenames(pagename)) 106 107 # Page access methods. 108 109 def readfile(self, filename, encoding=None): 110 111 """ 112 Return the contents of the file having the given 'filename' and optional 113 'encoding'. 114 """ 115 116 return self.readpath(self.dir.get_filename(filename), encoding) 117 118 # Convenience methods. 119 120 def get_attachment_filename(self, pagename, filename): 121 122 """ 123 Return the full path of an attachment file for the given 'pagename' 124 having the given 'filename'. 125 """ 126 127 if not pagename: 128 return None 129 130 return self.dir.get_filename(join(self._get_attachments_dir(pagename), 131 filename)) 132 133 # NOTE: Translation methods should encode filenames appropriately. 134 135 def to_filename(self, pagename): 136 137 "Return the filename corresponding to 'pagename'." 138 139 if sep == self.level_sep: 140 return pagename 141 else: 142 return self.level_sep.join(pagename.split("/")) 143 144 def to_pagename(self, filename): 145 146 "Return the pagename corresponding to 'filename'." 147 148 if sep == self.level_sep: 149 return filename 150 else: 151 return "/".join(filename.split(self.level_sep)) 152 153 input = DirectoryInput 154 155 # vim: tabstop=4 expandtab shiftwidth=4