I'm a newbie zopista, and python for that matter... In brief: I get a NameError when invoking "filter(...)" from DTML. I thought this was a built-in python method, so I'm a bit puzzled. In detail: 1) I want to display a dtml-tree of my folder hierarchy, but I want to exclude all Zwiki discussion groups. 2) In my index_html for the top level folder, I have the following: <dtml-tree Outline leaves=dtcTemplate > <SPAN CLASS="tree"> <dtml-if tree-item-expanded> <dtml-if expr="objectValues(['Folder'])"> <IMG SRC="<dtml-var BASE2>/Outline/OpenBook.gif" ALIGN="TOP" BORDER="0"> </dtml-if> <STRONG> <I><dtml-var title></I> </STRONG> <dtml-else> <dtml-if expr="objectValues(['Folder'])"> <IMG SRC="<dtml-var BASE2>/Outline/ClosedBook.gif" ALIGN="TOP" BORDER="0"> </dtml-if> <dtml-var title> </dtml-if> </SPAN> </dtml-tree> which is cribbed straight from QuickStart. 3) I only want to ignore Zwiki groups, but they are out-of-the-box folders, so I can't filter on meta-class. 4) My approach is just to add a property to the Zwiki folder ('blockTreeBranching') 5) In the dtml-tree tag, I change it to: <dtml-tree Technical leaves=dtcTemplate branches_expr="filter( lambda f: not f.hasProperty('blockTreeBranching', false), objectValues(['Folder']) )"> which, all things equal, should DoTheRightThang. 6) The code can be published, but when I view it, it spits out a NameError, choking on "filter". Argh. Ideas gratefully recieved... Nick HyperSpace Ltd,Birmingham Research Park, Edgbaston, UK, B15 2SQ (e) hyperspace@btinternet.com (t) +44 (0)121 414 7019
In brief: I get a NameError when invoking "filter(...)" from DTML. I thought this was a built-in python method, so I'm a bit puzzled.
Certain built-ins are not available in dtml for security and other reasons, filter and lambda are among them. As far as I know, you'll need to use an external method to do this or think of another way to do it in dtml. --jfarr "Perl is worse than Python because people wanted it worse." Larry Wall, 14 Oct 1998
On Fri, May 26, 2000 at 03:05:14PM -0700, Jonothan Farr wrote:
In brief: I get a NameError when invoking "filter(...)" from DTML. I thought this was a built-in python method, so I'm a bit puzzled.
Certain built-ins are not available in dtml for security and other reasons, filter and lambda are among them. As far as I know, you'll need to use an external method to do this or think of another way to do it in dtml.
One big question is: what's wrong with filter, map and lambda? They can make a lot of code a lot simpler, specially for people who have a background in functional programming. IIRC there is nothing wrong with them - only that all builtins were disabled and some specific few were re-enabled, and then those three were overlooked. Count one vote for getting them back (_.lambda, _.filter, _.map is fine enough, of course). []s, |alo +---- -- Hack and Roll ( http://www.hackandroll.org ) News for, uh, whatever it is that we are. http://zope.gf.com.br/lalo mailto:lalo@hackandroll.org pgp key: http://zope.gf.com.br/lalo/pessoal/pgp Brazil of Darkness (RPG) --- http://zope.gf.com.br/BroDar
On Mon, May 29, 2000 at 04:33:20PM -0300, Lalo Martins wrote:
One big question is: what's wrong with filter, map and lambda? They can make a lot of code a lot simpler, specially for people who have a background in functional programming.
IIRC there is nothing wrong with them - only that all builtins were disabled and some specific few were re-enabled, and then those three were overlooked.
Count one vote for getting them back (_.lambda, _.filter, _.map is fine enough, of course).
I can't comment with authority on why these methods are not accessible, but I imagine that they are banned because they'll probably let you lock up Zope in one way or another, creating a convenient denial-of-service attack. What I would like to say is that if your application needs lambda, filter or map, your code is getting bejond report or presentation generation (for which DTML is intended) and in the realm of data manipulation and business rules. In this case your code would be much better placed in some form of Method object, be that an External, Python, or when ready, Perl Method, or even as a disk based Product. -- Martijn Pieters | Software Engineer mailto:mj@digicool.com | Digital Creations http://www.digicool.com/ | Creators of Zope http://www.zope.org/ | The Open Source Web Application Server ---------------------------------------------
On Mon, May 29, 2000 at 09:40:59PM +0200, Martijn Pieters wrote:
I can't comment with authority on why these methods are not accessible, but I imagine that they are banned because they'll probably let you lock up Zope in one way or another, creating a convenient denial-of-service attack.
If someone can edit arbitrary DTML, there are already easier ways to cause infinite loops. And these loops don't lock up Zope, they only eventually raise an exception (granted, consuming lots of resources in the proccess).
What I would like to say is that if your application needs lambda, filter or map, your code is getting bejond report or presentation generation (for which DTML is intended) and in the realm of data manipulation and business rules. In this case your code would be much better placed in some form of Method object, be that an External, Python, or when ready, Perl Method, or even as a disk based Product.
1: This is simply not true, and a very poor excuse for handicapping the language. A common example is: <dtml-in "_.map (lambda item: Catalog.getobject (item.data_record_id_), Catalog (REQUEST)"> I know fetching the actual records from a ZCatalog introduces a performance penalty, but sometimes it's necessary; there are times you need to be absolutely sure everything is pushed on the namespace, including user-defined properties and sub-objects. This is the case in Hack&Roll, and I have to use a very ugly Python Method there (and as PythonMethods don't have map either, I have to build a list from scratch using for, which introduces additional penalties as I'm basically bypassing Python's optimizations). And _.filter can be a mini-catalog: <dtml-in "_.filter (lambda item: AUTHENTICATED_USER.has_permission ('some_permission', item), objectValues (['Folder'])"> 2: If I should be using a Python Method, then Python Methods should have these forms, and they don't. 3: In short, these excuses are just the fallback (or should I say Acquired?) excuses used mostly by people who don't know how to use these very cool features of Python. []s, |alo +---- -- Hack and Roll ( http://www.hackandroll.org ) News for, uh, whatever it is that we are. http://zope.gf.com.br/lalo mailto:lalo@hackandroll.org pgp key: http://zope.gf.com.br/lalo/pessoal/pgp Brazil of Darkness (RPG) --- http://zope.gf.com.br/BroDar
What I would like to say is that if your application needs lambda, filter or map, your code is getting bejond report or presentation generation (for which DTML is intended) and in the realm of data manipulation and business rules. In this case your code would be much better placed in some form of Method object, be that an External, Python, or when ready, Perl Method, or even as a disk based Product.
1: This is simply not true, and a very poor excuse for handicapping the language.
Nope. Lamba, filter, reduce, and map should IMHO not be part of DTML. Actually, exprs probably shouldn't be in there in the first place. People are trying to use DTML as a way to process non-UI elements. This is a slippery slope, and leads to something like PHP or ASP. My opinion is this: Generate and format your HTML with DTML, and do everything else in Python. This gives you the added benefit that you can change the return values of functions by changing the Python code without having to muck with DTML, which is painful any way you look at it. People are right when they say DTML is beginning to get worse than Perl, and IMHO, adding these functions could make it even worse than it is now. This sort of processing was not meant to happen in an expr under Zope. Python lets you do it, but it's sort of hard for somebody else to understand after you've completed it, even if they know Python well. Functional constructs are handy, but not the most clear thing on the planet.
A common example is:
<dtml-in "_.map (lambda item: Catalog.getobject (item.data_record_id_), Catalog (REQUEST)">
How could someone understand this when you're finished with it? I looked at it three times before figuring out what you were trying to do. What if you didn't write it and you needed to answer somebody asking a question about it on this mailing list? Isn't this much more understandable as an external method explicitly? def return_cataloged_objects(self): obs = [] catalog = self.Catalog request = self.REQUEST for r in catalog(request): d_rid = r.data_record_id_ ob = catalog.getobject(d_rid) obs.append(ob) return obs then: <dtml-in return_cataloged_objects> ... </dtml-in> It *might* be slighly slower, but someone maintaining your code will eventually thank you for this. Eventually it will cost you less money somewhere that you might be able to buy a faster server with.
I know fetching the actual records from a ZCatalog introduces a performance penalty, but sometimes it's necessary; there are times you need to be absolutely sure everything is pushed on the namespace, including user-defined properties and sub-objects. This is the case in Hack&Roll, and I have to use a very ugly Python Method there (and as PythonMethods don't have map either, I have to build a list from scratch using for, which introduces additional penalties as I'm basically bypassing Python's optimizations).
Sometimes. Sometimes not. Read http://www.python.org/doc/essays/list2str.html . As I understand it, by using expr syntax to begin with, you're defeating some of Zope's caching mechanisms, actually slowing things down in reality.
2: If I should be using a Python Method, then Python Methods should have these forms, and they don't.
Maybe they should... it would be nice. I'm not sure why they're not in Python Methods, other than Evan tried to make the security inherent in Python methods as close to DTML as he could. I use map a lot. I don't use lambda unless I really, really have to. Reduce and filter.. eh. I dunno. They're sort of on the periphery of usefulness.
3: In short, these excuses are just the fallback (or should I say Acquired?) excuses used mostly by people who don't know how to use these very cool features of Python.
I would hardly say Martijn is one of those. :-)
On Mon, May 29, 2000 at 10:58:54PM -0400, Chris McDonough wrote:
<dtml-in "_.map (lambda item: Catalog.getobject (item.data_record_id_), Catalog (REQUEST)">
How could someone understand this when you're finished with it?
Perfectly clearly for anyone used to functional programming; I'd even say, clear on first sight. A lot easier to understand and maintain than a separate method.
Isn't this much more understandable as an external method explicitly?
No. And external methods should definitely be phased out as much as possible, they defeat one of the major advantages of Zope (everything is manageable trought the web).
def return_cataloged_objects(self): obs = [] catalog = self.Catalog request = self.REQUEST for r in catalog(request): d_rid = r.data_record_id_ ob = catalog.getobject(d_rid) obs.append(ob)
return obs
Your method, in particular, is worse to understand than my one-liner, specially for anyone who uses functional programming seriously; but even other people would have to reason for a few minutes to understand what you're appending to that poor list and why. Reading functional programming requires a paradigm shift as much as reading OOP; but if you can handle it, it's definitly worth your time.
Maybe they should... it would be nice. I'm not sure why they're not in Python Methods, other than Evan tried to make the security inherent in Python methods as close to DTML as he could. I use map a lot. I don't use lambda unless I really, really have to. Reduce and filter.. eh. I dunno. They're sort of on the periphery of usefulness.
I respect the fact that you have your opinion where DTML is going and where it should go and where it shouldn't. But I don't think it is an excuse to cripple it. It is, instead, your opinion, as much as mine is mine. Yes, expressions make DTML less clear and walk around caching. No, they shouldn't be banned. They're useful. Ban them and all you get is either a code fork or a considerable number of lost users. You compare these to ASP, PHP or Perl. I compare them to __getattr__, __getitem__, __call__ and others on Python, and to operator overloading in C++. Think whatever you want. []s, |alo +---- -- Hack and Roll ( http://www.hackandroll.org ) News for, uh, whatever it is that we are. http://zope.gf.com.br/lalo mailto:lalo@hackandroll.org pgp key: http://zope.gf.com.br/lalo/pessoal/pgp Brazil of Darkness (RPG) --- http://zope.gf.com.br/BroDar
Lalo Martins wrote:
How could someone understand this when you're finished with it?
Perfectly clearly for anyone used to functional programming; I'd even say, clear on first sight. A lot easier to understand and maintain than a separate method.
OK, I give. I think this would be fine in a Python (or external) method. But I don't share your opinion that it should be exposed in DTML.
Isn't this much more understandable as an external method explicitly?
No. And external methods should definitely be phased out as much as possible, they defeat one of the major advantages of Zope (everything is manageable trought the web).
Agreed on the point about external methods. Python methods should succeed them. And if they do succeed them, I would like to see the functional built-ins exposed. It would be a shame to not have them if their use doesn't impact security.
Your method, in particular, is worse to understand than my one-liner, specially for anyone who uses functional programming seriously; but even other people would have to reason for a few minutes to understand what you're appending to that poor list and why.
I can see that argument... it depends on the reader, I suppose. I wouldn't complain much actually if the Python code had functional stuff in it. It's having it in DTML that bugs me, for reasons that have to do with separating HTML-like stuff from the stuff that actually runs the site under the hood.
Maybe they should... it would be nice. I'm not sure why they're not in Python Methods, other than Evan tried to make the security inherent in Python methods as close to DTML as he could. I use map a lot. I don't use lambda unless I really, really have to. Reduce and filter.. eh. I dunno. They're sort of on the periphery of usefulness.
I respect the fact that you have your opinion where DTML is going and where it should go and where it shouldn't. But I don't think it is an excuse to cripple it. It is, instead, your opinion, as much as mine is mine.
Yes, expressions make DTML less clear and walk around caching.
No, they shouldn't be banned. They're useful. Ban them and all you get is either a code fork or a considerable number of lost users.
I didn't say that we should ban them, I said they shouldn't have been introduced in the first place. We can't ban them now, we know that.
You compare these to ASP, PHP or Perl. I compare them to __getattr__, __getitem__, __call__ and others on Python, and to operator overloading in C++.
I compare them to ASP and PHP (not perl.. maybe embperl or PerlScript, but not perl), because these are languages that encourage the use of so-called "business logic" inside HTML, along with so-called "presentation logic". Whatever you name them, I like to keep them as separate as possible so designers don't shirk in fear or mess things up when they need to navigate around hairy constructs in code. I've found that separating them also lets you shift UI elements more easily. It's clear that you don't share my opinion, nor do the other 99 million people who use ASP or PHP. But I'm on the more moderate side of things, believe it or not...you should really talk to some other folks here, you'd argue for hours. :-)
----- Original Message ----- From: "Lalo Martins" <lalo@hackandroll.org> To: <zope@zope.org> Sent: Monday, May 29, 2000 11:40 PM Subject: Re: [Zope] Use of lambda expression in DTML
On Mon, May 29, 2000 at 10:58:54PM -0400, Chris McDonough wrote:
<dtml-in "_.map (lambda item: Catalog.getobject
(item.data_record_id_),
Catalog (REQUEST)">
How could someone understand this when you're finished with it?
Perfectly clearly for anyone used to functional programming; I'd even say, clear on first sight. A lot easier to understand and maintain than a separate method.
Assuming I'm reading this correctly, I think I'd probably express this as: <dtml-in "Catalog(REQUEST)"> <dtml-with "Catalog.getobject(data_record_id_)"> ...foo... </dtml-with> </dtml-in> BTW, I agree that exprs should be a part of DTML. You don't want to put significant program logic in DTML, but there are many places in which exprs are useful: Total: <dtml-var "subtotal + shipping"> I'll grant that you can set up all of the variables you need via a PythonMethod beforehand, but things like this can be nice and convenient... Any power that can be given to PythonMethods securely is a boon. Kevin
I want to install Zope in multiple instances. Apparently if you provide a unique name and user names you can do this. My question is...., "How would you gain access to each individual Zope?" For instance, I would like "manager 1" to have access to "Zope 1" on port:8080. He will use Zope in tandem with his static web. I then want "manager 2" to have access to "Zope 2" in the same capacity as "manager 1." They will also use thier own separate product preferences. I want to set-up some fellow newbie types to share the Zope Road to Enlightenment with. What I don't understand from the install.txt and the "how to" is just how each manager is going to access the correct Zope. They each have a static webspace via a web server on port:80. I am not concerned right now about .pcgi, frontend and backend servers, but separating and accessing two standard installs of Zope on an NT server. I am a bit embarrased asking this because I did have this scenario working via pcgi. I got distracted for a couple of weeks and cannot reproduce it. So I want to do it again with straight installs, then .pcgi and later fool around with employing Site Access. Hope I've provided enough info...and that the answer is not too time consuming to return. Thanks, hisnibs Virginia Web http://www.virginiaweb.com hisnibs@ihosts.net
I'd say the easiest way is to give them different ports: give zope1 port 8080 and zope2 port 9080 If you've installed the Zopes as NT services you need to change the parameters to the services in regedit: goto hkey_local_machine/currentcontrolset/services/zope2 and change/add a parameter to change the default port base. The parameter you want is -P (upper case P) if you change/add it so that you have -P 9000 on the second instance then that user would connect on port 9080 for http and 9021 for ftp. Some of the instructions may not be exactly right but this should give you enough info to get you started, :) hth Phil phil.harris@zope.co.uk ----- Original Message ----- From: "J. Michael Mc Kay" <admin@ihosts.net> To: <zope@zope.org> Sent: 30 May 2000 16:40 Subject: [Zope] Before I install zope
I want to install Zope in multiple instances. Apparently if you provide a unique name and user names you can do this. My question is...., "How would you gain access to each individual Zope?"
For instance, I would like "manager 1" to have access to "Zope 1" on port:8080. He will use Zope in tandem with his static web. I then want "manager 2" to have access to "Zope 2" in the same capacity as "manager 1." They will also use thier own separate product preferences.
I want to set-up some fellow newbie types to share the Zope Road to Enlightenment with.
What I don't understand from the install.txt and the "how to" is just how each manager is going to access the correct Zope. They each have a static webspace via a web server on port:80. I am not concerned right now about .pcgi, frontend and backend servers, but separating and accessing two standard installs of Zope on an NT server.
I am a bit embarrased asking this because I did have this scenario working via pcgi. I got distracted for a couple of weeks and cannot reproduce it. So I want to do it again with straight installs, then .pcgi and later fool around with employing Site Access.
Hope I've provided enough info...and that the answer is not too time consuming to return.
Thanks,
hisnibs
Virginia Web http://www.virginiaweb.com hisnibs@ihosts.net
_______________________________________________ Zope maillist - Zope@zope.org http://lists.zope.org/mailman/listinfo/zope ** No cross posts or HTML encoding! ** (Related lists - http://lists.zope.org/mailman/listinfo/zope-announce http://lists.zope.org/mailman/listinfo/zope-dev )
In brief: I get a NameError when invoking "filter(...)" from DTML. I thought this was a built-in python method, so I'm a bit puzzled.
Python's ideas of 'built-in' is simply any method in the module stored in the global variable called __builtins__. Any code executed with a non-standard global variable space may or may not have the same set of builtins as normal Python code. Unfortunately Zope does not expose all of the 'builtin' python methods to DMTL expressions. Some obviously need to be cut out (such as 'open') for security reasons, but the reasons why others were dropped are less obvious. If you really need any of the missing builtins back in you have a couple of choices. Both require you have full access to your Zope system. If you want the function available throughout your Zope system simply edit DocumentTemplate\DT_Util.py. Look for the list beginning 'None', 'abs', 'chr' and simply add 'filter' into the list. Alternatively if you dont want to patch Zope directly, create an external python method that exposes filter.
5) In the dtml-tree tag, I change it to:
<dtml-tree Technical leaves=dtcTemplate branches_expr="filter( lambda f: not f.hasProperty('blockTreeBranching', false), objectValues(['Folder']) )">
which, all things equal, should DoTheRightThang.
Even if you make the filter function visible as described above, this still won't quite work. For example the method 'objectValues' is not in scope within the function. The way around this is to pass in an extra parameter _vars. Try (untested): branches_expr="filter( lambda f, _vars=_vars: not f.hasProperty('blockTreeBranching', 0), objectValues(['Folder']) )"> and it might work. Alternatively use something like a PythonMethod, or even a DTML method and simply write the filter loop out in full using 'for' or 'dtml- in'. -- Duncan Booth duncan@dales.rmplc.co.uk int month(char *p){return(124864/((p[0]+p[1]-p[2]&0x1f)+1)%12)["\5\x8\3" "\6\7\xb\1\x9\xa\2\0\4"];} // Who said my code was obscure? http://dales.rmplc.co.uk/Duncan
participants (9)
-
Chris McDonough -
Duncan Booth -
J. Michael Mc Kay -
Jonothan Farr -
Kevin Dangoor -
Lalo Martins -
Martijn Pieters -
Nick Drew -
Phil Harris