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

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)
} } }

ExportFile_1.png

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

wikiutil_20070104_patch.txt

   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 ()
exportfile-1.6.0-1.py
   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)
text_x_exportfile-1.6.0-3.py

comments wanted

If something like this could be implemented may be we could use it for all codings on the Markets. Because

-- ReimarBauer 2007-01-02 19:31:43

ThomasWaldmann proposed to add a ContentSaving Action too.

wikiutil patch:

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)


CategoryFeatureRequest

MoinMoin: FeatureRequests/ExportFileAction (last edited 2007-10-29 19:13:35 by localhost)