Have an action for exporting a page
We had a conversation in chat. I suggested to have an action that would enable to download a page wihich contains only gettext ("#format gettext") as a PO file. We then tried to make this more general
discussion
dreimark: I do have a PackagePage patch written for attachments but it needs some further work to embed it to the action too see FeatureRequests/PackagesNeedsAddAttachmentAndMore ... I do believe that could be done with some parser code... I have done something similiar with pdf code in php some time ago ... with some of the frame parser code it could be rendered too but I would be prefer at first a very smart solution and to extend it later. Because the frame parser needs some fixes too.
We will need a parser and an action macro (invisible for the menu). all content included by a parser could be downloaded as file by an action. -- ReimarBauer 2007-01-01 20:44:11
first version
Here is a first implementation for exporting content for the 1.6 dev code. -- ReimarBauer 2007-01-02 19:21:51
Example
{ { {#!ExportFile = some wiki mark up = * A * B } } } { { {#!ExportFile file=example.txt #format plain AAEE BBAA CCAA DDDE FFAE BBCD } } } { { {#!ExportFile file=example.py #format python def format(self, formatter): self.pagename = formatter.page.page_name self.quoted_pagename = wikiutil.quoteWikinameURL(self.pagename) attachment_path = AttachFile.getAttachDir(self.request, self.pagename, create=1) } } }
The results files are
We do need an action macro exportfile.py in the action directory and a parser text_x_exportfile.py in the parsers directory. A patch of wikutil makes sense because a dict of process instructions and getting the Parser instance would be needed in other routines too.
1 # HG changeset patch
2 # User ReimarBauer <R.Bauer@fz-juelich.de>
3 # Date 1167887793 -3600
4 # Node ID adffe242a432ccb4219950cfd1c05abea0285733
5 # Parent 3c6f59cafbbe442f90171a8b0680be67eb320a67
6 added get_process_instruction and get_parser
7
8 diff -r 3c6f59cafbbe -r adffe242a432 MoinMoin/wikiutil.py
9 --- a/MoinMoin/wikiutil.py Thu Dec 21 03:39:57 2006 +0100
10 +++ b/MoinMoin/wikiutil.py Thu Jan 04 06:16:33 2007 +0100
11 @@ -1643,3 +1643,36 @@ def checkTicket(request, ticket):
12 ourticket = createTicket(request, timestamp_str)
13 return ticket == ourticket
14
15 +
16 +def get_process_instruction(text):
17 + """Creates dict of process instructions"""
18 + lines = text.split('\n')
19 + dict = {}
20 + dict["processing_instructions"] = False
21 + for line in lines:
22 + for pi in ("#format", "#refresh", "#redirect", "#deprecated",
23 + "#pragma", "#form", "#acl", "#language"):
24 + if line.lower().startswith(pi):
25 + value = (line.split(pi))[1]
26 + dict[str(pi[1:].lower())] = value.strip()
27 + dict["processing_instructions"] = True
28 + break
29 + return dict
30 +
31 +
32 +def get_parser(request, text):
33 + """gets the parser used from text"""
34 + pi = get_process_instruction(text)
35 + pi_format = request.cfg.default_markup or "wiki"
36 +
37 + # check for XML content
38 + if text and text[:5] == '<?xml':
39 + pi_format = "xslt"
40 +
41 + # check processing instructions
42 + if pi.has_key('format'):
43 + pi_format = (pi["format"])
44 + pi_format = pi_format.lower()
45 +
46 + Parser = searchAndImportPlugin(request.cfg, "parser", pi_format)
47 + return Parser
48 \ No newline at end of file
1 # -*- coding: iso-8859-1 -*-
2 """
3 MoinMoin - exportfile Action macro
4
5 PURPOSE::
6 This action macro is used from text_x_exportfile to export to a plain/text file
7
8 CALLING SEQUENCE::
9 called by text_x_exportfile POST Method
10
11 MODIFICATION HISTORY::
12 Version 1.6.0-1
13 @copyright: 2007 by Reimar Bauer (R.Bauer@fz-juelich.de)
14 @license: GNU GPL, see COPYING for details.
15 """
16 import os
17 from MoinMoin import wikiutil
18 from MoinMoin.action import AttachFile
19 from MoinMoin.util import timefuncs
20
21 def execute(pagename, request):
22 ticket = request.form.get('ticket', [''])[0]
23 if wikiutil.checkTicket(request, ticket):
24
25 attachment_path = AttachFile.getAttachDir(request, pagename)
26 timestamp = timefuncs.formathttpdate(int(os.path.getmtime(attachment_path)))
27 file = request.form.get('file', [''])[0]
28 raw = request.form.get('raw', [''])[0]
29 content_type = request.form.get('content-type', [''])[0]
30
31 if content_type == 'text/plain':
32 request.emit_http_headers([
33 'Content-Type: %s' % content_type,
34 'Last-Modified: %s' % timestamp,
35 'Content-Length: %d' % len(raw),
36 'Content-Disposition: %s; filename="%s"' % ('attachment', file),
37 ])
38 request.write(raw)
39 return ()
40 else:
41 return ()
42 else:
43 return ()
1 # -*- coding: iso-8859-1 -*-
2 """
3 MoinMoin - ExportFile parser
4
5 PURPOSE:
6 This parser is used to download some content of a wiki page to a file. It needs the action exportfile.py
7
8 CALLING SEQUENCE:
9 {{{
10 #!ExportFile [file=file]
11 = Example =
12 }}}
13
14 OPTIONAL KEYWORD PARAMETERS:
15 file: file name to save to
16
17 EXAMPLE:
18 {{{#!ExportFile
19 = some wiki mark up =
20 * A
21 * B
22 }}}
23
24
25 {{{#!ExportFile file=example.txt
26 #format plain
27 AAEE BBAA CCAA
28 DDDE FFAE BBCD
29 }}}
30
31
32 {{{#!ExportFile file=example.py
33 #format python
34 def format(self, formatter):
35 self.pagename = formatter.page.page_name
36 self.quoted_pagename = wikiutil.quoteWikinameURL(self.pagename)
37 attachment_path = AttachFile.getAttachDir(self.request, self.pagename, create=1)
38 }}}
39
40
41 PROCEDURE:
42 ABOUT:
43 This parser is the result of a discussion with ThiloPfennig about saving conten of a page to a file
44 while editing functionality is done from the wiki. see FeatureRequests/ExportFileAction
45
46 MODIFICATION HISTORY:
47 Version 1.6.0-1
48 1.6.0-2 some code cleanup
49 1.6.0-3 some more code moved to wikiutil
50 @copyright: 2007 by Reimar Bauer (R.Bauer@fz-juelich.de)
51 @license: GNU GPL, see COPYING for details.
52
53 """
54 Dependencies = ['time'] # do not cache
55 import StringIO, codecs
56 from MoinMoin.action import AttachFile
57 from MoinMoin import wikiutil
58 from MoinMoin.parser import text_moin_wiki
59
60 class Parser:
61 extensions = '*'
62 def __init__(self, raw, request, **kw):
63 self.file = 'exportfile.txt'
64 test = kw.get('format_args', '')
65 if test:
66 for arg in kw.get('format_args', '').split(','):
67 if arg.find('=') > -1:
68 key, value = arg.split('=')
69 setattr(self, key, wikiutil.escape(value.strip(), quote=1))
70 self.raw = raw
71 self.request = request
72 self.form = request.form
73 self._ = request.getText
74
75
76 def format(self, formatter):
77 self.pagename = formatter.page.page_name
78 self.quoted_pagename = wikiutil.quoteWikinameURL(self.pagename)
79 attachment_path = AttachFile.getAttachDir(self.request, self.pagename, create=1)
80
81 Parser = wikiutil.get_parser(self.request, self.raw)
82
83 lines = self.raw.split('\n')
84 raw = []
85 for line in lines:
86 is_good = True
87 for pi in ("#format", "#refresh", "#redirect", "#deprecated",
88 "#pragma", "#form", "#acl", "#language"):
89 if line.lower().startswith(pi):
90 is_good = False
91 break
92 if is_good:
93 raw.append(line)
94 raw = '\n'.join(raw)
95
96 out = StringIO.StringIO()
97 self.request.redirect(out)
98 wikiizer = Parser(raw, self.request)
99 wikiizer.format(formatter)
100 result = out.getvalue()
101 self.request.redirect()
102 del out
103
104 self.request.write(result)
105
106 form = """
107 <form action="%(baseurl)s/%(pagename)s" method="POST" enctype="multipart/form-data">
108 <input type="hidden" name="action" value="exportfile">
109 <input type="hidden" name="ticket" value="%(ticket)s">
110 <input type="hidden" name="file" value="%(file)s">
111 <input type="hidden" name="raw" value="%(raw)s">
112 <input type="hidden" name="content-type" value="%(content_type)s">
113 <input type="submit" value="download %(file)s">
114 </form>""" % {
115 "baseurl": self.request.getBaseURL(),
116 "ticket": wikiutil.createTicket(self.request),
117 "pagename": self.pagename,
118 "file": self.file,
119 "content_type": "text/plain",
120 "raw": raw,
121 }
122 self.request.write(form)
comments wanted
If something like this could be implemented may be we could use it for all codings on the Markets. Because
- We have then version control from the wiki.
- Someone else could easier contribute.
- We get easy a downloadable version
-- ReimarBauer 2007-01-02 19:31:43
ThomasWaldmann proposed to add a ContentSaving Action too.
wikiutil patch:
- get_processING_instructionS()
- can be optimized:
- first check for line[0] == '#'
- then check for line[1:] starting with pi (without #)
- don't use "dict" as attribute name, this overloads dict()
- if you iterate over lowercase stuff only, no need to lower() them again
- break!?
- maybe we rather want value = rest of line
and check if that all is done if #format ExportFile works too
For this FeatureRequest and some other routines I would like to add these functions to wikiutil. -- ReimarBauer 2007-01-14 10:07:51
1 def getProcessingInstructions(text):
2 """Creates dict of processing instructions"""
3 lines = text.split('\n')
4 kw = {}
5 kw["processing_instructions"] = False
6 for line in lines:
7 if line.startswith('#'):
8 for pi in ("format", "refresh", "redirect", "deprecated", "pragma", "form", "acl", "language"):
9 if line[1:].lower().startswith(pi):
10 kw[str(pi)] = ((line.split(pi))[1]).strip()
11 kw["processing_instructions"] = True
12 break
13 return kw
14
15 def getParser(request, text):
16 """gets the parser used from text"""
17 pi = getProcessingInstructions(text)
18 pi_format = request.cfg.default_markup or "wiki"
19
20 # check for XML content
21 if text and text[:5] == '<?xml':
22 pi_format = "xslt"
23
24 # check processing instructions
25 if pi.has_key('format'):
26 pi_format = (pi["format"]).lower()
27
28 Parser = searchAndImportPlugin(request.cfg, "parser", pi_format)
29 return Parser
Save action
1 # -*- coding: iso-8859-1 -*-
2 """
3 MoinMoin - Action macro for saving content
4
5 MODIFICATION HISTORY:
6 @copyright: 2007 by Reimar Bauer
7 @license: GNU GPL, see COPYING for details.
8 """
9 import os
10 from MoinMoin.Page import Page
11 from MoinMoin.action import AttachFile
12 from MoinMoin.util import timefuncs
13
14 def execute(pagename, request):
15 _ = request.getText
16 thispage = Page(request, pagename)
17 msg = _("You are not allowed to view this page.")
18 if request.user.may.read(pagename):
19 attachment_path = AttachFile.getAttachDir(request, pagename, create=1)
20 timestamp = timefuncs.formathttpdate(int(os.path.getmtime(attachment_path)))
21 file = "exportfile.txt"
22 raw = Page(request, pagename).get_raw_body()
23 lines = raw.split('\n')
24 result = []
25 for line in lines:
26 is_good = True
27 for pi in ("#format", "#refresh", "#redirect", "#deprecated",
28 "#pragma", "#form", "#acl", "#language"):
29 if line.lower().startswith(pi):
30 is_good = False
31 break
32 if is_good:
33 result.append(line)
34 result = '\n'.join(result)
35
36 content_type = "text/plain"
37 request.emit_http_headers([
38 'Content-Type: %s' % content_type,
39 'Last-Modified: %s' % timestamp,
40 'Content-Length: %d' % len(result),
41 'Content-Disposition: %s; filename="%s"' % ('attachment', file),
42 ])
43 request.write(result)
44
45 return thispage.send_page(request, msg=msg)