PythonLibraries Product
I'm thinking seriously about writing a Product to provide collections of Python functions defined by a single source text -- PythonLibraries. This would *not* be the same as Zope 3's persistent modules, although it would provide some of the same benefits. Here's the README.txt: Python Libraries The Python Libraries Product provides support for collections of restricted Python code. A Python Library is similar to a Folder full of Python-based Scripts, except that the functions in the Library are more like ordinary Python functions than Scripts, and a single persistent global variable namespace is shared among the functions in the Library. A Library obeys the same security restrictions, and has access to the same set of modules, as a Script. Libraries are *not* very much like Python modules or packages, except in that they both are convenient places to keep groups of functions. You cannot import a Library, define Python classes in one, or use the 'print' statement outside of function definitions. When changes to a Library are saved, its source code is executed. This process, known as "Library initialization", also occurs whenever the Library is loaded into memory from the ZODB. Global variables defined during initialization are divided into three groups, depending on the kind of value to which they refer: functions, simple data, and modules. There is one additional global variable, named 'Library', that is defined both during initialization and function evaluation, and which cannot be deleted or rebound. It refers to the Library object itself. Functions are made available to other Zope code as Library attributes. A function 'do_it' contained in the Library located at '/foo/myLib' may be called by a TALES expression such as "here/foo/myLib/do_it" or the Python expression "context.foo.myLib.do_it()". Function names that conflict with methods of the Library object are syntax errors. A Library's functions are not published by default, which means that they cannot be accessed by URL through ZPublisher. There is a Library method 'pl_publish()' that can be used to explicitly publish a function. Simple data includes Python built-in types such as numbers, strings, lists, and dictionaries. Variables with simple data are persistent, and their value is retained even when the Library is changed or reloaded, although the execution of the code can remove or overwrite them. These variables are not visible to other Zope objects. Modules are imported Python modules. These are not visible to other Zope objects, and do not persist -- they are re-imported each time the Library is changed or loaded. Unlike Scripts, Libraries do not have a Bindings tab. In order to access context objects, such as the Library's container, the root Zope object, or the authenticated user, functions must use a global variable created by a call to the 'pl_bind()' method of the Library. This method takes two arguments: a variable name, and a TALES expression. The TALES expression will be evaluated the first time that the variable is used in each call to a Library function, and the value will be cached for subsequent uses within the same call. For example, examine the following snippet of Library code: Library.pl_bind('user', 'user') Library.pl_bind('thingy', 'here/thingy | nothing') def f(): if user.has_role('Authenticated') and thingy is not None: print user, thingy return printed When the function 'f' is called, the 'user' and 'thingy' variables will be evaluated in its first line, and the values will be reused in the second line, if the condition is true. If 'f' is called again, in the same request or not, the bound variables will be re-evaluated. Bound variables are not available during Library initialization, since they are unlikely to evaluate meaningfully when a Library is loaded from the ZODB.
Evan Simpson wrote at 2003-9-8 14:43 -0500:
I'm thinking seriously about writing a Product to provide collections of Python functions defined by a single source text -- PythonLibraries.
+ 1
... The Python Libraries Product provides support for collections of restricted Python code. A Python Library is similar to a Folder full of Python-based Scripts, except that the functions in the Library are more like ordinary Python functions than Scripts, and a single persistent global variable namespace is shared among the functions in the Library.
Hopefully, these variables are used only for customization. I have been hit in the past, when I used compiled regular expressions as default parameters to an "ExternalMethod". Apparently, because some objects (such as compiled regular expressions) cannot be stored (worse loaded) persistently. Dieter
Evan Simpson wrote:
I'm thinking seriously about writing a Product to provide collections of Python functions defined by a single source text -- PythonLibraries. This would *not* be the same as Zope 3's persistent modules, although it would provide some of the same benefits.
Here's the README.txt:
Python Libraries
The Python Libraries Product provides support for collections of restricted Python code. A Python Library is similar to a Folder full of Python-based Scripts, except that the functions in the Library are more like ordinary Python functions than Scripts, and a single persistent global variable namespace is shared among the functions in the Library.
So AFAICT it's a convenience which allows you (a) to keep related functions together; and (b) to store local variables in a convenient place. It definitely sounds useful but also a lot of work for something it's possible to manage without quite easily at the moment..? Could you provide a brief summary of why this is better than a folder of python scripts? Perhaps a use case which illustrates the problems of the current way of doing things? seb
Seb Bacon wrote:
So AFAICT it's a convenience which allows you (a) to keep related functions together; and (b) to store local variables in a convenient place. It definitely sounds useful but also a lot of work for something it's possible to manage without quite easily at the moment..?
Could you provide a brief summary of why this is better than a folder of python scripts? Perhaps a use case which illustrates the problems of the current way of doing things?
It isn't *better* than a Folder of Scripts, it's *different* :-) I have two weak use-cases, a longstanding "I'm going to write that some day" itch, and some aesthetic arguments. One of the more frequently stated complaints about ZPTs is that to properly remove non-presentation logic and ugly little Python expressions from a template, you either need a pile of little Scripts, or a single "controller" Script that precalculates everything and passes it to the template. I've settled, fairly happily, on the second solution. Both of these solutions suffer from the "two or more objects to accomplish one task" management problem. I usually combine the objects in a dedicated Folder, which is still a bit awkward, and doesn't solve everything. One drawback is that the individual components are all published, despite the fact that I only intend one of them to be web-addressable. It would be very handy to attach the Scripts directly to the template, but the straightforward way of doing that means making the template a container, and opens a whole can of worms. Instead, what if templates had a Library tab, and it worked with External Editor? It would actually be easier to *just* write this, and not have independent Library objects, but generalizing this capability feels right to me. From an aesthetic viewpoint, a Library looks and works more like regular Python than a Script. Even though a Library is not a "*.py" file, it uses a subset of that syntax, so dedicated editor modes will like it better. Multi-line triple-quoted strings will not get extra spaces added to them. The "##" header hack won't be necessary, so line numbers in External Editor will match error message line numbers. On the other hand, Libraries don't support 'traverse_subpath', require an extra path step to address, and don't allow permission and proxy settings at individual function granularity. Cheers, Evan @ 4-am
----- Original Message ----- From: "Evan Simpson" <evan@4-am.com>
Both of these solutions suffer from the "two or more objects to accomplish one task" management problem. I usually combine the objects in a dedicated Folder, which is still a bit awkward, and doesn't solve everything. One drawback is that the individual components are all published, despite the fact that I only intend one of them to be web-addressable. ...znip... On the other hand, Libraries don't support 'traverse_subpath', require an extra path step to address, and don't allow permission and proxy settings at individual function granularity.
hm... I have made similar observations, and not only with Scripts (Python)... one idea I had, though I do not know if it is possible to implement, is to create a new kind of container that only exposes/publishes objects with a certain permission. Is it possible w/o patching the way zpublisher works? /dario - -------------------------------------------------------------------- Dario Lopez-Kästen, IT Systems & Services Chalmers University of Tech.
What's the latest word on mixing new-style classes and Persistence? I'm finding type subclassing to be extremely useful in PythonLibraries, but so far I'm only using them for non-persistent objects. For part of what I'm doing, though, it would be nice to be able to chuck the old PersistentList and PersistentMap, and replace them with actual list and map subclasses. As far as I know, trying to mix them *directly* is a no-no, but is there any problem with making a new-style class instance an attribute of a Persistent ExtensionClass? Cheers, Evan @ 4-am
participants (4)
-
Dario Lopez-Kästen -
Dieter Maurer -
Evan Simpson -
Seb Bacon