Python Base Classes, ZObjectManager, and Subobjects
I'm transitioning a product from pure ZClasses to a hybrid product python base classes and ZClasses. So this is my first time working with python products. I'm trying to setup a python base class to provide a central place to subclass ZObjectManager and CatalogAware that I can rebase later without the ZClass hassle. But when I try to create a ZClass in the product and subclass to one of my python base classes, I don't get the subobjects tab in my ZClass. Clearly I'm missing somthing basic here, but I have scoured the docs and mailing lists for a clue before coming here. BTW, I did find this post earlier that no one seemed to reply to, and below that are my actual python files. ---quoted message--- I want to create a Python base class that inherits from the ObjectManager and has the "Subobjects" tab in the ZClass management screen. Inheriting from OFS.ObjectManager.ObjectManager does not do this - I need to inherit from ZClasses.ObjectManager.ObjectManager. I still don't know how to have the Subobjects propertysheet thing work. I've tried the two ways I listed in my last email of doing this, but I can't get it to work. One way was: class MyObjectManager(ZClasses.ObjectManager.ObjectManager): " .... " class ZMyObjectManager: """Mix-in for Object Management """ _zclass_=myObjectManager propertysheets=ZClasses.ObjectManager.ZObjectManagerPropertySheets() manage_options=( {'label': 'Subobjects', 'action' :'propertysheets/subobjects/manage'}, ) and then register ZMyObjectManager as a base class in __init__.py. The other way was: class MyObjectManager(ZClasses.ObjectManager.ObjectManager): propertysheets=ZClasses.ObjectManager.ZObjectManagerPropertySheets() manage_options=( {'label': 'Subobjects', 'action' :'propertysheets/subobjects/manage'}, ) and register that as the base class. Neither of them work. -- Itamar S.T. itamars@ibm.net ---end quoted message--- #!/usr/bin/python # __init__.py from ZClasses import createZClassForBase from PartBase import PartBase from SitePartBase import SitePartBase from ProjectPartBase import ProjectPartBase def initialize( context ) : createZClassForBase( PartBase, globals(), 'ZCPPartBase' ) createZClassForBase( SitePartBase, globals(), 'ZCPSitePartBase' ) createZClassForBase( ProjectPartBase, globals(), 'ZCPProjectPartBase' ) #!/usr/bin/python # PartBases.py from ZClasses.ObjectManager import ZObjectManager from Products.ZCatalog.CatalogAwareness import CatalogAware class PartBases ( CatalogAware, ZObjectManager ) : """ Base Classes for all ZCP Parts """ #!/usr/bin/python # PartBase.py from PartBases import PartBases class PartBase ( PartBases ) : """ Base Class for ZCP Parts """ #!/usr/bin/python # Products/ZCapitalProjects/SitePartBases.py from PartBases import PartBases class SitePartBase ( PartBases ) : """ Base Class for ZCP Site Parts """ #!/usr/bin/python # Products/ZCapitalProjects/ProjectPartBases.py from PartBases import PartBases class ProjectPartBase ( PartBases ) : """ Base Class for ZCP Project Parts """ ----------------------------------------------------------------- | Ross Patterson rossp@cats.ucsc.edu | | Programmer/Analyst (831)459-2792 | | Physical Planning & Construction Fax:(831)423-7436 | | UC Santa Cruz http:www2.ucsc.edu/ppc | -----------------------------------------------------------------
Once it's reviewed, it'll be online: http://www.zope.org/Members/bowerymarc/squid-zserver-virtual explains step by step how to run Squid to accellerate zope's ZServer, with or without virtual domains (with is probably more interesting). It took me a while to figure all this stuff out, the older squid how-to's were a little hard to grok, until I read way too much about squid. Hopefully I've boiled all this down to a cookie cutter recipe anyone can follow. Vital to the simplicity is Webmin (http://www.webmin.com) which I think everyone should have. I wish those guys that wrote the OSX Zope control panel would do a webmin module! Marc
Nobody's really answering and I keep getting both closer and further looking at the ZClasses code. As I understand it now, ZClasses.ZClass.createZClassForBase is supposed to address the ZClass "meta class" issues such as creating the _zclass_ in addition to the actual class and handling propertysheets. So I would assume that my error lies somewhere in there, but I can't figure it out. A few more notes, when I create a ZClass that subclasses my python base class which in turn subclasses ZClasses.ObjectManager.ZObjectManager, it creates a ZClass with a default "View" for "Subobjects". This seems to indicate that somewhere the subobjects propertysheet is being treated as an instance propertysheet rather than a propertysheet of the ZClass meta class. Also, when I create an instance from such a ZClass, trying to access the instance in the ZMI yields an authorization error. Following is the traceback: Traceback (innermost last): File /usr/Zope/lib/python/ZPublisher/Publish.py, line 150, in publish_module File /usr/Zope/lib/python/ZPublisher/Publish.py, line 114, in publish File /usr/Zope/lib/python/Zope/__init__.py, line 158, in zpublisher_exception_hook (Object: blah1) File /usr/Zope/lib/python/ZPublisher/Publish.py, line 98, in publish File /usr/Zope/lib/python/ZPublisher/mapply.py, line 88, in mapply (Object: manage_workspace) File /usr/Zope/lib/python/ZPublisher/Publish.py, line 39, in call_object (Object: manage_workspace) File /usr/Zope/lib/python/App/Management.py, line 76, in manage_workspace (Object: blah1) Unauthorized: (see above) I would assume this happens because the propertysheets/subobjects/manage method listed in the view tab is not valid for the instance, but trying to call that method on the ZClass directly returns: Traceback (innermost last): File /usr/Zope/lib/python/ZPublisher/Publish.py, line 150, in publish_module File /usr/Zope/lib/python/ZPublisher/Publish.py, line 114, in publish File /usr/Zope/lib/python/Zope/__init__.py, line 158, in zpublisher_exception_hook File /usr/Zope/lib/python/ZPublisher/Publish.py, line 89, in publish File /usr/Zope/lib/python/ZPublisher/BaseRequest.py, line 278, in traverse File /usr/Zope/lib/python/OFS/PropertySheets.py, line 601, in __bobo_traverse__ AttributeError: subobjects I have also tried the two variations in the quoted message below. Then I tried the two variations below except substituting ZClasses.ObjectManager.ZObjectManager for ZClasses.ObjectManager.ObjectManager. All with the same results Again, my goal is to be able create a ZClass that subclasses a python base class that in turn subclasses ZClasses.ObjectManager.ZObjectManager in such a way that the final ZClass and any other ZClasses that subclass it have a subobjects tab in the management view of the ZClass. Thanks. On Sun, 27 Jan 2002, Ross Patterson wrote:
I'm transitioning a product from pure ZClasses to a hybrid product python base classes and ZClasses. So this is my first time working with python products.
I'm trying to setup a python base class to provide a central place to subclass ZObjectManager and CatalogAware that I can rebase later without the ZClass hassle. But when I try to create a ZClass in the product and subclass to one of my python base classes, I don't get the subobjects tab in my ZClass.
Clearly I'm missing somthing basic here, but I have scoured the docs and mailing lists for a clue before coming here. BTW, I did find this post earlier that no one seemed to reply to, and below that are my actual python files.
---quoted message---
I want to create a Python base class that inherits from the ObjectManager and has the "Subobjects" tab in the ZClass management screen. Inheriting from OFS.ObjectManager.ObjectManager does not do this - I need to inherit from ZClasses.ObjectManager.ObjectManager.
I still don't know how to have the Subobjects propertysheet thing work. I've tried the two ways I listed in my last email of doing this, but I can't get it to work.
One way was:
class MyObjectManager(ZClasses.ObjectManager.ObjectManager): " .... "
class ZMyObjectManager: """Mix-in for Object Management """
_zclass_=myObjectManager
propertysheets=ZClasses.ObjectManager.ZObjectManagerPropertySheets()
manage_options=( {'label': 'Subobjects', 'action' :'propertysheets/subobjects/manage'}, )
and then register ZMyObjectManager as a base class in __init__.py. The other way was:
class MyObjectManager(ZClasses.ObjectManager.ObjectManager): propertysheets=ZClasses.ObjectManager.ZObjectManagerPropertySheets()
manage_options=( {'label': 'Subobjects', 'action' :'propertysheets/subobjects/manage'}, )
and register that as the base class. Neither of them work.
-- Itamar S.T. itamars@ibm.net
---end quoted message---
#!/usr/bin/python # Products/ZCapitalProjects/__init__.py from ZClasses import createZClassForBase from PartBases import PartBases from PartBase import PartBase from SitePartBase import SitePartBase from ProjectPartBase import ProjectPartBase from PartBases import ZZCPObjectManager, ZCPObjectManager2, ZZCPObjectManager3, ZCPObjectManager4 createZClassForBase( PartBases, globals(), 'ZCPPartBases' ) createZClassForBase( PartBase, globals(), 'ZCPPartBase' ) createZClassForBase( SitePartBase, globals(), 'ZCPSitePartBase' ) createZClassForBase( ProjectPartBase, globals(), 'ZCPProjectPartBase' ) createZClassForBase( ZZCPObjectManager, globals(), 'ZZCPObjectManager' ) createZClassForBase( ZCPObjectManager2, globals(), 'ZCPObjectManager2' ) createZClassForBase( ZZCPObjectManager3, globals(), 'ZZCPObjectManager3' ) createZClassForBase( ZCPObjectManager4, globals(), 'ZCPObjectManager4' ) #!/usr/bin/python # Products/ZCapitalProjects/PartBases.py import ZClasses from ZClasses.ObjectManager import ZObjectManager from Products.ZCatalog.CatalogAwareness import CatalogAware class PartBases ( ZObjectManager ) : # CatalogAware, """ Base Classes for all ZCP Parts """ pass class ZCPObjectManager(ZClasses.ObjectManager.ObjectManager): " .... " class ZZCPObjectManager: """Mix-in for Object Management """ _zclass_=ZCPObjectManager propertysheets=ZClasses.ObjectManager.ZObjectManagerPropertySheets() manage_options=( {'label': 'Subobjects', 'action':'propertysheets/subobjects/manage'},) class ZCPObjectManager2(ZClasses.ObjectManager.ObjectManager): propertysheets=ZClasses.ObjectManager.ZObjectManagerPropertySheets() manage_options=( {'label': 'Subobjects', 'action' :'propertysheets/subobjects/manage'},) class ZCPObjectManager3(ZClasses.ObjectManager.ZObjectManager): " .... " class ZZCPObjectManager3: """Mix-in for Object Management """ _zclass_=ZCPObjectManager3 propertysheets=ZClasses.ObjectManager.ZObjectManagerPropertySheets() manage_options=( {'label': 'Subobjects', 'action':'propertysheets/subobjects/manage'},) class ZCPObjectManager4(ZClasses.ObjectManager.ZObjectManager): propertysheets=ZClasses.ObjectManager.ZObjectManagerPropertySheets() manage_options=( {'label': 'Subobjects', 'action' :'propertysheets/subobjects/manage'},) #!/usr/bin/python # Products/ZCapitalProjects/PartBase.py from PartBases import PartBases class PartBase ( PartBases ) : """ Base Class for ZCP Parts """ pass #!/usr/bin/python # Products/ZCapitalProjects/SitePartBases.py from PartBases import PartBases class SitePartBase ( PartBases ) : """ Base Class for ZCP Site Parts """ pass #!/usr/bin/python # Products/ZCapitalProjects/ProjectPartBases.py from PartBases import PartBases class ProjectPartBase ( PartBases ) : """ Base Class for ZCP Project Parts """ pass
I figured it out and I'm posting this so that the next hapless victim might stumble upon this in a google search where I did not. Long, with suggestions that have probably already been made for the improvements and clarification of ZClasses. The problem is that I was trying to subclass in python a class that was meant to be subclassed in a ZClass, namely ZClasses.ObjectManager.ZObjectManager. ZObjectManager is a mix-in class that sets the ObjectManager class as its _zclass_ attribute, a ZObjectManagerPropertySheets() class instance as its propertysheets attribute, and sets the appropriate manage_options attribute. ZClasses.createZClassForBase, however overrides all of this so calling it on a mix-in class yeilds two layers of meta-classes and everything goes #$*&i%@!! ZObjectManager gets registered using App.ProductContext.registerZClass(), which is supposedly deprecated. So I made a nearly exact duplicate of the ZObjectManager mix-in (which violates DRY) that sets _zclass_ to a class that subclasses ZCatalog.CatalogAwareness.CatalogAware and ZClasses.ObjectManager.ObjectManager, and handles the propertysheets and manage_options attributes. I then register my mix-in with registerZClass and the rest of my python base classes with createZClassForBase. It works, the subobjects management tab shows up in any ZClass that directly or indirectly subclasses my python mix-in. There are several glaring problems here, however. One is the DRY violation in duplicating the ZObjectManager mix-in. The problem here is that inheritance only applies to instances, so a class object that subclasses a python ZClass doesn't inherit IN ITSELF the _zclass_, propertysheets, manage_options, or any other attributes used by the ZClass machinery at module import time, and thus it must be duplicated. Is there any way around this? Second is the use of a deprecated function. Of course, I'm not alone on that one. The ZClass module itself still depends on that function for the registration of ZObjectManager. So maybe it shouldn't be deprecated, maybe it should be moved into ZClasses, maybe createZClassForBase should be more intelligent? Thirdly, its just all not very OO. Of course, now that I've struggled with all of this, I'm impressed as hell with ZClasses, I'm still pissed at them, but I'm also impressed. Its just difficult. All the same, however, there may well be room for more elegant ways of doing all this. For example, if I ever want my python base classes to subclass another class like ZObjectManager that implements changes to the ZClass management interface, I'm going to have to manually reconcile the demands of the two subclasses on the ZClass machinery. Ick. Of course, having finished complaining, I'm going to do nothing about all of this. My excuse, figuring this out without so much as a mailing list post to aid has put my project several days in arrears. Of course, this is how I choose to learn is with a project to push me. So there we have it. My working *.py files are quoted below the quoted history. On Mon, 28 Jan 2002, Ross Patterson wrote:
Nobody's really answering and I keep getting both closer and further looking at the ZClasses code. As I understand it now, ZClasses.ZClass.createZClassForBase is supposed to address the ZClass "meta class" issues such as creating the _zclass_ in addition to the actual class and handling propertysheets. So I would assume that my error lies somewhere in there, but I can't figure it out.
A few more notes, when I create a ZClass that subclasses my python base class which in turn subclasses ZClasses.ObjectManager.ZObjectManager, it creates a ZClass with a default "View" for "Subobjects". This seems to indicate that somewhere the subobjects propertysheet is being treated as an instance propertysheet rather than a propertysheet of the ZClass meta class.
Also, when I create an instance from such a ZClass, trying to access the instance in the ZMI yields an authorization error. Following is the traceback:
Traceback (innermost last): File /usr/Zope/lib/python/ZPublisher/Publish.py, line 150, in publish_module File /usr/Zope/lib/python/ZPublisher/Publish.py, line 114, in publish File /usr/Zope/lib/python/Zope/__init__.py, line 158, in zpublisher_exception_hook (Object: blah1) File /usr/Zope/lib/python/ZPublisher/Publish.py, line 98, in publish File /usr/Zope/lib/python/ZPublisher/mapply.py, line 88, in mapply (Object: manage_workspace) File /usr/Zope/lib/python/ZPublisher/Publish.py, line 39, in call_object (Object: manage_workspace) File /usr/Zope/lib/python/App/Management.py, line 76, in manage_workspace (Object: blah1) Unauthorized: (see above)
I would assume this happens because the propertysheets/subobjects/manage method listed in the view tab is not valid for the instance, but trying to call that method on the ZClass directly returns:
Traceback (innermost last): File /usr/Zope/lib/python/ZPublisher/Publish.py, line 150, in publish_module File /usr/Zope/lib/python/ZPublisher/Publish.py, line 114, in publish File /usr/Zope/lib/python/Zope/__init__.py, line 158, in zpublisher_exception_hook File /usr/Zope/lib/python/ZPublisher/Publish.py, line 89, in publish File /usr/Zope/lib/python/ZPublisher/BaseRequest.py, line 278, in traverse File /usr/Zope/lib/python/OFS/PropertySheets.py, line 601, in __bobo_traverse__ AttributeError: subobjects
I have also tried the two variations in the quoted message below. Then I tried the two variations below except substituting ZClasses.ObjectManager.ZObjectManager for ZClasses.ObjectManager.ObjectManager. All with the same results
Again, my goal is to be able create a ZClass that subclasses a python base class that in turn subclasses ZClasses.ObjectManager.ZObjectManager in such a way that the final ZClass and any other ZClasses that subclass it have a subobjects tab in the management view of the ZClass. Thanks.
On Sun, 27 Jan 2002, Ross Patterson wrote:
I'm transitioning a product from pure ZClasses to a hybrid product python base classes and ZClasses. So this is my first time working with python products.
I'm trying to setup a python base class to provide a central place to subclass ZObjectManager and CatalogAware that I can rebase later without the ZClass hassle. But when I try to create a ZClass in the product and subclass to one of my python base classes, I don't get the subobjects tab in my ZClass.
Clearly I'm missing somthing basic here, but I have scoured the docs and mailing lists for a clue before coming here. BTW, I did find this post earlier that no one seemed to reply to, and below that are my actual python files.
---quoted message---
I want to create a Python base class that inherits from the ObjectManager and has the "Subobjects" tab in the ZClass management screen. Inheriting from OFS.ObjectManager.ObjectManager does not do this - I need to inherit from ZClasses.ObjectManager.ObjectManager.
I still don't know how to have the Subobjects propertysheet thing work. I've tried the two ways I listed in my last email of doing this, but I can't get it to work.
One way was:
class MyObjectManager(ZClasses.ObjectManager.ObjectManager): " .... "
class ZMyObjectManager: """Mix-in for Object Management """
_zclass_=myObjectManager
propertysheets=ZClasses.ObjectManager.ZObjectManagerPropertySheets()
manage_options=( {'label': 'Subobjects', 'action' :'propertysheets/subobjects/manage'}, )
and then register ZMyObjectManager as a base class in __init__.py. The other way was:
class MyObjectManager(ZClasses.ObjectManager.ObjectManager): propertysheets=ZClasses.ObjectManager.ZObjectManagerPropertySheets()
manage_options=( {'label': 'Subobjects', 'action' :'propertysheets/subobjects/manage'}, )
and register that as the base class. Neither of them work.
-- Itamar S.T. itamars@ibm.net
---end quoted message---
#!/usr/bin/python # Products/ZCapitalProjects/__init__.py from ZClasses import createZClassForBase from PartZClass import PartZClass from PartBase import PartBase from SitePartBase import SitePartBase from ProjectPartBase import ProjectPartBase createZClassForBase( PartBase, globals(), 'ZCPPartBase' ) createZClassForBase( SitePartBase, globals(), 'ZCPSitePartBase' ) createZClassForBase( ProjectPartBase, globals(), 'ZCPProjectPartBase' ) def initialize( context ) : context.registerZClass( PartZClass ) #!/usr/bin/python # Products/ZCapitalProjects/PartZClass.py from ZClasses.ObjectManager import ObjectManager, ZObjectManagerPropertySheets from Products.ZCatalog.CatalogAwareness import CatalogAware class ZPartBase ( CatalogAware, ObjectManager ) : """ Base Classes for all ZCP Parts """ pass class PartZClass : """Mix-in for Object Management """ _zclass_=ZPartBase propertysheets=ZObjectManagerPropertySheets() manage_options=( {'label': 'Subobjects', 'action' :'propertysheets/subobjects/manage'}, ) #!/usr/bin/python # Products/ZCapitalProjects/PartBase.py class PartBase : """ Base Class for ZCP Parts """ pass #!/usr/bin/python # Products/ZCapitalProjects/SitePartBases.py class SitePartBase : """ Base Class for ZCP Site Parts """ pass #!/usr/bin/python # Products/ZCapitalProjects/ProjectPartBases.py class ProjectPartBase : """ Base Class for ZCP Project Parts """ pass ----------------------------------------------------------------- | Ross Patterson rossp@cats.ucsc.edu | | Programmer/Analyst (831)459-2792 | | Physical Planning & Construction Fax:(831)423-7436 | | UC Santa Cruz http:www2.ucsc.edu/ppc | -----------------------------------------------------------------
On Tue, 2002-01-29 at 17:28, Ross Patterson wrote:
I figured it out and I'm posting this so that the next hapless victim might stumble upon this in a google search where I did not. Long, with suggestions that have probably already been made for the improvements and clarification of ZClasses.
[...]
ZObjectManager gets registered using App.ProductContext.registerZClass(), which is supposedly deprecated. So I made a nearly exact duplicate of the ZObjectManager mix-in (which violates DRY) that sets _zclass_ to a class that subclasses ZCatalog.CatalogAwareness.CatalogAware and ZClasses.ObjectManager.ObjectManager, and handles the propertysheets and manage_options attributes.
Be careful here. Last I looked, CatalogAwareness is not VirtualHost safe. You should use CatalogPathAwareness instead. Cheers, Leo PS: now if only CatalogPathAwareness was avaliable for subclassing by ZClasses... -- Ideas don't stay in some minds very long because they don't like solitary confinement.
participants (3)
-
Leonardo Rochael Almeida -
marc lindahl -
Ross Patterson