This is the first ALPHA release of Neotonic ClearSilver.
This release is denoted as ALPHA. Although the code has been tested,
and is fairly stable, the current interfaces are subject to change as we
continue to work on the product.
Some preliminary documentation is available from
http://www.neotonic.com/clearsilver/docs/
The source package is available from:
http://www.neotonic.com/clearsilver/downloads/
Brandon
--
"Computers make very fast, very accurate, mistakes."
http://www.fiction.net/blong/
Main differences in this release:
- cgi_init() has been split into two calls, cgi_init() and cgi_parse(),
cgi_parse() is used to actually parse the POST data, all other CGI
data is added to the dataset and parsed in cgi_init(). This allows
one to look at CGI.ContentLength and abort a file upload if the file
is too large, for example.
- The parameter to cgi_init() has been changed. Now, you can create
your own HDF, and pass that to cgi_init(), and it will become the
CGI's dataset.
- There is now a callback structure that you can set up for getting
progress of form-data upload. Its fairly primitive because of the
restrictions of the HTTP form-data structure, but it should allow for
something. The callback announces its progress through the entire
POST data, not just each file.
Downloads available from the usual location:
http://www.neotonic.com/clearsilver/downloads/
Both a source download and patch against 0.1 are available.
Brandon
--
"Faith strikes me as intellectual laziness." -- Robert A. Heinlein
http://www.fiction.net/blong/
I'd like to see special kinds of "var" commands which know how to do
string escaping. For example, I'd like one which knows how to escape
HTML chars, and another which knows how to escape
javascript. Here are some possible syntax ideas:
var my_javascript_var = "<?cs var:js_escape(MY_HDF_DATA) ?>";
var my_javascript_var = "<?cs var_js:MY_HDF_DATA ?>";
--
David Jeske (N9LCA) + http://www.chat.net/~jeske/ + jeske@...
My CS code would be simplified in many cases if I had "special" local
variables during 'each' commands. For example "_n", "_last"
would be very nice.
This code:
<?cs setvar:count = #0 ?>
<?cs each:element = List ?>
<?cs setvar: count = count + #1 ?>
<?cs /each ?>
<?cs setvar:n = #0 ?>
<?cs each:element = List ?>
<?cs if:n == #0 ?>
handle first row
<?cs elif:n == #count ?>
handle last row
<?cs else ?>
other rows..
<?cs /if ?>
<?cs /each ?>
Would be simplified to:
<?cs each:element = List ?>
<?cs if:_n == #0 ?>
handle first row
<?cs elif:_last ?>
handle last row
<?cs else ?>
handle other rows
<?cs /if ?>
<?cs /each ?>
--
David Jeske (N9LCA) + http://www.chat.net/~jeske/ + jeske@...
--- David Jeske <jeske@...> wrote:
> I'd like to see special kinds of "var" commands which know how to do
> string escaping. For example, I'd like one which knows how to escape
> HTML chars, and another which knows how to escape
> javascript. Here are some possible syntax ideas:
>
> var my_javascript_var = "<?cs var:js_escape(MY_HDF_DATA) ?>";
> var my_javascript_var = "<?cs var_js:MY_HDF_DATA ?>";
and don't forget evar_js too.
-R
__________________________________________________
Do You Yahoo!?
Make international calls for as low as $.04/minute with Yahoo! Messenger
http://phonecard.yahoo.com/
Is there anything I can do to convince you to support real boolean
expressions with operator precedence?
msg.is_open == "y" | msg.is_open == "s" | msg.is_open == "p"
(msg.is_open == "y" | msg.is_open == "s") & msg.m_type == 0
--
David Jeske (N9LCA) + http://www.chat.net/~jeske/ + jeske@...
This is a "pre-massive change" release that contains various changes
from Rob Wheeler and myself:
- HTML Compression is now a compile time option
- reading off the socket for application/x-www-url-encoded POSTs
will now keep trying to read until all the data is available (or a
close condition occurs)
- Rob's code for changing the tmp dir for file uploads, and also for
not unlinking those files right away
- better code for reading lines off the socket (ie, better buffering)
- some better errors reporting during cs parse
- some errors during cs parsing fixed
- HDF now has symlinks. The : operator in HDF files now does a
symlink instead of a copy
- some fixes to the python module for use in PyApache (required
because of our trickiness with having multiple modules behind one
module)
Brandon
--
"Kill a man, and you are an assassin. Kill millions of men, and you
are a conqueror. Kill everyone, and you are a god." -- Jean Rostand
http://www.fiction.net/blong/
Ok, this release has some major changes to the CS Parsing code, some of
which are not compatible (on purpose).
- CS now supports generic expressions for if:, call arguments and set.
These expressions evaluate with the same precedence as C, which is
different than the strict left-right operator indifferent precedence
CS used before. Note that parenthesis are not yet supported in
expressions (due to some conflicts between the three levels of
parsing that I'll have to fix later)
- change to cgi_vredirect to not use the va_list multiple times, it
was core dumping on PowerPC/Linux
All that, and the library is 6k smaller.
These changes should make it easier to support some other operators in
expressions, including [] for HDF variable indexing and builtin functions
for handling escaping and the like.
You can ignore the included lemon grammar, it isn't entirely accurate
and isn't used.
Brandon
--
"Video games, not parents, are to blame for many of these teenage crimes.
I'm certain it was Frogger that taught my son to jaywalk."
-- John Bumbry, Systems Analyst
http://www.fiction.net/blong/
I wrote the following that I call the LinkANator(tm). The idea is that when
creating an href, generally speaking
only one item tends to change (though this should easily be expandable to
lists too), the rest of the items
need to get their values set, and I like to not have messy links so anything
with our default value shouldn't
show up in the href, and it should get the ? and &'s correct. So take the
following:
<?cs def:linkPiece(thelink, name, value, default, passedInName) ?>
<?cs set:piece = "" ?>
<?cs if:name != passedInName ?>
<?cs if:value != default ?>
<?cs if:thelink == "" ?>
<?cs set:thelink = "?" ?>
<?cs else ?>
<?cs set:thelink = thelink + "&" ?>
<?cs /if ?>
<?cs set:piece = name + "=" + value ?>
<?cs /if ?>
<?cs /if ?>
<?cs set:thelink = thelink + piece ?>
<?cs /def ?>
<?cs def:makeLink(tmpl, name, value) ?>
<?cs set:newlink = "" ?>
<?cs each:x = tmpl ?>
<?cs call:linkPiece(newlink, x.name, x.value, x.default, name) ?>
<?cs /each ?>
<?cs if:newlink == "" ?>
<?cs set:newlink = "?" ?>
<?cs else ?>
<?cs set:newlink = newlink + "&" ?>
<?cs /if ?>
"<?cs if:PAGENAME ?><?cs var!PAGENAME ?><?cs /if ?><?cs var!newlink ?><?cs
if:name ?><?cs var!name ?>=<?cs var!value ?><?cs /if ?>"
<?cs /def ?>
############# End of LinkANator(tm)
Looks groovy, except that to use it I need to define everything inline in
the cs file:
<?cs set:LinkBuild.0.name = "s" ?>
<?cs set:LinkBuild.0.value = CGI.cat_faq.SortBy ?>
<?cs set:LinkBuild.0.default = "p" ?>
<?cs set:LinkBuild.1.name = "cat" ?>
<?cs set:LinkBuild.1.value = CGI.cat_faq.Category ?>
<?cs set:LinkBuild.1.default = "-1" ?>
<?cs set:LinkBuild.2.name = "b" ?>
<?cs set:LinkBuild.2.value = CGI.cat_faq.Begin ?>
<?cs set:LinkBuild.2.default = "1" ?>
<?cs call:makeLink(LinkBuild, "bob", "sally") ?>
Note the unhappy use of value having to be done in the CS file itself. While
not totally heinous
it would be nice to be able to move the LinkBuild def into an hdf file. This
would require that
I be able to do check the "value" field against the default as an evar,
since value will in general
be coming from the cgi:
<?cs if:evar(value) == default ?> # illegal syntax
(In theory I would probably have a "type" field so that value could either
be var'd or evar'd depending on
what you want to put in there.)
Not having gone through the ClearSilver source cuz I'm lazy, the first
question is whether evar() is legal
in a def()? In CS/HDF is wasn't because evar() required a tree change at
display time since the def()
wasn't really expanded inplace like a macro, but instead had one tree that
was referenced whenever it
was used.
Now, if it is possible, what I'd really like would be to dump evar() as
syntax and instead have it be able
to parse like # does for numbers, maybe like:
<?cs if:&value == default ?>
Of course, if evar isn't possible everywhere then this point is moot anyway.
Thoughts?
cwikla
On 11/07/01 John L Cwikla uttered the following other thing:
> Looks groovy, except that to use it I need to define everything inline in
> the cs file:
>
> <?cs set:LinkBuild.0.name = "s" ?>
> <?cs set:LinkBuild.0.value = CGI.cat_faq.SortBy ?>
> <?cs set:LinkBuild.0.default = "p" ?>
> <?cs set:LinkBuild.1.name = "cat" ?>
> <?cs set:LinkBuild.1.value = CGI.cat_faq.Category ?>
> <?cs set:LinkBuild.1.default = "-1" ?>
> <?cs set:LinkBuild.2.name = "b" ?>
> <?cs set:LinkBuild.2.value = CGI.cat_faq.Begin ?>
> <?cs set:LinkBuild.2.default = "1" ?>
>
> <?cs call:makeLink(LinkBuild, "bob", "sally") ?>
>
>
> Note the unhappy use of value having to be done in the CS file itself. While
> not totally heinous
> it would be nice to be able to move the LinkBuild def into an hdf file. This
> would require that
> I be able to do check the "value" field against the default as an evar,
> since value will in general
> be coming from the cgi:
>
> <?cs if:evar(value) == default ?> # illegal syntax
Um, couldn't you just (in the hdf file) do:
LinkBuild.0.name = s
LinkBuild.0.value : CGI.cat_faq.SortBy
LinkBuild.0.default = p
etc?
: is a symlink in ClearSilver, not a hard copy (as of 0.3)
> (In theory I would probably have a "type" field so that value could either
> be var'd or evar'd depending on
> what you want to put in there.)
>
> Not having gone through the ClearSilver source cuz I'm lazy, the first
> question is whether evar() is legal in a def()? In CS/HDF is wasn't
> because evar() required a tree change at display time since the def()
> wasn't really expanded inplace like a macro, but instead had one tree
> that was referenced whenever it was used.
evar is "legal" in a def, but it isn't going to do what you think if you
use it against a local variable, for the same reason it was in CS/HDF.
The reason is, evar is evaluated at parse time, not at render time.
In CS/HDF, the point of this was to keep from allocating memory at
render time, and that same philosophy was sorta used in ClearSilver, but
I'm less attached to the concept. It would mean actually doing a
separate parse and render for "lvar", though.
> Now, if it is possible, what I'd really like would be to dump evar() as
> syntax and instead have it be able
> to parse like # does for numbers, maybe like:
>
> <?cs if:&value == default ?>
Is that a good choice, syntax wise? Given what & does in C, I would
expect that to not evar.
Brandon
--
"A snooze button is a poor substitute for no alarm clock at all."
http://www.fiction.net/blong/
Ah, the ":" syntax works just groovilishissly.
----- Original Message -----
From: "Brandon Long" <blong@...>
To: <clearsilver@yahoogroups.com>
Sent: Wednesday, November 07, 2001 3:28 PM
Subject: Re: Evar notation akin to #
> On 11/07/01 John L Cwikla uttered the following other thing:
> > Looks groovy, except that to use it I need to define everything inline
in
> > the cs file:
> >
> > <?cs set:LinkBuild.0.name = "s" ?>
> > <?cs set:LinkBuild.0.value = CGI.cat_faq.SortBy ?>
> > <?cs set:LinkBuild.0.default = "p" ?>
> > <?cs set:LinkBuild.1.name = "cat" ?>
> > <?cs set:LinkBuild.1.value = CGI.cat_faq.Category ?>
> > <?cs set:LinkBuild.1.default = "-1" ?>
> > <?cs set:LinkBuild.2.name = "b" ?>
> > <?cs set:LinkBuild.2.value = CGI.cat_faq.Begin ?>
> > <?cs set:LinkBuild.2.default = "1" ?>
> >
> > <?cs call:makeLink(LinkBuild, "bob", "sally") ?>
> >
> >
> > Note the unhappy use of value having to be done in the CS file itself.
While
> > not totally heinous
> > it would be nice to be able to move the LinkBuild def into an hdf file.
This
> > would require that
> > I be able to do check the "value" field against the default as an evar,
> > since value will in general
> > be coming from the cgi:
> >
> > <?cs if:evar(value) == default ?> # illegal syntax
>
> Um, couldn't you just (in the hdf file) do:
> LinkBuild.0.name = s
> LinkBuild.0.value : CGI.cat_faq.SortBy
> LinkBuild.0.default = p
>
> etc?
>
> : is a symlink in ClearSilver, not a hard copy (as of 0.3)
>
> > (In theory I would probably have a "type" field so that value could
either
> > be var'd or evar'd depending on
> > what you want to put in there.)
> >
> > Not having gone through the ClearSilver source cuz I'm lazy, the first
> > question is whether evar() is legal in a def()? In CS/HDF is wasn't
> > because evar() required a tree change at display time since the def()
> > wasn't really expanded inplace like a macro, but instead had one tree
> > that was referenced whenever it was used.
>
> evar is "legal" in a def, but it isn't going to do what you think if you
> use it against a local variable, for the same reason it was in CS/HDF.
> The reason is, evar is evaluated at parse time, not at render time.
> In CS/HDF, the point of this was to keep from allocating memory at
> render time, and that same philosophy was sorta used in ClearSilver, but
> I'm less attached to the concept. It would mean actually doing a
> separate parse and render for "lvar", though.
>
> > Now, if it is possible, what I'd really like would be to dump evar() as
> > syntax and instead have it be able
> > to parse like # does for numbers, maybe like:
> >
> > <?cs if:&value == default ?>
>
> Is that a good choice, syntax wise? Given what & does in C, I would
> expect that to not evar.
>
> Brandon
> --
> "A snooze button is a poor substitute for no alarm clock at all."
> http://www.fiction.net/blong/
>
> To unsubscribe from this group, send an email to:
> ClearSilver-unsubscribe@yahoogroups.com
>
>
>
> Your use of Yahoo! Groups is subject to http://docs.yahoo.com/info/terms/
>
>
--- Brandon Long <blong@...> wrote:
> > <?cs if:&value == default ?>
>
> Is that a good choice, syntax wise? Given what & does in C, I would
> expect that to not evar.
How about <?cs if: *value == default ?>?
-R
__________________________________________________
Do You Yahoo!?
Find a job, post your resume.
http://careers.yahoo.com
Yeah, after I sent it I thought * would have been better, but because of the
":" syntax I don't know if it's needed anymore.
----- Original Message -----
From: "Rob Wheeler" <rob_wheeler@...>
To: <ClearSilver@yahoogroups.com>
Sent: Wednesday, November 07, 2001 3:58 PM
Subject: Re: Evar notation akin to #
> --- Brandon Long <blong@...> wrote:
> > > <?cs if:&value == default ?>
> >
> > Is that a good choice, syntax wise? Given what & does in C, I would
> > expect that to not evar.
>
> How about <?cs if: *value == default ?>?
>
> -R
>
>
> __________________________________________________
> Do You Yahoo!?
> Find a job, post your resume.
> http://careers.yahoo.com
>
>
> To unsubscribe from this group, send an email to:
> ClearSilver-unsubscribe@yahoogroups.com
>
>
>
> Your use of Yahoo! Groups is subject to http://docs.yahoo.com/info/terms/
>
>
Ok, the list of changes:
- first pass at a "loop" command in CS. Format is fairly ugly, but
basically:
<?cs loop:i = #1, #50 ?>
<?cs /loop ?>
the loop will be executed sequentially with i = 1, i = 2, etc up to
i = 50 (inclusive). Also:
<?cs loop:i = #1, #55, #2 ?>
<?cs /loop ?>
the loop will be executed sequentially with i = 1, i = 3, i = 5, etc
up to i = 55 (inclusive). Also:
See test7.cs in the cs directory for more examples.
- allow def command anywhere (per Rob's request)
- fix text->html function handling of email/urls
- var command now works more like an echo, in that it takes a full
expression, so the following do what you'd expect:
<?cs var:"5" ?>
<?cs var:Foo.Bar + "&" Bar.Foo ?>
etc.
- Add an apache module for ClearSilver, mod_ecs. See the README in
the mod_ecs directory for more information. Basically, this allows
you to use your existing ClearSilver CGI's without the fork/exec
overhead with very minimal changes.
As usual, the new version is available for download from:
http://www.neotonic.com/clearsilver/
Brandon
--
"I need to either get a new hard drive or clean my home dir."
-- Mark Notarus
http://www.fiction.net/blong/
ClearSilver developers,
Currently, it looks like the each command sorts entries by the order in
which they were inserted into the HDF dataset. I tried sorting based on
the alphabetical/numerical values of the HDF keys, but that does not
work. I was wondering if sorting by the order in which items were
inserted into the dataset was intentional behavior. That is, can I
count on that behavior?
Thanks,
Alan
On 01/30/02 Alan Braverman uttered the following other thing:
> ClearSilver developers,
>
> Currently, it looks like the each command sorts entries by the order in
> which they were inserted into the HDF dataset. I tried sorting based on
> the alphabetical/numerical values of the HDF keys, but that does not
> work. I was wondering if sorting by the order in which items were
> inserted into the dataset was intentional behavior. That is, can I
> count on that behavior?
Yes, sorting by insertion order is intentional behavior.
HDF stores sub values for a node as a linked list, with new entries
inserted on the end. CS just walks the linked list in order. In the
future, we might provide functions for the CS each syntax which will
allow you to walk the values in different sort orders... maybe. Or
maybe it'll be a function on HDF that will have to be run prior to the
template stage.
Brandon
--
"The *reason* for exploding the planet is so you can surf on the shock
waves." -- Melanie Rimmer
http://www.fiction.net/blong/
--- Brandon Long <blong@...> wrote:
> maybe it'll be a function on HDF that will have to be run prior to
> the template stage.
Pretty grody, but you could do:
static int sortByName(const void *a, const void *b) {
HDF *ha = (HDF *) a;
HDF *hb = (HDF *) b;
return strcasecmp(hdf_get_value(ha, "Name", ""), hdf_get_value(hb,
"Name", ""));
}
static
NEOERR *hdf_sort_obj(HDF *h, int (*compareFunc)(const void *, const
void*))
{
HDF *p, *c = hdf_obj_child(h);
int swapped;
do {
swapped = 0;
for (p = c; p && p->next; p = p->next) {
if (compareFunc(p, p->next) > 0) {
HDF *tmp = p->child;
p->child = p->next->child;
p->next->child = tmp;
swapped = 1;
}
}
} while (swapped);
return STATUS_OK;
}
__________________________________________________
Do You Yahoo!?
Great stuff seeking new owners in Yahoo! Auctions!
http://auctions.yahoo.com
With a fresh extract of the 0.4 ClearSilver library, running 'make' on
my RedHat Linux 7.1 box produces errors because the dependency file
generated expects to find "../Python.h" Obviously, this file is in
/usr/include/python1.5...
Might want to tweak the dependency generation on that one.
...Paul
On 02/11/02 cryomax uttered the following other thing:
> With a fresh extract of the 0.4 ClearSilver library, running 'make' on
> my RedHat Linux 7.1 box produces errors because the dependency file
> generated expects to find "../Python.h" Obviously, this file is in
> /usr/include/python1.5...
>
> Might want to tweak the dependency generation on that one.
There's currently no configure system or anything for building
clearsilver, and its pretty much set up now to build in the neotonic
source tree. You'll probably have to edit rules.mk to change some
include/library paths if you are compiling it (in particular, you'll
almost certainly have to change PYTHON_INC in rules.mk)
Brandon
--
"The only thing nude playing cards are good for is playing solitaire."
-- Harry Anderson, PI 1/7/98
http://www.fiction.net/blong/
How do I retrieve values submitted from a multi-select box? For
example, if I have:
<select name=myselect size=5 multple>
<option value=foo>Foo</option>
<option value=bar>Bar</option>
<option value=biff>Biff</option>
</select>
When this comes back through a CGI, after selecting a two or more of
the choices, I only get one of the values.
This seems to be a problem in the standard Python cgi lib. Any plans
to correct the situation in ClearSilver?
...Paul
On 04/04/02 cryomax uttered the following other thing:
> How do I retrieve values submitted from a multi-select box? For
> example, if I have:
>
> <select name=myselect size=5 multple>
> <option value=foo>Foo</option>
> <option value=bar>Bar</option>
> <option value=biff>Biff</option>
> </select>
>
> When this comes back through a CGI, after selecting a two or more of
> the choices, I only get one of the values.
>
> This seems to be a problem in the standard Python cgi lib. Any plans
> to correct the situation in ClearSilver?
This works the same way it did in CS/HDF, basically multiple values of
the same name from the form go into the HDF like so:
1 value => Query.myselect = value
2 values => Query.myselect = second value
Query.myselect.0 = first value
Query.myselect.1 = second value
3 values => Query.myselect = third value
Query.myselect.0 = first value
Query.myselect.1 = second value
Query.myselect.2 = third value
From python, one could do something like this:
def allQuery (hdf, s):
l = []
if hdf.getValue ("Query.%s.0" % s, ""):
obj = hdf.getChild ("Query.%s" % s)
while obj:
l.append(obj.value())
obj = obj.next()
else:
t = hdf.getValue ("Query.%s" % s, "")
if t: l.append(t)
return l
Its definitely annoying in CS, where you have to do something like:
<?cs if:Query.myselect.0 ?>
myselect =
<?cs set:first = #1 ?>
<?cs each:myselect = Query.myselect ?>
<?cs if:#first ?><?cs set:first = #0 ?><?cs else ?>, <?cs /if ?>
<?cs var:myselect ?>
<?cs /each ?>
<?cs else ?>
myselect = <?cs var:Query.myselect ?>
<?cs /if ?>
Brandon
--
"religion is the ultimate legacy system." -- Giles Bowkett
http://www.fiction.net/blong/
Yeah, I know, there wasn't an announcement for v0.5, it was out last
week, but some bugs found shortly after it was released made for some
quick fixes...
Aside from the assorted bugfixes, we have the following new features:
- Function to sort HDF at a given level in the tree.
- Support for HTTP PUT (works a lot like POST File Upload, except you
call cgi_filehandle() with NULL instead of a query name).
- search/in/index functions for ULIST
- support for parenthesis in CS expressions
- support for bracket array access in CS expressions
this means that foo["bar"] is equal to foo.bar, and
if bar = test, then foo[bar] = foo.test
- some convenience functions for NEOERRs, so you can now get just
the error string instead of the entire traceback. You can also
match an error without clearing it (so you can re-throw it).
- support for alt CS command. This command allows you to follow an
alternative path if a given expression doesn't have a value.
<?cs alt:MyVar ?> I don't know anything <?cs /alt ?> will display
the value of MyVar if it exists, or display the text if not.
- support for loop CS command. This command allows you to walk
through a sequential list of values without actually writing all of
them into your HDF. The syntax is currently quite ugly and subject
to change when I think of a better one, but:
<?cs loop:x=#1,#100,#3 ?>
<?cs var:x ?>
<?cs /loop ?>
This will display the values 1 to 100 (inclusive) by 3.
- ne_listdir() and some other functions that will load the list of
files for a directory into a ULIST
- An image viewer is now included as an example. It's called imd, and
you can see it in action at http://www.fiction.net/~blong/Images/
(login: friend pass: yakko)
- HDF now supports attributes on a per node basis. This means that
you can now have out of band data in your HDF dataset. For example:
Images {
top {
height [type=num] = 512
width [type=num] = 512
url [url] = /img/loc/top.gif
alt [type=string, lang=en, desc="The end of \n the world?"] = ClearSilver
Rocks!
}
}
Currently, attributes are only accessible from code as I'm still
considering what the possible CS syntax should be. Yes, this brings
HDF a step closer to XML, but its still simpler in the base case...
and at some point in the future I might add xml export/import
functions for HDF...
Also, be sure to check out the new improved ClearSilver website at
http://www.clearsilver.net/
As always, we invite people to participate, share examples, suggest
examples, write documentation, write code...
Brandon
--
"Atheism requires too much faith." -- Andrew C. Bulhak
http://www.fiction.net/blong/
Brandon,
fyi, when invoking the cgi_* functions from within a C++ program, I
had to wrap cgi.h with "extern "C" {}". Otherwise, things seem to work
well.
Mark
On 05/13/02 snoovler uttered the following other thing:
> Brandon,
>
> fyi, when invoking the cgi_* functions from within a C++ program, I
> had to wrap cgi.h with "extern "C" {}". Otherwise, things seem to work
> well.
Oops, we hadn't quite gotten to those yet... Dave was doing a bunch of
work in C++ and we'd fixed up all the headers for the util directory,
but not for the cs and cgi directories. It'll be in the next release.
Brandon
--
"The Creation of the Universe was made possible by a grant from Texas
Instruments." -- Credits, The Creation of the Universe (PBS)
http://www.fiction.net/blong/
Are there any tricks to using the python module? So far I've
discovered that you have to import neo_cgi and then you can import
the hidden neo_util and neo_cs modules.
I'm working on a mod_python handler that so far looks a lot like
static.py in terms of functionality. So far, pretty cool. If I
end up with something generic enough to hang around as a sample
script, I'll send it on up.
--
David Terrell | "I'd like to go out on a limb and say that
dbt@... | Ashcroft is probably not the most evil human
Nebcorp Prime Minister | on earth, though I can't think of any
http://wwn.nebcorp.com | counterexamples." - Tim Skirvin
On 06/17/02 David Terrell uttered the following other thing:
> Are there any tricks to using the python module? So far I've
> discovered that you have to import neo_cgi and then you can import
> the hidden neo_util and neo_cs modules.
>
> I'm working on a mod_python handler that so far looks a lot like
> static.py in terms of functionality. So far, pretty cool. If I
> end up with something generic enough to hang around as a sample
> script, I'll send it on up.
No, that's the main trickiness. The only other thing that might be
problematic would be to do something like:
cgi = neo_cgi.CGI()
cgi.hdf.setValue("Query.foo", "5")
h_obj = cgi.hdf.getChild("Query")
cgi = None
h_obj.getValue("foo", "")
Currently, the code generates python HDF objects on the fly for each
node that python requests of the HDF tree, but it doesn't maintain the
references quite correctly (each node should have a reference to the top
of the HDF tree, and at the time there wasn't a way to get the top of
the HDF tree from any random node, I could fix this now but haven't
gotten around to it). The above could core-dump. In most CGI's, its
highly unlikely that you would do anything like the above, but just a
warning.
Attached is a base-CSPage class that we use, it provides a couple simple
items, including a Context class which you can override to have
different stdin/stdout (we use this for running scripts in a regression
environment, for instance), an output() method (mostly to catch write
errors if the socket has closed), allQuery() which will return a list of
all of the query var values for when you are expecting possibly-multiple
input. By default, you would create a sub class like:
class MyPage(CSPage):
def setup(self):
# always run this
def Action_Save(self):
# this runs if there is a Query.Action.Save hdf value
# do work
self.redirectUri("/back")
def display(self):
# this runs if there is no action
And then you would start your CGI with:
def main(context):
MyPage(context, pagename="my_page").start()
if __name__ == "__main__":
main(Context())
We typically use PyApache instead, but that's more because of
familiarity, and I had problems getting all of them to work with python
2.1, but that was due to a bug in python (see
http://www.fiction.net/blong/pyapache.html for more information).
Brandon
--
"Power Ennobles. Absolute power ennobles absolutely."
-- Harlan Ellison
http://www.fiction.net/blong/
#!/neo/opt/bin/python
import neo_cgi
import sys, os, string
import time
from log import *
# errors thrown...
NoPageName = "NoPageName"
NoDisplayMethod = "NoDisplayMethod"
# errors signaled back to here
Redirected = "Redirected"
DisplayDone = "DisplayDone"
class Context:
def __init__ (self):
self.argv = sys.argv
self.stdin = sys.stdin
self.stdout = sys.stdout
self.stderr = sys.stderr
self.environ = os.environ
class CSPage:
def __init__(self, context, pagename=0,readDefaultHDF=1,israwpage=0):
if pagename == 0:
raise NoPageName, "missing pagename"
self.pagename = pagename
self.readDefaultHDF = readDefaultHDF
self._israwpage = israwpage
self.context = context
self.page_start_time = time.time()
neo_cgi.cgiWrap(context.stdin, context.stdout, context.environ)
neo_cgi.IgnoreEmptyFormVars(1)
self.ncgi = neo_cgi.CGI()
self.ncgi.parse()
self._path_num = 0
domain = self.ncgi.hdf.getValue("CGI.ServerName","")
domain = self.ncgi.hdf.getValue("HTTP.Host", domain)
self.domain = domain
self.setPaths([self.ncgi.hdf.getValue("CGI.DocumentRoot","")])
self.subclassinit()
def subclassinit(self):
pass
def setPaths(self, paths):
for path in paths:
self.ncgi.hdf.setValue("hdf.loadpaths.%d" % self._path_num, path)
self._path_num = self._path_num + 1
def redirectUri(self,redirectTo):
ncgi = self.ncgi
if ncgi.hdf.getIntValue("Cookie.debug",0) == 1:
ncgi.hdf.setValue("CGI.REDIRECT_TO",redirectTo)
ncgi.display("dbg/redirect.cs")
print "<PRE>"
print neo_cgi.htmlEscape(ncgi.hdf.dump())
print "</PRE>"
raise DisplayDone
self.ncgi.redirectUri(redirectTo)
raise Redirected, "redirected To: %s" % redirectTo
## ----------------------------------
## methods to be overridden in subclass when necessary:
def setup(self):
pass
def display(self):
raise NoDisplayMethod, "no display method present in %s" % repr(self)
def main(self):
self.setup()
self.handle_actions()
self.display()
## ----------------------------------
def handle_actions(self):
hdf = self.ncgi.hdf
hdfobj = hdf.getObj("Query.Action")
if hdfobj:
firstchild = hdfobj.child()
if firstchild:
action = firstchild.name()
if firstchild.next():
raise "multiple actions present!!!"
method_name = "Action_%s" % action
method = getattr(self,method_name)
apply(method,[])
def start(self):
SHOULD_DISPLAY = 1
if self._israwpage:
SHOULD_DISPLAY = 0
ncgi = self.ncgi
if self.readDefaultHDF:
try:
if not self.pagename is None:
ncgi.hdf.readFile("%s.hdf" % self.pagename)
except:
log("Error reading HDF file: %s.hdf" % (self.pagename))
# call page main function!
try:
self.main()
except DisplayDone:
SHOULD_DISPLAY = 0
except Redirected:
# catch redirect exceptions
SHOULD_DISPLAY = 0
except:
SHOULD_DISPLAY = 0
import handle_error
handle_error.handleException("Display Failed!")
print "Content-Type: text/html\n\n"
# print the page
print "<H1> Error in Page </H1>"
print "A copy of this error report has been submitted to the
developers. "
print "The details of the error report are below."
print "<PRE>"
print handle_error.exceptionString()
print "</PRE>\n"
# print debug info always on page error...
print "<HR>\n"
print "<PRE>"
print neo_cgi.htmlEscape(ncgi.hdf.dump())
print "</PRE>"
etime = time.time() - self.page_start_time
ncgi.hdf.setValue("CGI.debug.execute_time","%f" % (etime))
if SHOULD_DISPLAY and self.pagename:
debug_output =
ncgi.hdf.getIntValue("page.debug",ncgi.hdf.getIntValue("Cookie.debug",0))
if not debug_output:
ncgi.hdf.setValue("Config.CompressionEnabled","1")
# default display
template_name = ncgi.hdf.getValue("Content","%s.cs" % self.pagename)
# ncgi.hdf.setValue ("cgiout.charset", "utf-8");
ncgi.display(template_name)
# debug output
if debug_output:
print "<HR>\n"
print "Execution Time: %5.3f<BR><HR>" % (etime)
print "<PRE>"
print neo_cgi.htmlEscape(ncgi.hdf.dump())
print "</PRE>"
# ncgi.hdf.setValue("hdf.DEBUG",ncgi.hdf.dump())
# ncgi.display("debug.cs")
script_name = ncgi.hdf.getValue("CGI.ScriptName","")
if script_name:
script_name = string.split(script_name,"/")[-1]
log ("[%s] etime/dtime: %5.3f/%5.3f %s (%s)" % (self.domain, etime,
time.time() - etime - self.page_start_time, script_name, self.pagename))
# a protected output function to catch the output errors that occur when
# the server is either restarted or the user pushes the stop button on the
# browser
def output(self, str):
try:
self.context.stdout.write(str)
except IOError, reason:
log("IOError: %s" % (repr(reason)))
raise DisplayDone
def allQuery (self, s):
l = []
if self.ncgi.hdf.getValue ("Query.%s.0" % s, ""):
obj = self.ncgi.hdf.getChild ("Query.%s" % s)
while obj:
l.append(obj.value())
obj = obj.next()
else:
t = self.ncgi.hdf.getValue ("Query.%s" % s, "")
if t: l.append(t)
return l
Are there any restrictions on HDF node names? I'm able to set a node
with a name of Serial0/0 but I can't read that file back in:
>>> h = neo_util.HDF("")
>>> h.setValue("a.a/a","a")
>>> print h.writeString()
a {
a/a = a
}
>>> h.writeFile('/tmp/a')
>>> h.readFile('/tmp/a')
Traceback (most recent call last):
File "<stdin>", line 1, in ?
neo_util.ParseError: ParseError: [/tmp/a:2] Unable to parse line
--
David Terrell | "We must go forward, not backwards; upwards,
Nebcorp Prime Minister | not forwards; and always twirling, twirling,
dbt@... | twirling towards freedom!"
http://wwn.nebcorp.com/ | - The Simpsons