How to handle Macro Content for python

How to tackle the problem of handling the content of the macro in Python

We wanted to use info from puppet in our xwiki, but we did not like to copy this info. We planned to read a file and then display it in the wiki. We did use some of the standard extensions but that was not to our liking.

We did make a macro which would read the puppet role or profile from a specific place. The name of the xwiki page should have the same name as the puppet profile or role. The content would be displayed as a code block, also a list of used profiles would be added with links to specific page.

But still we did need a macro which can read files and display them using names. So we started to look how to do that.

The only thing I could find was : https://www.xwiki.org/xwiki/bin/view/Documentation/DevGuide/Tutorials/WritingMacros/WikiMacroTutorial/

{{velocity}}$xcontext.macro.content{[/velocity}}

So after some testing steps we found how to get the info :

First step code

print(type(xcontext.macro))

Result :
<type ‘java.util.HashMap’>

Second step code

print(xcontext.macro)

Result :
result: None, context: org.xwiki.rendering.transformation.MacroTransformationContext@6d4adeb3,
doc: Main.Kladblok.Jo.A test.A Test.WebHome, descriptor: org.xwiki.rendering.macro.wikibridge.WikiMacroDescriptor@15660fa,
params: org.xwiki.rendering.macro.wikibridge.WikiMacroParameters@9216a66, content: een twee drie

We want the -> content: een twee drie entry

Last step test code

print(xcontext.macro.get('content')

Result:
een twee drie

I will include a small second part which will read the code as file and display the content, if the file holds any xwiki code this will be interpreted and displayed in the correct “xwiki” format. If you watch the code you will see 2 commented lines. If you remove the comment in the code it will be displayed as a code block.

The other macros we made (ugly code) will read puppet role and profile files and display them as xwiki code blocks and references to other profiles.

Summary

You need to create a macro page see https://www.xwiki.org/xwiki/bin/view/Documentation/DevGuide/Tutorials/WritingMacros/WikiMacroTutorial/

If you look at the sample of the XWiki.WikiMacroClass you must make some changes to use the code sample below. We will first highlight the changes :

Macro id : rfbnacb
Macro name : Read File By Name and Display Code Block
Macro code : paste the python code here

If you get a java stack dump (click on the red error message) The indentation of python might not be correct error hint almost at the bottom of the dump.

Read a file by name as code block (in our tomcat it has to be in a specific directory) to be accessed due to rights (wrongs)

This macro is simple and quit strait forward we expect only on filename (and path). If the file does not exist you get an error message, as shown in the error box below.

Red Info block with text : There is no file with name :/var/lib/tomcat/puppetcode/this_file_does_not_exist

Use of the Macro

Use the macro tags as shown below and use path and file name to display the file. wiki code in the file will be interpreted see the samples below.

{{rfbnacb}}
/var/lib/tomcat/puppetcode/role-overview
{{/rfbnacb}}

MacroCode in python

Below is the Macro Code in python with simple error handling and comments.

The trick was how to retrieve the filename and path between the macro tags. We only found a velocity example there can be more info found at the end …

Lot of ugly python code below :

{{python}}
import sys

# Read File By Name as Code Block (rfbnacb)
# rfbnacb

# Wil display error message  
def errormess(message):
   s='\n\n{{error}}\n\n'+message+'\n\n{{/error}}\n\n'
  print(s)
  return    

def readfile2list(filename):
  import os.path  
  if os.path.isfile(filename) :
      with open(filename,'r') as f:
            mylist = f.read().splitlines()
       f.close()
  else :
#      File not foud so display error message
       errormess('There is no file with name :'+filename)
       mylist=[]
  return mylist

#
#   --------------------------------------------------------------------------
#   Main Loop

# Get the text/info between the macro tags {{rfbn}} and {{/rfbn}}  
filename=xcontext.macro.get('content')
thisprofilelist=readfile2list(filename)

# Uncomment line below to display the file as code block with syntax high lighting
print('{{code}}')

# We print the whole file if there is wiki code in the file this will be interpreted bij the wiki
for i in thisprofilelist:
  print (i)  

# Uncomment the line below to stop displaying the file as code block with syntax high lighting
print('{{/code}}')

{{/python}}

Sample output :

 === Puppet role gevonden ===

[[assethook>>t;doc:Main.Role.assethook.WebHome]]
[[bacula>>;doc:Main.Role.bacula.WebHome]]

Hint :

If you comment out the print(‘{{code}}’) and the print(‘{{/code}}’) the file will be interpreted as xwiki code.