[albatross-users] Some questions and my albatross wrapper....

Cameron Blackwood korg at darkqueen.org
Thu Feb 23 14:40:07 EST 2006





Hi everyone. Im an on again, off again albatross user and Ive been
working on a 'wrapper class' to make my albatross programming easier.

This post is kind of long, but first Ill as some silly questions :)
and some comments and then Ill talk about the wrapper Im writing.

Im a system admin my trade, not a web designer so _please_ do post any
opinions or comments on better ways to do this (because it probably
hasnt occured to me :)



Doc request: Extending tags & input_add
---------------------------------------
I was coding up a Custom tag to make input/command buttons easier, and it
took me ages to get the input value into the context.

It took me a while to locate the input_add() function :). Maybe make
a note of that in the docs? Yes, it was quickly obvious from looking
at the source, but how about adding:

  "If your tag does form input, you need to register the input name
  with the input_add function" :)

Oh and I just want to say that Id been avoiding making my own tags,
but boy, is it ever easy and cool! Again albatross rocks with its
simplicity and easy of use.


Doc request: Extended tag names
-------------------------------
Could we get some documentation on what is makes a _valid_ name for an
extended tag? Or maybe register_tagclasses() should produce an error
if the name isnt valid (so you dont register stuff that is never
called).

Lets play 'Which of the following are valid'? :)
  alx-foo_moo:  valid
  alx-foo-moo:  invalid
  al-foo-moo:   ah, its too hard, lets just stick with alx-foomoo :)
:)

Defining a tag alx-test_for that silently stops working if I rename it
alx-test-for is just plain weird. I guess I expected that if you
register a tag that cant be called, register would say something. :)

Either that or put something in the docs?


For loops with var="foo"?
-------------------------
I keep using for loops and I keep needing 'iter.value()' all through my
templates which is ugly and kind of annoying. (I tend to use the
object more than the iterator, but maybe thats just me.)

Is there any reason we cant make the al-for optionally set a variable
in the context?

I hacked up a test version and I have this working:
  <alx-kwfor obj="o" expr="[1,1.4,'foo',[1,2],'end']">
    <li><al-value expr="type(o)">
    <al-value expr="o">
  </alx-kwfor>
produces:
  * <type 'int'>1
  * <type 'float'>1.4
  * <type 'str'>foo
  * <type 'list'>[1, 2]
  * <type 'str'>end

Which seems handy to me. Maybe there could be an optional tag in
al-for, rather than everyone rolling their own?

Now, what to call it....
  value? valuename? variable? var? item? itemname? name? dagnamit?


Templates?
----------
I love my albatross :), but what I want is for a single meta-template
over my whole site. Currently I have the following in all my
tempaltes:

  <al-expand name="header"/>
  <al-form method="post">
  **my stuff**
  </al-form>
  <al-expand name="footer"/>

But really thats kind of ugly. Is there a better way to do it?
(header and footer are magically loaded, obviously).

I thought about hacking the load_template code to chuck this on
automatically or some ugly system where you always just render a base
template, rather than the page template, and the page code itself is
just a macro or something. Nothing was really obvious or clear.

Comments and ideas welcome here.

(note my sudden idea below might solve this...)


More on templates...
--------------------
As I said, Im working on a wrapper function for albatross and it seems
to me that the one could argue that the template should be provided
by the page object, not passed to the page object in... *BING!*
*SUDDEN IDEA!*

Let me change this topic to:  moron templates! :)
Myself being the moron.

I was passing the template to the page's __init__ function as shown in
some of the demo code, but I dont have to do that, do I? I just realised
that writing this. I can dynamically locate the template in my page's
display function. Maybe.

Hmm. That may solve my 'standard layout' problem. Hmm. Maybe I
can make my page class have a 'return_template_string' function which
generates the actual template from the file and the headers and
creates a Template.

[Note, I might just be ranting for this section, I havnt thought it
through fully.]


templates wrong?
----------------
Maybe Ive been doing them incorrectly... I think I need to think about
them some more.

Maybe ill end up with my page class doing the loading and creating of
the Template (from the headers & footers and the actual template
file) as that seems to be the 'right thing'(tm).



My wrapper class
================
Why a wrapper class?

Well I always found it kind of hard to revisit albatross code that Id
written. There were a number of reasons for that but mostly they boil
down to the fact that I want to write code that is 'just magically loaded
and works' rather than having to tinker with albtross startup itself.

Now when Im in 'albatross' mode, its all easy enough and flowing, but
getting there was always a bit of a struggle (and it was usually the
annoying startup & setup stuff and not the everyday pages stuff that got
to me). So I tried to create a better wrapper for Applications and Pages
that did most of the work for me.

  * Creating the APP.
    problem:  All those register_page()'s were kind of annoying.
    solution: give the APP a single directory on start up and make it
              locate and load all the pages in that directory tree
              and register them. (It also finds the start page
              automatically too.)

  * global and locals
    problem:  Kind of obscure to use globals and locals in the ctx
    solution: page has a create_global and create_local function and
              automatically flushes the locals on page change. Much
              less overhead.

  * looking up variables
    problem:  ctx.locals.foo is a bit confusing to people new to
              albatross (especially if foo is a global)
    solution: page and ctx now support  self['foo']='moo'
              (If foo doesnt exist, it barfs, so you need to set it as
              local or global before use.)

  * debugging messages
    you can just self.DEBUG("Im looking at foo... v==%s",foo)
    and it appears in a log. Also DEBUGvars dumps all the variables in
    the context into the DEBUG output. (Which I usually just display
    in my footer while developing.) It also writes what its calling
    and doing into the DEBUG output so you can see page changes and what
    is being called.

  * page class.
    An actual base page class which supports some short cuts to use
    the ctx. Eg, 

      def work_process(s):
        login,username,passwd=s['login','username','password']
        s.DEBUG('login [%s][%s]',username,passwd)
        if login and username=='admin' and passwd=='foo':
          s.goto('ok')

    seems easier to read and maintain. Also s['notset'] return None if
    the variable doenst exist so you can go:

        if s['login'] and s['username']=='admin' and s['passwd']=='foo':

  * command buttons
    Smarter wrapping of <input type="submit"> buttons so you can do
    template code like this:

      <al-for iter="i" expr="ten_list">
         <al-value expr="i.value()">::
         <alx-kwbutton label="inc this number" op="add" args="[i.index(), 1]">

    which will make a button with the label and call a method 'add'
    with the arguments specified if you click it.

    (It stores the details in a list in the context and makes an
    name="id" and then checks that id against the list of pressed
    buttons before page_process. It calls them automatically just
    after process.)

    (Im going to extend this to other buttons (radio/choice) too.)

    (There might be a nicer way to do this, any ideas are welcome.)

  * goto (set_page) acts like 'cd'
    Given I loaded all the pages in from a single directory, you can
    end up with pages like  login, user/info, user/edit, user/messages
    so the goto function is relative to where you are now. (Its a
    small thing, I know.)

Im trying to get this stuff neated up and postable by the weekend so
that I can use it as a library in the pyweek.org contest (write a game
in python in a week) for a web based game.

Ill post a url to it here once its up (IE readable by non insane humans :)
and I have the template thing worked out more.

(Then its off to do my image library... :)


cheers,
cam


PS: I feel stupid wrapping albatross, because i guess im really just
    wrapping away all the stuff that always gave me trouble.

    But it seems to me that everyone in the universe has to make their
    own web framework at some stage and albatross always seems 'so
    close' to perfect that wrapping the bits that annoyed me seems the
    easiest solution. :)

    No offence to the object-craft. I love albatross and even used the
    template stuff to dynamically generate c and c++ code in a research
    project. :) :) :) :)

--
 / `Rev Dr'   cam  at darkqueen.org            Roleplaying, virtual goth \
<   http://darkqueen.org        Poly, *nix, Python, C/C++, genetics, ATM  >
 \  [+61 3] 9809 1523[h]         skeptic, Evil GM(tm). Sysadmin for hire /
                      ---------- Random Quote ----------
modesty, n.:
	Being comfortable that others will discover your greatness.



More information about the Albatross-users mailing list