moinlight 0.4.5__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- moinformat/__init__.py +30 -0
- moinformat/errors.py +33 -0
- moinformat/imports.py +88 -0
- moinformat/input/__init__.py +39 -0
- moinformat/input/common.py +167 -0
- moinformat/input/directory.py +175 -0
- moinformat/input/dummy.py +64 -0
- moinformat/input/manifest.py +33 -0
- moinformat/input/moindirectory.py +165 -0
- moinformat/input/standalone.py +55 -0
- moinformat/io.py +43 -0
- moinformat/links/__init__.py +42 -0
- moinformat/links/common.py +118 -0
- moinformat/links/html.py +263 -0
- moinformat/links/manifest.py +33 -0
- moinformat/links/mediawiki.py +159 -0
- moinformat/macros/__init__.py +30 -0
- moinformat/macros/anchor.py +45 -0
- moinformat/macros/attachlist.py +88 -0
- moinformat/macros/br.py +41 -0
- moinformat/macros/common.py +59 -0
- moinformat/macros/footnote.py +195 -0
- moinformat/macros/include.py +163 -0
- moinformat/macros/mailto.py +70 -0
- moinformat/macros/manifest.py +33 -0
- moinformat/macros/navigation.py +71 -0
- moinformat/macros/pagelist.py +66 -0
- moinformat/macros/toc.py +274 -0
- moinformat/macros/verbatim.py +41 -0
- moinformat/metadata.py +263 -0
- moinformat/output/__init__.py +39 -0
- moinformat/output/common.py +128 -0
- moinformat/output/directory.py +230 -0
- moinformat/output/dummy.py +68 -0
- moinformat/output/manifest.py +33 -0
- moinformat/output/moindirectory.py +72 -0
- moinformat/output/standalone.py +75 -0
- moinformat/parsers/__init__.py +44 -0
- moinformat/parsers/common.py +558 -0
- moinformat/parsers/graphviz.py +97 -0
- moinformat/parsers/html.py +81 -0
- moinformat/parsers/manifest.py +33 -0
- moinformat/parsers/moin.py +1321 -0
- moinformat/parsers/pretty.py +79 -0
- moinformat/parsers/table.py +163 -0
- moinformat/resources/__init__.py +20 -0
- moinformat/resources/fixlinks.xsl +86 -0
- moinformat/resources/notugly.xsl +594 -0
- moinformat/serialisers/__init__.py +51 -0
- moinformat/serialisers/common.py +240 -0
- moinformat/serialisers/html/__init__.py +20 -0
- moinformat/serialisers/html/graphviz.py +191 -0
- moinformat/serialisers/html/html.py +72 -0
- moinformat/serialisers/html/moin.py +451 -0
- moinformat/serialisers/html/table.py +34 -0
- moinformat/serialisers/manifest.py +46 -0
- moinformat/serialisers/mediawiki/__init__.py +20 -0
- moinformat/serialisers/mediawiki/moin.py +513 -0
- moinformat/serialisers/mediawiki/table.py +33 -0
- moinformat/serialisers/moin/__init__.py +20 -0
- moinformat/serialisers/moin/graphviz.py +45 -0
- moinformat/serialisers/moin/moin.py +271 -0
- moinformat/serialisers/moin/table.py +64 -0
- moinformat/serialisers/pretty/__init__.py +20 -0
- moinformat/serialisers/pretty/common.py +36 -0
- moinformat/serialisers/pretty/graphviz.py +45 -0
- moinformat/serialisers/pretty/html.py +63 -0
- moinformat/serialisers/pretty/moin.py +184 -0
- moinformat/serialisers/pretty/pretty.py +36 -0
- moinformat/serialisers/pretty/table.py +33 -0
- moinformat/themes/__init__.py +39 -0
- moinformat/themes/common.py +119 -0
- moinformat/themes/debian/__init__.py +20 -0
- moinformat/themes/debian/css/all-admonitions.css +52 -0
- moinformat/themes/debian/css/all-footnote.css +4 -0
- moinformat/themes/debian/css/all-navigation.css +10 -0
- moinformat/themes/debian/css/all-smileys.css +105 -0
- moinformat/themes/debian/css/all-toc.css +10 -0
- moinformat/themes/debian/css/all.css +71 -0
- moinformat/themes/debian/css/print-revisions.css +3 -0
- moinformat/themes/debian/css/screen-revisions.css +33 -0
- moinformat/themes/debian/html.py +31 -0
- moinformat/themes/debian/revisions_template.html +9 -0
- moinformat/themes/debian/template.html +12 -0
- moinformat/themes/default/__init__.py +20 -0
- moinformat/themes/default/css/all-admonitions.css +34 -0
- moinformat/themes/default/css/all-footnote.css +4 -0
- moinformat/themes/default/css/all-navigation.css +10 -0
- moinformat/themes/default/css/all-smileys.css +105 -0
- moinformat/themes/default/css/all-toc.css +9 -0
- moinformat/themes/default/css/all.css +21 -0
- moinformat/themes/default/css/print-revisions.css +3 -0
- moinformat/themes/default/css/screen-revisions.css +33 -0
- moinformat/themes/default/html.py +31 -0
- moinformat/themes/default/revisions_template.html +9 -0
- moinformat/themes/default/template.html +12 -0
- moinformat/themes/html.py +189 -0
- moinformat/themes/manifest.py +41 -0
- moinformat/themes/mercurial/__init__.py +20 -0
- moinformat/themes/mercurial/css/all-admonitions.css +34 -0
- moinformat/themes/mercurial/css/all-footnote.css +4 -0
- moinformat/themes/mercurial/css/all-navigation.css +10 -0
- moinformat/themes/mercurial/css/all-smileys.css +105 -0
- moinformat/themes/mercurial/css/all-toc.css +9 -0
- moinformat/themes/mercurial/css/all.css +82 -0
- moinformat/themes/mercurial/css/print-revisions.css +3 -0
- moinformat/themes/mercurial/css/print.css +13 -0
- moinformat/themes/mercurial/css/screen-revisions.css +33 -0
- moinformat/themes/mercurial/css/screen.css +12 -0
- moinformat/themes/mercurial/html.py +31 -0
- moinformat/themes/mercurial/revisions_template.html +9 -0
- moinformat/themes/mercurial/template.html +12 -0
- moinformat/tree/__init__.py +20 -0
- moinformat/tree/graphviz.py +45 -0
- moinformat/tree/html.py +24 -0
- moinformat/tree/moin.py +1056 -0
- moinformat/tree/pretty.py +65 -0
- moinformat/tree/table.py +35 -0
- moinformat/utils/__init__.py +20 -0
- moinformat/utils/copying.py +61 -0
- moinformat/utils/directory.py +214 -0
- moinformat/utils/file.py +32 -0
- moinformat/utils/graphviz.py +342 -0
- moinformat/utils/htmlparse/__init__.py +22 -0
- moinformat/utils/htmlparse/lex.py +232 -0
- moinformat/utils/htmlparse/parse.py +110 -0
- moinformat/utils/htmlparse/token.py +158 -0
- moinformat/utils/htmlparse/tree.py +100 -0
- moinformat/utils/links.py +222 -0
- moinformat/utils/markup.py +60 -0
- moinformat/utils/moindirectory.py +268 -0
- moinformat/utils/patterns.py +158 -0
- moinlight-0.4.5.dist-info/METADATA +111 -0
- moinlight-0.4.5.dist-info/RECORD +136 -0
- moinlight-0.4.5.dist-info/WHEEL +4 -0
- moinlight-0.4.5.dist-info/entry_points.txt +2 -0
moinformat/__init__.py
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Moin wiki format tools.
|
|
3
|
+
|
|
4
|
+
Copyright (C) 2017, 2018, 2019 Paul Boddie <paul@boddie.org.uk>
|
|
5
|
+
|
|
6
|
+
This program is free software; you can redistribute it and/or modify it under
|
|
7
|
+
the terms of the GNU General Public License as published by the Free Software
|
|
8
|
+
Foundation; either version 3 of the License, or (at your option) any later
|
|
9
|
+
version.
|
|
10
|
+
|
|
11
|
+
This program is distributed in the hope that it will be useful, but WITHOUT
|
|
12
|
+
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
13
|
+
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
14
|
+
details.
|
|
15
|
+
|
|
16
|
+
You should have received a copy of the GNU General Public License along with
|
|
17
|
+
this program. If not, see <http://www.gnu.org/licenses/>.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
from moinformat.input import make_input
|
|
21
|
+
from moinformat.links import make_linker
|
|
22
|
+
from moinformat.metadata import Metadata
|
|
23
|
+
from moinformat.output import make_output
|
|
24
|
+
from moinformat.parsers import get_parser, make_parser, parse
|
|
25
|
+
from moinformat.serialisers import get_serialiser, make_serialiser, serialise
|
|
26
|
+
from moinformat.themes import make_theme
|
|
27
|
+
from moinformat.utils.copying import copy_attachments
|
|
28
|
+
import moinformat.errors as errors
|
|
29
|
+
|
|
30
|
+
# vim: tabstop=4 expandtab shiftwidth=4
|
moinformat/errors.py
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Moin wiki processing errors.
|
|
3
|
+
|
|
4
|
+
Copyright (C) 2019 Paul Boddie <paul@boddie.org.uk>
|
|
5
|
+
|
|
6
|
+
This program is free software; you can redistribute it and/or modify it under
|
|
7
|
+
the terms of the GNU General Public License as published by the Free Software
|
|
8
|
+
Foundation; either version 3 of the License, or (at your option) any later
|
|
9
|
+
version.
|
|
10
|
+
|
|
11
|
+
This program is distributed in the hope that it will be useful, but WITHOUT
|
|
12
|
+
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
13
|
+
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
14
|
+
details.
|
|
15
|
+
|
|
16
|
+
You should have received a copy of the GNU General Public License along with
|
|
17
|
+
this program. If not, see <http://www.gnu.org/licenses/>.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
class ProcessingError(Exception):
|
|
21
|
+
|
|
22
|
+
"A generic processing error."
|
|
23
|
+
|
|
24
|
+
def __init__(self, errors):
|
|
25
|
+
self.errors = errors
|
|
26
|
+
|
|
27
|
+
def __repr__(self):
|
|
28
|
+
return "%s(%r)" % (self.__class__.__name__, self.errors)
|
|
29
|
+
|
|
30
|
+
def __str__(self):
|
|
31
|
+
return "Error: %s\nMessage: %s\n" % (self.__class__.__name__, self.errors)
|
|
32
|
+
|
|
33
|
+
# vim: tabstop=4 expandtab shiftwidth=4
|
moinformat/imports.py
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Import utilities.
|
|
3
|
+
|
|
4
|
+
Copyright (C) 2017, 2018, 2021 Paul Boddie <paul@boddie.org.uk>
|
|
5
|
+
|
|
6
|
+
This program is free software; you can redistribute it and/or modify it under
|
|
7
|
+
the terms of the GNU General Public License as published by the Free Software
|
|
8
|
+
Foundation; either version 3 of the License, or (at your option) any later
|
|
9
|
+
version.
|
|
10
|
+
|
|
11
|
+
This program is distributed in the hope that it will be useful, but WITHOUT
|
|
12
|
+
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
13
|
+
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
14
|
+
details.
|
|
15
|
+
|
|
16
|
+
You should have received a copy of the GNU General Public License along with
|
|
17
|
+
this program. If not, see <http://www.gnu.org/licenses/>.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
from os.path import isdir, join, split, splitext
|
|
21
|
+
from os import listdir
|
|
22
|
+
from importlib import import_module
|
|
23
|
+
|
|
24
|
+
reserved = ["__init__", "common", "manifest"]
|
|
25
|
+
|
|
26
|
+
def get_extensions(dirname, modname, stores, reserved, prefix=None):
|
|
27
|
+
|
|
28
|
+
"Import extensions inside 'dirname'."
|
|
29
|
+
|
|
30
|
+
for filename in listdir(dirname):
|
|
31
|
+
pathname = join(dirname, filename)
|
|
32
|
+
|
|
33
|
+
# Descend into directories, prefixing the identified modules.
|
|
34
|
+
|
|
35
|
+
if isdir(pathname):
|
|
36
|
+
store_name = prefix and "%s.%s" % (prefix, modname) or filename
|
|
37
|
+
get_extensions(pathname, "%s.%s" % (modname, filename),
|
|
38
|
+
stores, reserved, store_name)
|
|
39
|
+
continue
|
|
40
|
+
|
|
41
|
+
# Identify modules and import them.
|
|
42
|
+
|
|
43
|
+
leafname, ext = splitext(filename)
|
|
44
|
+
|
|
45
|
+
if ext == ".py" and leafname not in reserved:
|
|
46
|
+
store_name = prefix and "%s.%s" % (prefix, leafname) or leafname
|
|
47
|
+
stores[store_name] = import_module("%s.%s" % (modname, leafname))
|
|
48
|
+
|
|
49
|
+
def get_mapping(modules, get_keys, get_value):
|
|
50
|
+
|
|
51
|
+
"""
|
|
52
|
+
Using the 'modules' mapping, employ 'get_keys' and 'get_value' to register
|
|
53
|
+
objects provided by the modules in a mapping.
|
|
54
|
+
"""
|
|
55
|
+
|
|
56
|
+
mapping = {}
|
|
57
|
+
|
|
58
|
+
# Use the callables to obtain the keys and values from modules.
|
|
59
|
+
|
|
60
|
+
for name, module in modules.items():
|
|
61
|
+
keys = get_keys(name, module)
|
|
62
|
+
if keys:
|
|
63
|
+
|
|
64
|
+
# Make a mapping for each key to the module concerned.
|
|
65
|
+
|
|
66
|
+
for key in keys:
|
|
67
|
+
mapping[key] = get_value(module)
|
|
68
|
+
|
|
69
|
+
return mapping
|
|
70
|
+
|
|
71
|
+
def get_modules(module_file, module_name):
|
|
72
|
+
|
|
73
|
+
"""
|
|
74
|
+
Obtain details of the indicated module's package using 'module_file',
|
|
75
|
+
corresponding to a __file__ attribute, and 'module_name', corresponding to
|
|
76
|
+
a __name__ attribute.
|
|
77
|
+
"""
|
|
78
|
+
|
|
79
|
+
dirname = split(module_file)[0]
|
|
80
|
+
package = module_name.rsplit(".", 1)[0]
|
|
81
|
+
|
|
82
|
+
# Define an attribute mapping names to modules.
|
|
83
|
+
|
|
84
|
+
modules = {}
|
|
85
|
+
get_extensions(dirname, package, modules, reserved)
|
|
86
|
+
return modules
|
|
87
|
+
|
|
88
|
+
# vim: tabstop=4 expandtab shiftwidth=4
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Input contexts.
|
|
3
|
+
|
|
4
|
+
Copyright (C) 2018 Paul Boddie <paul@boddie.org.uk>
|
|
5
|
+
|
|
6
|
+
This program is free software; you can redistribute it and/or modify it under
|
|
7
|
+
the terms of the GNU General Public License as published by the Free Software
|
|
8
|
+
Foundation; either version 3 of the License, or (at your option) any later
|
|
9
|
+
version.
|
|
10
|
+
|
|
11
|
+
This program is distributed in the hope that it will be useful, but WITHOUT
|
|
12
|
+
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
13
|
+
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
14
|
+
details.
|
|
15
|
+
|
|
16
|
+
You should have received a copy of the GNU General Public License along with
|
|
17
|
+
this program. If not, see <http://www.gnu.org/licenses/>.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
from moinformat.input.manifest import inputs
|
|
21
|
+
|
|
22
|
+
# Top-level functions.
|
|
23
|
+
|
|
24
|
+
def get_input(name):
|
|
25
|
+
|
|
26
|
+
"""
|
|
27
|
+
Return the input context class with the given 'name' or None if no such
|
|
28
|
+
class is found.
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
return inputs.get(name)
|
|
32
|
+
|
|
33
|
+
def make_input(metadata, name=None):
|
|
34
|
+
|
|
35
|
+
"Return an input context using 'metadata' and the optional 'name'."
|
|
36
|
+
|
|
37
|
+
return metadata.get_input(name)
|
|
38
|
+
|
|
39
|
+
# vim: tabstop=4 expandtab shiftwidth=4
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Input context common functionality.
|
|
3
|
+
|
|
4
|
+
Copyright (C) 2018, 2019, 2026 Paul Boddie <paul@boddie.org.uk>
|
|
5
|
+
|
|
6
|
+
This program is free software; you can redistribute it and/or modify it under
|
|
7
|
+
the terms of the GNU General Public License as published by the Free Software
|
|
8
|
+
Foundation; either version 3 of the License, or (at your option) any later
|
|
9
|
+
version.
|
|
10
|
+
|
|
11
|
+
This program is distributed in the hope that it will be useful, but WITHOUT
|
|
12
|
+
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
13
|
+
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
14
|
+
details.
|
|
15
|
+
|
|
16
|
+
You should have received a copy of the GNU General Public License along with
|
|
17
|
+
this program. If not, see <http://www.gnu.org/licenses/>.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
from moinformat.utils.file import readfile
|
|
21
|
+
from os.path import exists, split
|
|
22
|
+
import codecs
|
|
23
|
+
import re
|
|
24
|
+
|
|
25
|
+
class Input:
|
|
26
|
+
|
|
27
|
+
"A common input context abstraction."
|
|
28
|
+
|
|
29
|
+
default_encoding = "utf-8"
|
|
30
|
+
|
|
31
|
+
def __init__(self, metadata):
|
|
32
|
+
|
|
33
|
+
"Initialise the input context with the given 'metadata'."
|
|
34
|
+
|
|
35
|
+
self.metadata = metadata
|
|
36
|
+
|
|
37
|
+
# Obtain essential metadata.
|
|
38
|
+
|
|
39
|
+
self.encoding = metadata.get("input_encoding", self.default_encoding)
|
|
40
|
+
|
|
41
|
+
def all(self):
|
|
42
|
+
|
|
43
|
+
"Return all pages in the context."
|
|
44
|
+
|
|
45
|
+
return []
|
|
46
|
+
|
|
47
|
+
def all_attachments(self):
|
|
48
|
+
|
|
49
|
+
"Return all attachment filenames in the context."
|
|
50
|
+
|
|
51
|
+
return []
|
|
52
|
+
|
|
53
|
+
def get_attachments(self, pagename):
|
|
54
|
+
|
|
55
|
+
"Return all attachment filenames for the given 'pagename'."
|
|
56
|
+
|
|
57
|
+
return []
|
|
58
|
+
|
|
59
|
+
def current_revision(self, pagename):
|
|
60
|
+
|
|
61
|
+
"Return the current revision for the given 'pagename'."
|
|
62
|
+
|
|
63
|
+
return None
|
|
64
|
+
|
|
65
|
+
def find(self, pattern):
|
|
66
|
+
|
|
67
|
+
"Return all pagenames matching the given regular expression 'pattern'."
|
|
68
|
+
|
|
69
|
+
found = []
|
|
70
|
+
|
|
71
|
+
p = re.compile(pattern)
|
|
72
|
+
|
|
73
|
+
for pagename in self.all():
|
|
74
|
+
if p.match(pagename):
|
|
75
|
+
found.append(pagename)
|
|
76
|
+
|
|
77
|
+
return found
|
|
78
|
+
|
|
79
|
+
def revisions(self, pagename):
|
|
80
|
+
|
|
81
|
+
"Return all revisions for the given 'pagename'."
|
|
82
|
+
|
|
83
|
+
return [None]
|
|
84
|
+
|
|
85
|
+
def provides_history(self):
|
|
86
|
+
|
|
87
|
+
"Return whether the context provides revision history."
|
|
88
|
+
|
|
89
|
+
return False
|
|
90
|
+
|
|
91
|
+
# Page characteristics.
|
|
92
|
+
|
|
93
|
+
def parent(self, pagename):
|
|
94
|
+
|
|
95
|
+
"Return the parent of 'pagename'."
|
|
96
|
+
|
|
97
|
+
return "/" in pagename and pagename.rsplit("/", 1)[0] or None
|
|
98
|
+
|
|
99
|
+
def subpages(self, pagename):
|
|
100
|
+
|
|
101
|
+
"Return the subpages of 'pagename'."
|
|
102
|
+
|
|
103
|
+
return []
|
|
104
|
+
|
|
105
|
+
# Page access methods.
|
|
106
|
+
|
|
107
|
+
def exists(self, pagename):
|
|
108
|
+
|
|
109
|
+
"Return whether 'pagename' exists."
|
|
110
|
+
|
|
111
|
+
return exists(self.to_filename(pagename))
|
|
112
|
+
|
|
113
|
+
def revision_exists(self, pagename, revision=None):
|
|
114
|
+
|
|
115
|
+
"""
|
|
116
|
+
Return whether 'pagename' exists for 'revision', if specified, or the
|
|
117
|
+
recorded current revision otherwise.
|
|
118
|
+
"""
|
|
119
|
+
|
|
120
|
+
return self.exists(pagename)
|
|
121
|
+
|
|
122
|
+
def readfile(self, filename, encoding=None):
|
|
123
|
+
|
|
124
|
+
"""
|
|
125
|
+
Return the contents of the file having the given 'filename' and optional
|
|
126
|
+
'encoding'. This implementation treats 'filename' as a path.
|
|
127
|
+
"""
|
|
128
|
+
|
|
129
|
+
return self.readpath(filename, encoding)
|
|
130
|
+
|
|
131
|
+
def read_revision(self, pagename, revision=None, encoding=None):
|
|
132
|
+
|
|
133
|
+
"""
|
|
134
|
+
Return the contents of the file having the given 'pagename', 'revision',
|
|
135
|
+
and optional 'encoding'.
|
|
136
|
+
"""
|
|
137
|
+
|
|
138
|
+
return self.readfile(self.to_filename(pagename), encoding)
|
|
139
|
+
|
|
140
|
+
# Input methods.
|
|
141
|
+
|
|
142
|
+
def readpath(self, filename, encoding=None):
|
|
143
|
+
|
|
144
|
+
"""
|
|
145
|
+
Return the contents of the file having the given 'filename'. If the
|
|
146
|
+
optional 'encoding' is specified, override the general encoding.
|
|
147
|
+
"""
|
|
148
|
+
|
|
149
|
+
return readfile(filename, encoding or self.encoding)
|
|
150
|
+
|
|
151
|
+
# Name translation methods.
|
|
152
|
+
|
|
153
|
+
def to_filename(self, pagename):
|
|
154
|
+
|
|
155
|
+
"Return the filename corresponding to 'pagename'."
|
|
156
|
+
|
|
157
|
+
return pagename
|
|
158
|
+
|
|
159
|
+
def to_pagename(self, filename):
|
|
160
|
+
|
|
161
|
+
"Return the pagename corresponding to 'filename'."
|
|
162
|
+
|
|
163
|
+
# Take the leafname as the pagename from an arbitrary filename.
|
|
164
|
+
|
|
165
|
+
return split(filename)[-1]
|
|
166
|
+
|
|
167
|
+
# vim: tabstop=4 expandtab shiftwidth=4
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Directory input context.
|
|
3
|
+
|
|
4
|
+
Copyright (C) 2018-2019, 2026 Paul Boddie <paul@boddie.org.uk>
|
|
5
|
+
|
|
6
|
+
This program is free software; you can redistribute it and/or modify it under
|
|
7
|
+
the terms of the GNU General Public License as published by the Free Software
|
|
8
|
+
Foundation; either version 3 of the License, or (at your option) any later
|
|
9
|
+
version.
|
|
10
|
+
|
|
11
|
+
This program is distributed in the hope that it will be useful, but WITHOUT
|
|
12
|
+
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
13
|
+
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
14
|
+
details.
|
|
15
|
+
|
|
16
|
+
You should have received a copy of the GNU General Public License along with
|
|
17
|
+
this program. If not, see <http://www.gnu.org/licenses/>.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
from moinformat.input.common import Input
|
|
21
|
+
from moinformat.utils.directory import Directory
|
|
22
|
+
from os.path import join, sep
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class CommonDirectoryInput(Input):
|
|
26
|
+
|
|
27
|
+
"Common directory input functionality."
|
|
28
|
+
|
|
29
|
+
def __init__(self, metadata):
|
|
30
|
+
|
|
31
|
+
"Initialise the context with the given 'metadata'."
|
|
32
|
+
|
|
33
|
+
if "input_filename" not in metadata:
|
|
34
|
+
raise ValueError(metadata)
|
|
35
|
+
|
|
36
|
+
Input.__init__(self, metadata)
|
|
37
|
+
self.dir = Directory(metadata.get("input_filename"))
|
|
38
|
+
|
|
39
|
+
# Support attachments directories.
|
|
40
|
+
|
|
41
|
+
self.attachments_dir = metadata.get("attachments")
|
|
42
|
+
|
|
43
|
+
# Support a common attachments directory.
|
|
44
|
+
|
|
45
|
+
self.common_attachments = metadata.get("common_attachments")
|
|
46
|
+
|
|
47
|
+
def _get_attachments_dir(self, pagename):
|
|
48
|
+
|
|
49
|
+
"Return the attachments directory for 'pagename'."
|
|
50
|
+
|
|
51
|
+
if self.common_attachments:
|
|
52
|
+
return join(self.dir.filename, self.attachments_dir)
|
|
53
|
+
else:
|
|
54
|
+
return join(self.dir.filename, self.attachments_dir, pagename)
|
|
55
|
+
|
|
56
|
+
def all_attachments(self):
|
|
57
|
+
|
|
58
|
+
"Return all attachment filenames in the context."
|
|
59
|
+
|
|
60
|
+
return self.dir.select_files(join(self.attachments_dir, "*"), True)
|
|
61
|
+
|
|
62
|
+
def get_attachments(self, pagename):
|
|
63
|
+
|
|
64
|
+
"""
|
|
65
|
+
Return all attachment filenames for the given 'pagename'. Each filename
|
|
66
|
+
is relative to the appropriate attachment directory.
|
|
67
|
+
"""
|
|
68
|
+
|
|
69
|
+
return Directory(self._get_attachments_dir(pagename)).select_files("*")
|
|
70
|
+
|
|
71
|
+
# Page characteristics.
|
|
72
|
+
|
|
73
|
+
# def subpages(self, pagename): # There us no subpage_filenames method in this class
|
|
74
|
+
# "Return the subpages of 'pagename'."
|
|
75
|
+
# return list(map(self.to_pagename, self.subpage_filenames(pagename)))
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
# Page access methods.
|
|
79
|
+
|
|
80
|
+
def exists(self, pagename):
|
|
81
|
+
|
|
82
|
+
"Return whether 'pagename' exists."
|
|
83
|
+
|
|
84
|
+
return self.dir.exists(self.to_filename(pagename))
|
|
85
|
+
|
|
86
|
+
def readfile(self, filename, encoding=None):
|
|
87
|
+
|
|
88
|
+
"""
|
|
89
|
+
Return the contents of the file having the given 'filename' and optional
|
|
90
|
+
'encoding'.
|
|
91
|
+
"""
|
|
92
|
+
|
|
93
|
+
return self.readpath(self.dir.get_filename(filename), encoding)
|
|
94
|
+
|
|
95
|
+
# Convenience methods.
|
|
96
|
+
|
|
97
|
+
def get_attachment_filename(self, pagename, filename):
|
|
98
|
+
|
|
99
|
+
"""
|
|
100
|
+
Return the full path of an attachment file for the given 'pagename'
|
|
101
|
+
having the given 'filename'.
|
|
102
|
+
"""
|
|
103
|
+
|
|
104
|
+
if not pagename:
|
|
105
|
+
return None
|
|
106
|
+
|
|
107
|
+
return self.dir.get_filename(join(self._get_attachments_dir(pagename),
|
|
108
|
+
filename))
|
|
109
|
+
|
|
110
|
+
class DirectoryInput(CommonDirectoryInput):
|
|
111
|
+
|
|
112
|
+
"A directory input context."
|
|
113
|
+
|
|
114
|
+
name = "directory"
|
|
115
|
+
|
|
116
|
+
def __init__(self, metadata):
|
|
117
|
+
|
|
118
|
+
"Initialise the context with the given 'metadata'."
|
|
119
|
+
|
|
120
|
+
CommonDirectoryInput.__init__(self, metadata)
|
|
121
|
+
|
|
122
|
+
# Support an encoding of the level separator for the filesystem.
|
|
123
|
+
# Where it is the same as the directory separator, documents are stored
|
|
124
|
+
# using nested directories, not as a flat list.
|
|
125
|
+
|
|
126
|
+
self.level_sep = metadata.get("input_separator", sep)
|
|
127
|
+
|
|
128
|
+
# Search recursively in nested directories for pages.
|
|
129
|
+
|
|
130
|
+
self.nested = self.level_sep == sep
|
|
131
|
+
|
|
132
|
+
def all(self):
|
|
133
|
+
|
|
134
|
+
"Return all pages in the context."
|
|
135
|
+
|
|
136
|
+
# Ignore dotfiles.
|
|
137
|
+
|
|
138
|
+
return list(map(self.to_pagename, self.dir.select_files("[!.]*", self.nested)))
|
|
139
|
+
|
|
140
|
+
# Page characteristics.
|
|
141
|
+
|
|
142
|
+
def subpage_filenames(self, pagename):
|
|
143
|
+
|
|
144
|
+
"Return the subpage filenames of 'pagename'."
|
|
145
|
+
|
|
146
|
+
pattern = self.to_filename("%s%s*" % (pagename, self.level_sep))
|
|
147
|
+
return self.dir.select_files(pattern, self.nested)
|
|
148
|
+
|
|
149
|
+
def subpages(self, pagename):
|
|
150
|
+
"Return the subpages of 'pagename'."
|
|
151
|
+
return list(map(self.to_pagename, self.subpage_filenames(pagename)))
|
|
152
|
+
|
|
153
|
+
# NOTE: Translation methods should encode filenames appropriately.
|
|
154
|
+
|
|
155
|
+
def to_filename(self, pagename):
|
|
156
|
+
|
|
157
|
+
"Return the filename corresponding to 'pagename'."
|
|
158
|
+
|
|
159
|
+
if sep == self.level_sep:
|
|
160
|
+
return pagename
|
|
161
|
+
else:
|
|
162
|
+
return self.level_sep.join(pagename.split("/"))
|
|
163
|
+
|
|
164
|
+
def to_pagename(self, filename):
|
|
165
|
+
|
|
166
|
+
"Return the pagename corresponding to 'filename'."
|
|
167
|
+
|
|
168
|
+
if sep == self.level_sep:
|
|
169
|
+
return filename
|
|
170
|
+
else:
|
|
171
|
+
return "/".join(filename.split(self.level_sep))
|
|
172
|
+
|
|
173
|
+
input = DirectoryInput
|
|
174
|
+
|
|
175
|
+
# vim: tabstop=4 expandtab shiftwidth=4
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"""Dummy input context."""
|
|
2
|
+
#
|
|
3
|
+
# Copyright (C) 2026 Morten Kjeldgaard <mok0@mailbox.org>
|
|
4
|
+
#
|
|
5
|
+
# This program is free software; you can redistribute it and/or modify it under
|
|
6
|
+
# the terms of the GNU General Public License as published by the Free Software
|
|
7
|
+
# Foundation; either version 3 of the License, or (at your option) any later
|
|
8
|
+
# version.
|
|
9
|
+
#
|
|
10
|
+
# This program is distributed in the hope that it will be useful, but WITHOUT
|
|
11
|
+
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
12
|
+
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
13
|
+
# details.
|
|
14
|
+
|
|
15
|
+
# You should have received a copy of the GNU General Public License along with
|
|
16
|
+
# this program. If not, see <http://www.gnu.org/licenses/>.
|
|
17
|
+
|
|
18
|
+
from moinformat.input.common import Input
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class DummyInput(Input):
|
|
22
|
+
|
|
23
|
+
"A dummy output context meant for testing."
|
|
24
|
+
|
|
25
|
+
name = "dummy"
|
|
26
|
+
|
|
27
|
+
def read(self, stream=None):
|
|
28
|
+
"""Read from 'stream', or standard input if not specified,
|
|
29
|
+
returning a character string. This is a dummy reader, and it
|
|
30
|
+
accepts a stream, so in testing we can pass it a StringIO
|
|
31
|
+
object."""
|
|
32
|
+
|
|
33
|
+
if not stream:
|
|
34
|
+
return ""
|
|
35
|
+
|
|
36
|
+
return stream.read()
|
|
37
|
+
|
|
38
|
+
# Convenience methods.
|
|
39
|
+
|
|
40
|
+
def get_attachment_filename(self, _pagename, _filename):
|
|
41
|
+
"""Prevent independent output by returning a filename of None
|
|
42
|
+
corresponding to the given 'pagename' and any specified
|
|
43
|
+
'filename'."""
|
|
44
|
+
|
|
45
|
+
return None
|
|
46
|
+
|
|
47
|
+
def exists(self, pagename: str):
|
|
48
|
+
"""Return whether 'pagename´ exists, but this is a dummy
|
|
49
|
+
reader so yes it does."""
|
|
50
|
+
|
|
51
|
+
return True
|
|
52
|
+
|
|
53
|
+
def readpath(self, filename: str, encoding=None):
|
|
54
|
+
"""This function is intended to return the contents of the
|
|
55
|
+
file having the given 'filename', but since this is a dummy
|
|
56
|
+
input meant for testing, we merely return the string passed in
|
|
57
|
+
`filename'."""
|
|
58
|
+
|
|
59
|
+
return filename
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
input = DummyInput
|
|
63
|
+
|
|
64
|
+
# vim: tabstop=4 expandtab shiftwidth=4
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Input context implementation manifest.
|
|
3
|
+
|
|
4
|
+
Copyright (C) 2017, 2018, 2021 Paul Boddie <paul@boddie.org.uk>
|
|
5
|
+
|
|
6
|
+
This program is free software; you can redistribute it and/or modify it under
|
|
7
|
+
the terms of the GNU General Public License as published by the Free Software
|
|
8
|
+
Foundation; either version 3 of the License, or (at your option) any later
|
|
9
|
+
version.
|
|
10
|
+
|
|
11
|
+
This program is distributed in the hope that it will be useful, but WITHOUT
|
|
12
|
+
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
13
|
+
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
14
|
+
details.
|
|
15
|
+
|
|
16
|
+
You should have received a copy of the GNU General Public License along with
|
|
17
|
+
this program. If not, see <http://www.gnu.org/licenses/>.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
from moinformat.imports import get_extensions, get_mapping, get_modules
|
|
21
|
+
|
|
22
|
+
# Define an attribute mapping names to modules.
|
|
23
|
+
|
|
24
|
+
modules = get_modules(__file__, __name__)
|
|
25
|
+
|
|
26
|
+
# Obtain all input contexts.
|
|
27
|
+
|
|
28
|
+
# Use names declared in each class to register the contexts:
|
|
29
|
+
# input.name -> input
|
|
30
|
+
|
|
31
|
+
inputs = get_mapping(modules, lambda n, m: [m.input.name], lambda m: m.input)
|
|
32
|
+
|
|
33
|
+
# vim: tabstop=4 expandtab shiftwidth=4
|