Passing variables to WikklyText macros

2 views
Skip to first unread message

jdlrobson

unread,
Dec 14, 2009, 11:05:21 AM12/14/09
to WikklyText
Hi there,
I'm looking at Wikklytext and designing my own macro. I have got the
Hello World macro running so am set up in this respect however I want
to make some global variables available to the macro.

I am assuming the WikContext would be the best place to do this but I
have no idea how to prep the WikContext variable to contain this
variable.

To best explain I'll try using an example:
#Example:
#define a variable:
foo = {'a':{'variable':2},b:{'variable':3}}
#define a macro
def macro(context, *args):
multiplier = int(args[0].text)
bar =(context.foo.a.variable * multiplier) +
(context.foo.b.variable * multiplier)
return str(bar)

#run wikklytext
wikklytext.WikklyText_to_InnerHTML(arguments)

The result of this would make the <<macro 4>> render 20 in this case.

How would I go about doing something like this? Which argument would
this be passed in for the call to WikklyText_to_InnerHTML?

Really hope you can make sense of what I am trying to achieve here.

Many thanks
Jon

Frank McIngvale

unread,
Dec 14, 2009, 12:22:38 PM12/14/09
to wikkl...@googlegroups.com
On Mon, Dec 14, 2009 at 10:05 AM, jdlrobson <jdlr...@gmail.com> wrote:
Hi there,
I'm looking at Wikklytext and designing my own macro. I have got the
Hello World macro running so am set up in this respect however I want
to make some global variables available to the macro.


Hi, I'm not 100% sure if I'm understanding your question and there is a lot of flexibility here so let me tell you what I'm thinking and you correct me if I'm off track. You say "global" here but I'm not sure where you are wanting to set the variables from. If you are setting the variables from Python, then you can just stick them in the .py module and set them normally.

If you want to set the values from the wikitext and access them from Python, I'd use the <<set>> macro.

So for example:

--wikitext--

<<set A 2>>
<<set B 3>>
<<macro 4>>

--python--

def macro(context, *args)
   multiplier = int(args[0].text)
   A = int(context.var_get_text("A"))
   B = int(context.var_get_text("B"))

   .. rest of code like you had it ..

-----------

If that is what you're looking for, then the context is the right place to put them because using the context makes it threadsafe (multiple wikitexts can set their own "A" and "B" without disturbing each other).

And here's a third way to do it, purely as wikitext, no .py module needed:

--wikitext--
<?py
def macro(context, *args):
   mult = int(args[0].text)
   A = int(context.var_get_text("A"))
   B = int(context.var_get_text("B"))
   return "Answer is: "+str(A*mult + B*mult)
?>

<<set A 2>>
<<set B 3>>
<<macro 4>>
---------------

So you can do it as pure-.py, mix of py+wikitext, or pure wikitext, it just depends on how you are using it.

[BTW, you might want to look at context.var_get() as well -- it returns the full list of Elements in case you want something more complicated than a simple text variable. var_get_text() is just a convenience wrapper.]

Does that help or at least help clarify the question?

frank


I am assuming the WikContext would be the best place to do this but I
have no idea how to prep the WikContext variable to contain this
variable.

To best explain I'll try using an example:
#Example:
#define a variable:
foo = {'a':{'variable':2},b:{'variable':3}}
#define a macro
def macro(context, *args):
 multiplier = int(args[0].text)
 bar =(context.foo.a.variable * multiplier) +
(context.foo.b.variable  * multiplier)
 return str(bar)

#run wikklytext
wikklytext.WikklyText_to_InnerHTML(arguments)

The result of this would make the <<macro 4>> render 20 in this case.

How would I go about doing something like this? Which argument would
this be passed in for the call to WikklyText_to_InnerHTML?

Really hope you can make sense of what I am trying to achieve here.

Many thanks
Jon

--

You received this message because you are subscribed to the Google Groups "WikklyText" group.
To post to this group, send email to wikkl...@googlegroups.com.
To unsubscribe from this group, send email to wikklytext+...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/wikklytext?hl=en.



jdlrobson

unread,
Dec 14, 2009, 6:00:55 PM12/14/09
to WikklyText
Sort of.. I'm using raw python code.
What I don't understand is I have a complex python data structure -
environ -(a dictionary containing strings, integers and other
dictionaries) and I want to access it from my macro.

I try
tiddler =context.var_set("environ",environ)

However when I try:
environ =context.var_get("environ")
Instead of getting the dictionary I get a text element....? (<Element
'Text' at 0x17d4b30>)

What's going on here? I don't understand why it is becoming a text
element.
Jon

On Dec 14, 5:22 pm, Frank McIngvale <fmcingv...@gmail.com> wrote:
> > wikklytext+...@googlegroups.com<wikklytext%2Bunsu...@googlegroups.com>
> > .

Frank McIngvale

unread,
Dec 14, 2009, 11:21:24 PM12/14/09
to wikkl...@googlegroups.com
On Mon, Dec 14, 2009 at 5:00 PM, jdlrobson <jdlr...@gmail.com> wrote:
Sort of.. I'm using raw python code.
What I don't understand is I have a complex python data structure -
environ -(a dictionary containing strings, integers and other
dictionaries) and I want to access it from my macro.

I try
tiddler =context.var_set("environ",environ)

However when I try:
environ =context.var_get("environ")
Instead of getting the dictionary I get a text element....? (<Element
'Text' at 0x17d4b30>)

This may be clearer looking at it from a wikitext perspective. Lets say I do this ...

<<set VAR //__some text__//>>

This does NOT store the literal text "//__some text__//" in the variable VAR. Instead the wikitext is first evaluated, turned into a list of XML-like Elements, and those Elements are stored in VAR. No matter how simple or complicated the wikitext is, a subsequent <<get VAR>> will ALWAYS return a list of Elements, to make the interface uniform.

So now from the Python side, when you do context.var_set("VAR", "123") it actually places the "123" into an Element, and the Element into a list. When you do var_set_text and var_get_text, those routines hide the list accesses, making it simpler to get/set simple text values.

And finally, to your question ... when you do var_set("VAR", arg) it is expecting you to pass an ElementList [var_set() is simply the last step of doing <<set>> which would create an ElementList]. Passing an arbitrary object is pretty much guaranteed to do weird things later when another caller expects an ElementList.

HOWEVER, if you are doing the setting AND getting from within pure Python, why mess with var_set/var_get at all? If you want to stick some data into the context (and it doesn't need to be visible from the wikitext) just do setattr() instead. OR for more future-proof usage, stick it in the context.uservars dict, for your example, "context.uservars["environ"] = environ" would work, AS LONG AS no wikitext ever tries to access "environ".

Am I getting warmer? :-)

frank





To unsubscribe from this group, send email to wikklytext+...@googlegroups.com.

jdlrobson

unread,
Dec 15, 2009, 9:47:10 AM12/15/09
to WikklyText
Sample code might help:
So I run the code below.
My log statement suggests it has done what I want.

However in my macro when I try to get the value
eg. context.uservars["environ"]
I find it doesn't exist. In fact context.uservars is empty. Am I
setting this too early in my code? Where does it get overwritten?

Jon
CODE:
def WikklyText_to_InnerHTML(text, encoding, safe_mode, setvars=None,
max_runtime=-1, url_resolver=None,
tree_posthook=None, xml_posthook=None,
plugin_dirs=None,
rendercache=None,
macro_handler=None,environ=None,tiddler=None,
**kwargs):
from wikklytext import WikklyText_to_XML
from wikklytext.buildHTML import WikklyText_XML_to_InnerHTML

if kwargs.has_key('plugin_dir'):
# in 1.4.0 this was named 'plugin_dir' so accept if plugin_dirs not
given
plugin_dirs = plugin_dirs or kwargs.get('plugin_dir',None)
deprecation("Change 'plugin_dir' to 'plugin_dirs' in args to
WikklyText_to_InnerHTML()")

xml, context = WikklyText_to_XML(text, encoding, safe_mode, setvars,
max_runtime, url_resolver, tree_posthook,
plugin_dirs, rendercache, macro_handler)

if xml_posthook is not None:
xml_posthook(xml, context)
#context.setvar("tiddler")
# allow unlimited time here -- any unbounded recursions have already
been handled above
#return WikklyText_XML_to_InnerHTML(xml, encoding, safe_mode,
links_new_window, max_runtime=-1)
context.add_runtime(1000000)
import logging

context.uservars["environ"] = environ
context.uservars["tiddler"] = tiddler
logging.debug(context.uservars["tiddler"])
html = WikklyText_XML_to_InnerHTML(context, xml, encoding)
return (html,context)



On Dec 15, 4:21 am, Frank McIngvale <fmcingv...@gmail.com> wrote:
> > <wikklytext%2Bunsu...@googlegroups.com<wikklytext%252Buns...@googlegroups.com>

Frank McIngvale

unread,
Dec 15, 2009, 3:53:13 PM12/15/09
to wikkl...@googlegroups.com
On Tue, Dec 15, 2009 at 8:47 AM, jdlrobson <jdlr...@gmail.com> wrote:
Sample code might help:
So I run the code below.
My log statement suggests it has done what I want.

However in my macro when I try to get the value
eg. context.uservars["environ"]
I find it doesn't exist. In fact context.uservars is empty. Am  I
setting this too early in my code? Where does it get overwritten?

Ahh, so you are talking about setting a variable OUTSIDE the WikklyText_to_InnerHTML() call and having it propogate in. The problem right now is that the context is created inside the WikklyText_to_InnerHTML() call and returned as an output-only value once the processing is finished. I did this for convenience initially, but really there needs to be an extra keyword arg here to let you pass your own context IN. (And actually you CAN set text & integer values into .uservars via the "setvars" arg but you are looking to pass arbitrary Python values so that won't work.)

So then your code would look like:

  context = WikContext( ... )
  # set some values into context ...
  context.uservars['A'] = someobject
  context.uservars['B'] = anotherobject
  # now pass it in ..
  html,context = WikklyText_to_InnerHTML( ..., context=context)

Is that what you are looking for? That's easy to add ... just trying to remember if there are any caveats to creating your own WikContext ...

frank

To unsubscribe from this group, send email to wikklytext+...@googlegroups.com.

jdlrobson

unread,
Dec 15, 2009, 4:24:48 PM12/15/09
to WikklyText
But WikklyText_to_InnerHTML doesn't take context as an argument....?

On Dec 15, 8:53 pm, Frank McIngvale <fmcingv...@gmail.com> wrote:
> > > > <wikklytext%2Bunsu...@googlegroups.com<wikklytext%252Buns...@googlegroups.com>
>
> ...
>
> read more »

jdlrobson

unread,
Dec 15, 2009, 4:25:45 PM12/15/09
to WikklyText
Oh sorry, somehow got confused by your post. Yes that would be
something I'd be looking for. Is that easy to do?

Jon

On Dec 15, 8:53 pm, Frank McIngvale <fmcingv...@gmail.com> wrote:

Frank McIngvale

unread,
Dec 16, 2009, 11:46:01 AM12/16/09
to WikklyText

On Dec 15, 3:25 pm, jdlrobson <jdlrob...@gmail.com> wrote:
> Oh sorry, somehow got confused by your post. Yes that would be
> something I'd be looking for. Is that easy to do?

Yes, it is a fairly trivial change ... the subtlety comes in if you
want to subclass WikContext. In that case you have to provide your
own .copy() method since the context has to be cloned at several
points through the parsing/evaluation process, so I'll add comments to
that effect. I'll put out a 1.9.3-TEST version with the changes.

frank
> ...
>
> read more »

jdlrobson

unread,
Dec 18, 2009, 11:51:35 AM12/18/09
to WikklyText
Great.
Am assuming doing pip install wikklytext==dev will give me the latest
version when it is released?
My rss feed is now pointed at http://wikklytext.com/wiki/rss.xml as I
am quite blocked in my wikklytext development without this.

Much appreciated.
Jon

> ...
>
> read more »

Frank McIngvale

unread,
Dec 18, 2009, 1:53:01 PM12/18/09
to wikkl...@googlegroups.com
Actually I'm not putting the 1.9.x series on PyPI yet -- there are some compatibility breaks in how the wiki attaches to Apache and I wanted to give anyone running the wiki a chance to switchover without breaking it. I'll be posting the link here instead.

BTW, I'm not familiar with the notation like "wikklytext==dev" -- does PyPI let you post "stable" vs "dev" releases? I looked before but couldn't find anything like that.

frank

> ...
>
> read more »

--

You received this message because you are subscribed to the Google Groups "WikklyText" group.
To post to this group, send email to wikkl...@googlegroups.com.

jdlrobson

unread,
Dec 18, 2009, 2:05:46 PM12/18/09
to WikklyText
I've not had any experience myself but it's definitely possible (pip
for install can be installed in this way - pip install pip==dev and
pip install pip both work.

I'm told this might provide a good starting point:
http://peak.telecommunity.com/DevCenter/setuptools#making-your-package-available-for-easyinstall

Jon


On Dec 18, 6:53 pm, Frank McIngvale <fmcingv...@gmail.com> wrote:
> Actually I'm not putting the 1.9.x series on PyPI yet -- there are some
> compatibility breaks in how the wiki attaches to Apache and I wanted to give
> anyone running the wiki a chance to switchover without breaking it. I'll be
> posting the link here instead.
>
> BTW, I'm not familiar with the notation like "wikklytext==dev" -- does PyPI
> let you post "stable" vs "dev" releases? I looked before but couldn't find
> anything like that.
>
> frank
>

> On Fri, Dec 18, 2009 at 10:51 AM, jdlrobson <jdlrob...@gmail.com> wrote:
> > Great.
> > Am assuming doing pip install wikklytext==dev will give me the latest
> > version when it is released?

> > My rss feed is now pointed athttp://wikklytext.com/wiki/rss.xmlas I

> ...
>
> read more »

Frank McIngvale

unread,
Dec 18, 2009, 2:25:14 PM12/18/09
to wikkl...@googlegroups.com
Thanks for the link. OK 1.9.3 is out, please give it a whirl. If this doesn't help with what you're doing let me know.

Here is a complete demo -- I'm using embedded Python code instead of a full plugin, but functionally there is no difference:
===============================================================
"""
Shows how to pass your own WikContext instead of having it automatically created.
This lets you do interesting things like pass arbitrary objects into the wikitext from Python.
"""
from wikklytext import WikContext, WikklyText_to_InnerHTML

wikitext = """
<?py
def sum_it(context):
    obj = context.uservars['MYOBJECT']
    return str(obj.a + obj.b + obj.c)
?>

Hello wikitext! The answer is: <<sum_it>>
"""

class MyObject(object):
    def __init__(self, a, b, c):
        self.a = a
        self.b = b
        self.c = c
       
# have to turn off restricted_mode so I can use <?py
context = WikContext(restricted_mode=False)

# Pass an arbitrary object into the wikitext.
# Note that context.uservars is where values are stored/fetched when you
# do <<set>> and <<get>>. When placing an arbitrary Python object into .uservars
# like this, you (in general) CANNOT DO <<get MYOBJECT>> without causing an error
# since <<get>> assumes that it is returning a list of Elements.
# MYOBJECT should only be accessed by Python code in a plugin or <?py section as above.
o = MyObject(10,11,12)
context.uservars['MYOBJECT'] = o

html,context = WikklyText_to_InnerHTML(wikitext, 'utf-8', context=context)
# should print "Hello wikitext! The answer is: 33"
print html
========================================

frank

> ...
>
> read more »

jdlrobson

unread,
Dec 21, 2009, 11:29:35 AM12/21/09
to WikklyText
Brilliant this seems to have done just the job :)
Thanks Frank
Jon

> On Fri, Dec 18, 2009 at 1:05 PM, jdlrobson <jdlrob...@gmail.com> wrote:
> > I've not had any experience myself but it's definitely possible (pip
> > for install can be installed in this way - pip install pip==dev and
> > pip install pip both work.
>
> > I'm told this might provide a good starting point:
>

> >http://peak.telecommunity.com/DevCenter/setuptools#making-your-packag...

> ...
>
> read more »

Reply all
Reply to author
Forward
0 new messages