Getting at third-party modules in dtml?
I've got an ancient DTMLFile UI that I need to add a feature to, and I really don't want to have to rewrite it all in ZPT today... I'd love to, just don't have time now... and there's something I just can't figure out: Say I have a function that I want to make callable in my UI. It needs to be globally available, i.e. it needs to be callable *without* having an instance of my product yet. (This has to do with listing information about all acquirable instances of the product, so the user can choose from those available.) I can make the security declarations fine, e.g. ModuleSecurityInfo('Products.MyProduct.utils').declarePublic('getBaz') .... and then I can import and use getBaz() in python Scripts, and I can use it in ZPT too by doing something like python:modules['Products.MyProduct.utils'].doBaz() .... but how the heck do I do that in DTML? There's no "modules" namespace in DTML anywhere that I can find... I guess I could wrap the function in an external method. But since this UI is for a product I maintain, I REALLY do not want to have to add goofy stuff like that to the installation instructions and make my users clutter their ZODB with external methods. That's way too fragile and messy. Thanks, PW
Hi!
Say I have a function that I want to make callable in my UI. It needs to be globally available, i.e. it needs to be callable *without* having an instance of my product yet. (This has to do with listing information about all acquirable instances of the product, so the user can choose from those available.)
In a Product's __init__.py: def theSecret(self): return "A hobbit!" methods = { 'whatIsFrodo': theSecret } Save that i.E. in MyInstance/Products/MyFancy/__init__.py, restart Zope And than <dtml-var whatIsFrodo>. Lg, AXEL. -- Gentoo? Debian? RedHat? SuSE? *BSD? Stop the distri-war, make little user!
Axel Straschil wrote at 2005-9-20 04:07 +0000:
Hi!
Say I have a function that I want to make callable in my UI. It needs to be globally available, i.e. it needs to be callable *without* having an instance of my product yet. (This has to do with listing information about all acquirable instances of the product, so the user can choose from those available.)
In a Product's __init__.py:
def theSecret(self): return "A hobbit!"
methods = { 'whatIsFrodo': theSecret }
Save that i.E. in MyInstance/Products/MyFancy/__init__.py, restart Zope And than <dtml-var whatIsFrodo>.
And if you do not want to pollute the "Folder" (class) namespace, you can define it as a "constructors" (to "registerClass") and use it via "<objectManager>.manage_addProduct[<your product>].constructor(...)" -- Dieter
Axel Straschil wrote at 2005-9-20 04:07 +0000:
Hi!
Say I have a function that I want to make callable in my UI. It needs to be globally available, i.e. it needs to be callable *without* having an instance of my product yet. (This has to do with listing information about all acquirable instances of the product, so the user can choose from those available.)
In a Product's __init__.py:
def theSecret(self): return "A hobbit!"
methods = { 'whatIsFrodo': theSecret }
Save that i.E. in MyInstance/Products/MyFancy/__init__.py, restart Zope And than <dtml-var whatIsFrodo>.
And if you do not want to pollute the "Folder" (class) namespace, you can define it as a "constructors" (to "registerClass") and use it via "<objectManager>.manage_addProduct[<your product>].constructor(...)"
Very educational, thanks for the replies! I didn't understand Dieter's comment until I tried Axel's suggestion. It apparently works by adding a "theSecret" method to the Folder class and derived objects including the root App object. i.e. you can visit http://localhost:8080/theSecret and (if the method has a docstring) you'll see 'A hobbit!'. I have to say that's pretty darn obscure behavior. It's the antithesis of self-documenting, and I've never seen it used before. Is this documented somewhere? I see one example of it in OFS/tests/testProductInit.py... Also, AFAICT there's no way to declare security on that function. (which is OK in this case since I wanted something 'public' anyway). Anyway, in the end, I followed neither suggestion, since I don't want either to "pollute the Folder (class) namespace", nor do I want to register a constructor that isn't really a constructor ... the former would be obnoxious to users who install my product, the latter seems likely to confuse whoever has to maintain this code after me! Instead, I bit the bullet and rewrote the offending part of the UI as a PageTemplateFile; it wasn't much work after all and I can leave the rest as DTML for now. I like this solution because client code (the template) has to explicitly look up the function via the 'modules' mapping. -PW
Hi!
before. Is this documented somewhere?
Never seen a Documentation for that, everything in Zope that is not done "Trough the Web" is "Use the source, Luke" documented. I.E., this thread is worth a Documentation, but who will write it down ... ;-) Lg, AXEL. -- Gentoo? Debian? RedHat? SuSE? *BSD? Stop the distri-war, make little user!
Paul Winkler wrote at 2005-9-20 14:02 -0500:
... I have to say that's pretty darn obscure behavior. It's the antithesis of self-documenting, and I've never seen it used before. Is this documented somewhere?
It is the ancient product initialization -- used by the first products: e.g. DTML Document and Method and ZSQL Method. It was superceeded by product local constructors -- for the obvious reason to avoid name clashes.
... Also, AFAICT there's no way to declare security on that function. (which is OK in this case since I wanted something 'public' anyway).
It is -- if you know and use the implementation details of Zope's security subsystem: To protect a method "m" with permission "p", you assign "PermissionRole(p)" to "m__roles__". Not that a maintainer (without the same detailed knowledge about the security subsystem) would understand such a "method" -- unless you had put in an explaining comment... -- Dieter
participants (3)
-
Axel Straschil -
Dieter Maurer -
Paul Winkler