Zope 2.7: OrderSupport for ObjectManager
Hi! Implementing the OrderedObjectManager proposal, we fleshed it out and modified it a bit. I made an initial checkin on a branch which reflects our current thinking. So this is your chance to discuss the changes before we merge it into the trunk. The code: yuppie-ordersupport-branch (Creating the branch went wrong a bit. Please just checkout lib/python/AccessControl, lib/python/OFS and lib/python/Products/OFSP.) The original proposal: <http://dev.zope.org/Wikis/DevSite/Proposals/OrderedObjectManager> Some key issues: 1.) OrderSupport is a mixin class for ObjectManager. (using the CopySupport / FindSupport / UndoSupport pattern) 2.) 'Folder (Ordered)' is a 'Folder' with OrderSupport. (using the 'Script (Python)' pattern for the meta_type to avoid a name clash with the existing OrderedFolder product or names like OrderedFolderLite) 3.) For the ZMI, we use the same 'main.dtml' as the ObjectManager. This way we avoid redundant code and make it easier for products that need to change the 'main.dtml'. If there are no objections, I'm going to land this soon. Cheers, Yuppie PS: For API Help, we have to copy (!) the Interface to OFSP/help? Right?
Looks reasonable... I'm a bit uncomfortable with the sort-by-subobject-attribute code in orderObjects (the code that is called when sort order is not "position"). I'm wondering if a generic "IndexedFolder" implementation might be better for this behavior, where the user may define one or more indexes on the container itself. The indexes could named after attributes of subobjects. The indexes and a sort function for each index would be maintained on the container, and the API methods objectValues, objectIds, etc.would consult the indexes to return objects in sorted order dynamically (as opposed to just returning the presorted list of _objects, which needs to be manipulated statically after each insertion). This might be an argument to ditch the dynamic sorting feature until we better understand the use cases. That said, the feature isn't exposed in the mgmt interface, so it might be ok. But if people come to rely on it, it will be difficult to remove (and will never ever go away). Just a thought. - C On Mon, 2003-05-05 at 07:35, Yuppie wrote:
Hi!
Implementing the OrderedObjectManager proposal, we fleshed it out and modified it a bit. I made an initial checkin on a branch which reflects our current thinking. So this is your chance to discuss the changes before we merge it into the trunk.
The code yuppie-ordersupport-branch (Creating the branch went wrong a bit. Please just checkout lib/python/AccessControl, lib/python/OFS and lib/python/Products/OFSP.)
The original proposal: <http://dev.zope.org/Wikis/DevSite/Proposals/OrderedObjectManager>
Some key issues:
1.) OrderSupport is a mixin class for ObjectManager. (using the CopySupport / FindSupport / UndoSupport pattern)
2.) 'Folder (Ordered)' is a 'Folder' with OrderSupport. (using the 'Script (Python)' pattern for the meta_type to avoid a name clash with the existing OrderedFolder product or names like OrderedFolderLite)
3.) For the ZMI, we use the same 'main.dtml' as the ObjectManager. This way we avoid redundant code and make it easier for products that need to change the 'main.dtml'.
If there are no objections, I'm going to land this soon.
Cheers,
Yuppie
PS: For API Help, we have to copy (!) the Interface to OFSP/help? Right?
_______________________________________________ Zope-Dev maillist - Zope-Dev@zope.org http://mail.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://mail.zope.org/mailman/listinfo/zope-announce http://mail.zope.org/mailman/listinfo/zope )
Hi Chris! Thanks for your feedback. Chris McDonough wrote:
I'm a bit uncomfortable with the sort-by-subobject-attribute code in orderObjects (the code that is called when sort order is not "position").
I'm wondering if a generic "IndexedFolder" implementation might be better for this behavior, where the user may define one or more indexes on the container itself. The indexes could named after attributes of subobjects. The indexes and a sort function for each index would be maintained on the container, and the API methods objectValues, objectIds, etc.would consult the indexes to return objects in sorted order dynamically (as opposed to just returning the presorted list of _objects, which needs to be manipulated statically after each insertion).
Well, you could use 'orderObjects' for that use case if you write some code that does the necessary manipulation after each insertion. But we included it for another use case: Sometimes people want to maintain a user-specific order, but want to start from a sorted order. E.g. if most sub-objects should be ordered by 'title', but some special sub-objects should be at top of the container. I like your ideas of "IndexedFolder". And there are the two methods 'getDefaultSorting' and 'setDefaultSorting' in OrderSupport that do something similar in a very basic way.
This might be an argument to ditch the dynamic sorting feature until we better understand the use cases. That said, the feature isn't exposed in the mgmt interface, so it might be ok. But if people come to rely on it, it will be difficult to remove (and will never ever go away).
AFAICS, 'orderObjects' would still be useful for the use case described above. 'getDefaultSorting' and 'setDefaultSorting' provide a small subset of the API you propose and should play well with any "IndexedFolder". Cheers, Yuppie
Hi Yuppie... On Tue, 2003-05-06 at 06:20, Yuppie wrote:
Well, you could use 'orderObjects' for that use case if you write some code that does the necessary manipulation after each insertion. But we included it for another use case:
Sometimes people want to maintain a user-specific order, but want to start from a sorted order. E.g. if most sub-objects should be ordered by 'title', but some special sub-objects should be at top of the container.
So you mean that someone's usage of it would go like this: - Add an ordered folder "O" and change its sort attr to "title" - Add a bunch of subobjects to "O". - Apply sorting. - Move stuff up and down. Is that about right?
I like your ideas of "IndexedFolder". And there are the two methods 'getDefaultSorting' and 'setDefaultSorting' in OrderSupport that do something similar in a very basic way.
I suspect these method signatures would need to change if we were to use an index and an arbitrary sort function.
This might be an argument to ditch the dynamic sorting feature until we better understand the use cases. That said, the feature isn't exposed in the mgmt interface, so it might be ok. But if people come to rely on it, it will be difficult to remove (and will never ever go away).
AFAICS, 'orderObjects' would still be useful for the use case described above. 'getDefaultSorting' and 'setDefaultSorting' provide a small subset of the API you propose and should play well with any "IndexedFolder".
While I see what you're saying, I think anticipating an API is a bit speculative. Anyway, all of this is just advisory, but at very least, I'd like to see the "apply current sorting" button go away in the UI because it's not entirely clear what it does to someone who doesn't understand the code. If you can't investigate the sorting parameters TTW, you probably shouldn't be able to activate them TTW. - C
Hi Chris! Chris McDonough wrote:
Sometimes people want to maintain a user-specific order, but want to start from a sorted order. E.g. if most sub-objects should be ordered by 'title', but some special sub-objects should be at top of the container.
So you mean that someone's usage of it would go like this:
- Add an ordered folder "O" and change its sort attr to "title"
- Add a bunch of subobjects to "O".
- Apply sorting.
- Move stuff up and down.
Is that about right?
Yes.
This might be an argument to ditch the dynamic sorting feature until we better understand the use cases. That said, the feature isn't exposed in the mgmt interface, so it might be ok. But if people come to rely on it, it will be difficult to remove (and will never ever go away).
AFAICS, 'orderObjects' would still be useful for the use case described above. 'getDefaultSorting' and 'setDefaultSorting' provide a small subset of the API you propose and should play well with any "IndexedFolder".
While I see what you're saying, I think anticipating an API is a bit speculative.
Naturally.
Anyway, all of this is just advisory, but at very least, I'd like to see the "apply current sorting" button go away in the UI because it's not entirely clear what it does to someone who doesn't understand the code. If you can't investigate the sorting parameters TTW, you probably shouldn't be able to activate them TTW.
I'm not sure I did get your last point: The sorting parameters are visualized by the sorting the items currently have in the TTW view (and by the bold column heading). I thought this is a very intuitiv way to investigate sorting parameters. Cheers, Yuppie
On Tue, 2003-05-06 at 10:23, Yuppie wrote:
So you mean that someone's usage of it would go like this:
- Add an ordered folder "O" and change its sort attr to "title"
- Add a bunch of subobjects to "O".
- Apply sorting.
- Move stuff up and down.
Is that about right?
Yes.
OK, thank you for confirming. I've never had a need to do this, but I respect the fact that you have.
Anyway, all of this is just advisory, but at very least, I'd like to see the "apply current sorting" button go away in the UI because it's not entirely clear what it does to someone who doesn't understand the code. If you can't investigate the sorting parameters TTW, you probably shouldn't be able to activate them TTW.
I'm not sure I did get your last point: The sorting parameters are visualized by the sorting the items currently have in the TTW view (and by the bold column heading). I thought this is a very intuitiv way to investigate sorting parameters.
I see now that the sort order of the items in the ZMI can be applied. It was a little *too* obvious for me to understand. ;-) I thought the sort attr needed to be set manually from Python. - C
Chris McDonough wrote:
On Tue, 2003-05-06 at 10:23, Yuppie wrote:
So you mean that someone's usage of it would go like this:
- Add an ordered folder "O" and change its sort attr to "title"
- Add a bunch of subobjects to "O".
- Apply sorting.
- Move stuff up and down.
Is that about right?
Yes.
OK, thank you for confirming. I've never had a need to do this, but I respect the fact that you have.
I've also never had a need to do this, but I respect the fact that Maik has ;) Yuppie
Chris McDonough wrote:
On Tue, 2003-05-06 at 11:56, Yuppie wrote:
I've also never had a need to do this, but I respect the fact that Maik has ;)
Maik, do you still think this is a good idea?
Hi Chris, my personal use-case for this feature is the typical "Through-The-Web"-developer: She creates lots of DTML, ZPT, PythonScripts in a folder (needed for acquisition), adds several new objects etc. After a while she has a mess of different objects, where it is hard to find the one she wants to work on. So she clicks on "Types" to sort the folder by meta_types, "applies this sorting" and moves the three PythonScripts she is currently working on to the top of the folder (no more scrolling every time to the buttom of the folder etc.). This feature is something like cleaning up your desktop automagically (sort all my bills, my lectures, my proposals, ...) and put the important documents afterwards onto the top. I like the idea of "cleaning up", but I don't insist on the "Apply this sorting" button. So let's drop it, because it seems to special for me in the meanwhile...:) Cheers, Maik
On Tue, 2003-05-06 at 14:53, Maik Jablonski wrote:
She creates lots of DTML, ZPT, PythonScripts in a folder (needed for acquisition), adds several new objects etc. After a while she has a mess of different objects, where it is hard to find the one she wants to work on. So she clicks on "Types" to sort the folder by meta_types, "applies this sorting" and moves the three PythonScripts she is currently working on to the top of the folder (no more scrolling every time to the buttom of the folder etc.).
Oh, I see! I didn't know that the use case was related to the ZMI UI, I thought it was related to the objectmanager API and people getting things back in some presorted order... apologies.
This feature is something like cleaning up your desktop automagically (sort all my bills, my lectures, my proposals, ...) and put the important documents afterwards onto the top.
I see.
I like the idea of "cleaning up", but I don't insist on the "Apply this sorting" button. So let's drop it, because it seems to special for me in the meanwhile...:)
It does seem handy, but I think it'd probably be better to leave it out of the core if it's just for ZMI UI purposes... it might be better implemented as a "skin" for normal folders. I must admit that as I think about it, the whole ordered folder notion (with or without this functionality) seems to be more about skinning the existing folder UI than it is about creating a new slightly-different metatype. I realize by saying that I'm probably contradicting other folks who made comments on the proposal, but something just doesn't feel quite right about having two objects that cannot be interchanged without data conversion when the underlying data structure is exactly the same. Might there be some way we can provide hooks to allow people to more easily build add-on products that modified UI code with this type of functionality (e.g. prevent people from having to overwrite main.dtml)? - C
Chris McDonough wrote:
Might there be some way we can provide hooks to allow people to more easily build add-on products that modified UI code with this type of functionality (e.g. prevent people from having to overwrite main.dtml)?
That's what I thought of many times... How about changing main.dtml with a series of diff-patches on Zope's startup? - Zope starts and sets up the main.dtml as manage_main of the ObjectManager. - Product A (e.g. External Editor) applies a patch to the source of manage_main (as diff to the "official" main.dtml) - Product B (e.g. AbracadabraObject) applies a patch to the patched manage_main (as diff to the "official" main.dtml) - and so on... Some guidelines for Product-Authors should help avoiding interferences... Cheers, Maik
I must admit that as I think about it, the whole ordered folder notion (with or without this functionality) seems to be more about skinning the existing folder UI than it is about creating a new slightly-different metatype.
This is what I was trying to say in my post a few days ago. I still dont think that OrderedObjectManager should be a container/folder type. It should be a metatype that you can add to any existing folder, btreefolder, ldapfolder, sqlfolder, or whatever you may have. Configure it from where to get ids (could be objectIds, a catalog query using pathindex or just about anything), and provide a way to sort them. /Magnus
Hi! Magnus Heino wrote:
I must admit that as I think about it, the whole ordered folder notion (with or without this functionality) seems to be more about skinning the existing folder UI than it is about creating a new slightly-different metatype.
This is what I was trying to say in my post a few days ago.
I still dont think that OrderedObjectManager should be a container/folder type.
It should be a metatype that you can add to any existing folder, btreefolder, ldapfolder, sqlfolder, or whatever you may have. Configure it from where to get ids (could be objectIds, a catalog query using pathindex or just about anything), and provide a way to sort them.
Well. The problem is: We are not talking about Zope3. In the thread the proposal was discussed, Shane wrote:
In Zope 3 you'd be able to do it right. In Zope 2 you can hope for nothing better than a terrible hack.
Zope 2 folders already have the _objects tuple. Do you want to maintain a second list to store order? A lot of products make use of details of the current Folder implementation. Rewriting parts of it would cause a lot of trouble. Our first proposal was to add the ordering API to the default Folder. The result of the discussion was OrderedFolder. That makes it easier to migrate to Zope3: If it is an OrderedFolder, the order of _objects is important, if it is an Folder, we just can discard _objects. I'd be more than happy if someone comes up with a better solution for Zope 2.7. But I'm not willing to wait for Zope3 to do it right. Cheers, Yuppie
I'll have to chime in since I saw something that's a bad assumption. Yuppie wrote:
Our first proposal was to add the ordering API to the default Folder. The result of the discussion was OrderedFolder. That >makes it easier to migrate to Zope3: If it is an OrderedFolder, the order of _objects is important, if it is an Folder, we just can >discard _objects. This is a *really* bad assumption; for several projects I've monkey-patched folder to support ordering in custom CMS projects; the order of _objects is important to these folks. I appologize for chiming in so late in the game, but if requirements are being driven by that assumption, it's not a safe one IMNSHO. Thanks, Andrew Sawyers Software Engineer Zope Corporation
Hi Andrew! Andrew Sawyers wrote:
I'll have to chime in since I saw something that's a bad assumption. Welcome to the discussion :)
Yuppie wrote:
Our first proposal was to add the ordering API to the default Folder.
The result of the discussion was OrderedFolder. That >makes it easier to migrate to Zope3: If it is an OrderedFolder, the order of _objects is important, if it is an Folder, we just can >discard _objects. This is a *really* bad assumption; for several projects I've monkey-patched folder to support ordering in custom CMS projects; the order of _objects is important to these folks. I appologize for chiming in so late in the game, but if requirements are being driven by that assumption, it's not a safe one IMNSHO.
So a better assumption would be: We don't know what people did with _objects, so _objects might be important. Right? That means: All Zope2 Folders have to be converted to Zope3 Folders with OrderSupport (what ever OrderSupport would look like in Zope3). If that is the case, I can't see why the default Zope2 Folder can't have OrderSupport. Maybe you read the discussion I had with Shane about this issue <http://mail.zope.org/pipermail/zope-coders/2002-December/002955.html> or ask him yourself. I'm not sure if I did get all his arguments, but the point that convinced me is becoming weak. Cheers, Yuppie
Thanks for the warm welcome :) I'll elaborate on points in-line so see below..... Yuppie wrote:
Hi Andrew!
Andrew Sawyers wrote:
I'll have to chime in since I saw something that's a bad assumption.
Welcome to the discussion :)
Yuppie wrote:
Our first proposal was to add the ordering API to the default Folder.
The result of the discussion was OrderedFolder. That >makes it easier to migrate to Zope3: If it is an OrderedFolder, the order of _objects is important, if it is an Folder, we just can >discard _objects. This is a *really* bad assumption; for several projects I've monkey-patched folder to support ordering in custom CMS projects; the order of _objects is important to these folks. I appologize for chiming in so late in the game, but if requirements are being driven by that assumption, it's not a safe one IMNSHO.
So a better assumption would be:
We don't know what people did with _objects, so _objects might be important.
Right?
Right, if there's any discussion on considering a migration path into Zope3 this can't be ignored.
That means: All Zope2 Folders have to be converted to Zope3 Folders with OrderSupport (what ever OrderSupport would look like in Zope3).
If that is the case, I can't see why the default Zope2 Folder can't have OrderSupport. Maybe you read the discussion I had with Shane about this issue <http://mail.zope.org/pipermail/zope-coders/2002-December/002955.html> or ask him yourself.
I quickly glanced over the thread and at first thought I disagree. Order is important to many people (or at least the appearance of order) - and it's more then just sorting, because they want them sorted by Title, but always 'X' to be the first item. This may not be so important to developers, but it's definately important to the end users of the systems I've created in the past (for sure the past 3 projects). I'll talk to Shane and see if I understand the approaches they're planning for Zope3 (I'm out of the loop on that doing project work).....but so far I'm not convinced.
I'm not sure if I did get all his arguments, but the point that convinced me is becoming weak.
Cheers,
Yuppie
Cheers, Andrew
Hi! Andrew Sawyers wrote:
That means: All Zope2 Folders have to be converted to Zope3 Folders with OrderSupport (what ever OrderSupport would look like in Zope3).
If that is the case, I can't see why the default Zope2 Folder can't have OrderSupport. Maybe you read the discussion I had with Shane about this issue <http://mail.zope.org/pipermail/zope-coders/2002-December/002955.html> or ask him yourself.
I quickly glanced over the thread and at first thought I disagree. Order is important to many people (or at least the appearance of order) - and it's more then just sorting, because they want them sorted by Title, but always 'X' to be the first item. This may not be so important to developers, but it's definately important to the end users of the systems I've created in the past (for sure the past 3 projects). I'll talk to Shane and see if I understand the approaches they're planning for Zope3 (I'm out of the loop on that doing project work).....but so far I'm not convinced.
Andrew, did you have a chance to talk to Shane? We discussed this issue months ago and we found a solution everybody (who took part in the discussion) can live with and that was ok'ed by Brian. The result was OrderedFolder and as Toby wrote:
Anyone who is relying on orderedness of Zope2 folders needs to migrate those to OrderedFolder before jumping to Zope3.
If anybody wants to reopen this discussion, please do it now. I'd happily change the implementation and give the default 'Folder' OrderSupport. If not, I'd like to move on with OrderedFolder and resolve the remaining minor issues. Cheers, Yuppie
Yuppie wrote:
Andrew Sawyers wrote:
I quickly glanced over the thread and at first thought I disagree. Order is important to many people (or at least the appearance of order) - and it's more then just sorting, because they want them sorted by Title, but always 'X' to be the first item. This may not be so important to developers, but it's definately important to the end users of the systems I've created in the past (for sure the past 3 projects). I'll talk to Shane and see if I understand the approaches they're planning for Zope3 (I'm out of the loop on that doing project work).....but so far I'm not convinced.
Andrew, did you have a chance to talk to Shane?
Andrew did, and we continue to disagree. :-) However, Toby and I seem to be the only ones who don't want stored order mixed in to normal folders. I guess we're outnumbered. So if you prefer to mix stored order into normal Folders, that's OK by me, but I'll make two requests: - Folders should have a new boolean attribute, perhaps "_stored_order". It should default to false, meaning there is no stored order. As soon as the user manually modifies the order, that attribute should be set to true. This will smooth the transition to Zope 3, and it will allow folders without a stored order to continue to sort automatically. - Please split up manage_main into several parts. This is fairly trivial to do, but no one has bothered. You see, another change to manage_main is going to cause pain for everyone who maintains a product that replaces manage_main. If you take the time to split up manage_main, it will no longer be necessary for products to replace the entire manage_main, and at least this might be the last time product maintainers have to endure this pain. BTW it doesn't really matter whether you change ObjectManager or Folder. It is commonly believed that most folderish products subclass ObjectManager instead of Folder, but that is not the case. Most folderish products subclass Folder. Since ObjectManager is what knows about the _objects attribute, where the order is stored, you might as well implement the order modification API in ObjectManager. Shane
My concern was mainly with the assumption of migration; so since I've been told on this end that's really a non-issue I'm not so worried anymore. Andrew Shane Hathaway wrote:
Yuppie wrote:
Andrew Sawyers wrote:
I quickly glanced over the thread and at first thought I disagree. Order is important to many people (or at least the appearance of order) - and it's more then just sorting, because they want them sorted by Title, but always 'X' to be the first item. This may not be so important to developers, but it's definately important to the end users of the systems I've created in the past (for sure the past 3 projects). I'll talk to Shane and see if I understand the approaches they're planning for Zope3 (I'm out of the loop on that doing project work).....but so far I'm not convinced.
Andrew, did you have a chance to talk to Shane?
Andrew did, and we continue to disagree. :-)
However, Toby and I seem to be the only ones who don't want stored order mixed in to normal folders. I guess we're outnumbered. So if you prefer to mix stored order into normal Folders, that's OK by me, but I'll make two requests:
- Folders should have a new boolean attribute, perhaps "_stored_order". It should default to false, meaning there is no stored order. As soon as the user manually modifies the order, that attribute should be set to true. This will smooth the transition to Zope 3, and it will allow folders without a stored order to continue to sort automatically.
- Please split up manage_main into several parts. This is fairly trivial to do, but no one has bothered. You see, another change to manage_main is going to cause pain for everyone who maintains a product that replaces manage_main. If you take the time to split up manage_main, it will no longer be necessary for products to replace the entire manage_main, and at least this might be the last time product maintainers have to endure this pain.
BTW it doesn't really matter whether you change ObjectManager or Folder. It is commonly believed that most folderish products subclass ObjectManager instead of Folder, but that is not the case. Most folderish products subclass Folder. Since ObjectManager is what knows about the _objects attribute, where the order is stored, you might as well implement the order modification API in ObjectManager.
Shane
Hi Andrew! Andrew Sawyers wrote:
My concern was mainly with the assumption of migration; so since I've been told on this end that's really a non-issue I'm not so worried anymore.
Could you please elaborate on this? Why is it a non-issue? Thanks, Yuppie
On Wednesday 07 May 2003 4:00 pm, Yuppie wrote:
So a better assumption would be:
We don't know what people did with _objects, so _objects might be important.
Right?
That means: All Zope2 Folders have to be converted to Zope3 Folders with OrderSupport (what ever OrderSupport would look like in Zope3).
If that is the case, I can't see why the default Zope2 Folder can't have OrderSupport. Maybe you read the discussion I had with Shane about this issue <http://mail.zope.org/pipermail/zope-coders/2002-December/002955.html> or ask him yourself.
I'm with Shane on this one. Anyone who is relying on orderedness of Zope2 folders needs to migrate those to OrderedFolder before jumping to Zope3. Folders in Zope2 wont ever lose their internal order, or their _objects attribute, but they shouldnt gain an API. -- Toby Dickenson http://www.geminidataloggers.com/people/tdickenson
Yuppie wrote:
We don't know what people did with _objects, so _objects might be important.
Yes, I've seen people using the "Rename"-Button (=> delete and recreate) to order a folder... Wired, but the result is: _objects are a ordered tuple.
That means: All Zope2 Folders have to be converted to Zope3 Folders with OrderSupport (what ever OrderSupport would look like in Zope3).
Indeed...
If that is the case, I can't see why the default Zope2 Folder can't have OrderSupport.
Returning to the starting point of the discussion weeks ago? Interesting... I like the idea of the OrderSupport-Mixin-class. But maybe we shouldn't introduce a new additional meta_type "Folder (Ordered)". Instead we should extend the normal Folder with OrderSupport as originally proposed. People who don't need order support don't have to use it. All other people can use the OrderSupport without converting their Folder-(or-derived)-Instances. Cheers, Maik
I like the idea of the OrderSupport-Mixin-class. But maybe we shouldn't introduce a new additional meta_type "Folder (Ordered)". Instead we should extend the normal Folder with OrderSupport as originally proposed. People who don't need order support don't have to use it. All other people can use the OrderSupport without converting their Folder-(or-derived)-Instances.
FWIW, if "ordered folder" functionality needs to go into the core (which I'm admittedly leery of to start with), I think I agree with Maik, as long as: - the ordering method names are sufficiently verbose (to reduce the chance of acquisition name collisions). - the default Folder ZMI UI does not change, but can be influenced by add-in product code. FWIW, this whole business would be made much easier if we moved the skin machinery out of CMF and into the core. - C
I'm all confused now. What are the use cases for this order support again? For me, ordered support is useful in two cases: 1. For people want to make menues or lists of document/objects, and want them to be in a specific order. This requires ordering of the objects, and to display that ordering. 2. When you make objects and services that rely on an ordered list of subobjects. For example, say that you have a service of some kind that uses several plugins to perform functions, and it has to call these plugins in a particular order. Is there anything I have missed? When it comes to UI, you need to have a way of ordering and sorting the objects, and of course displaying the cureent order. There are two ways to do that as I can see it. 1. Use the currentZMI object listing, "main.dtml". That saves you from having two user interfaces. It would be nice to have a sorting function too, to sort on id, title and date, and this is alredy availiable in the ZMI, and that means it doesn't have to be duplicated it. 2 Having two separate interfaces, one being the normal ZMI view, and the second being a ZMI tab where you order and sort the objects. There are benefits to this, for example it means that you can sort the ZMI object list without changing the ordering. It also keeps the main.dtml exactly as it is today, since the ordered support would instead add a separate tab, and it would keep the main display less cluttered. I do not as of today have an opinion on this last matter. When it comes to API, I would expect an API with two methods. One to move to a particular position, where 0 is first and -1 is last, as per normal Python standard, and the other where you move relatively, where negative numbers move you towards the front and positive towards the back. As an example of this I give you my OrderedDictionary.py, which have: def order(self, key, order) and def move(self, key, distance) There would also be functions to move a set of keys one step forward, one step backwards, first and last that are callable through the ZMI with a list of ids, to make it easier to do web user interfaces. I do have ONE opinion (wow!): I personally preferr the type of UI where you check the boxes of the objects you want to move, and then click a button to move all of them up/down/first/last as opposed to the UI that has one up/down/first/last button per object. Well, that's my take on all this. I'm sure I've missed some important stuff, but as I said, I got all confused by the discussion. ;) # (c) 2003 Nuxeo SARL <http://nuxeo.com> # An Ordered, Persistent dictionary. # Some code from David Benjamins odict # $Id: OrderedDictionary.py,v 1.3 2003/02/21 17:14:30 regebro Exp $ from types import ListType, TupleType from ZODB.PersistentMapping import PersistentMapping from ZODB.PersistentList import PersistentList class OrderedDictionary(PersistentMapping): def __init__(self, dict = None): if dict: self._keys = PersistentList(dict.keys()) else: self._keys = PersistentList() PersistentMapping.__init__(self, dict) def __delitem__(self, key): PersistentMapping.__delitem__(self, key) self._keys.remove(key) def __setitem__(self, key, item): PersistentMapping.__setitem__(self, key, item) if key not in self._keys: self._keys.append(key) def __cmp__(self, dict): if isinstance(dict, OrderedDictionary): return cmp(self.data, dict.data) and cmp(self._keys, dict._keys) else: return 0 def clear(self): PersistentMapping.clear(self) self._keys = PersistentList() def copy(self): mcopy = OrderedDictionary() mcopy.data = self.data.copy() mcopy._keys = self._keys[:] return mcopy def items(self): return zip(self._keys, self.values()) def keys(self): return self._keys[:] # This returns a non-persistent copy of self._keys, # so you can manipulate the copy without manipulating self._keys def popitem(self): try: key = self._keys[-1] except IndexError: raise KeyError('dictionary is empty') val = self[key] del self[key] return (key, val) def index(self, key): return self._keys.index(key) def setdefault(self, key, failobj = None): if key not in self._keys: self._keys.append(key) return PersistentMapping.setdefault(self, key, failobj) def update(self, dict): for (key,val) in dict.items(): self.__setitem__(key,val) def values(self): return map(self.get, self._keys) def order(self, key, order ): """Moves the specified item to the specifed position 0 is first, 1 is second, -1 is last, -1 second from last, and so on. """ if order < 0: order = len(self) + order # Negative numbers are counted from behind if order < 0: order = 0 # It's still negative: move first self._keys.remove(key) if order >= len(self._keys): self._keys.append(key) else: self._keys.insert(order, key) def move(self, key, distance): """Moves the specified item a number of positions Positive numbers move to higher index numbers, negavtive to lower index numbers""" oldpos = self.index(key) newpos = oldpos + distance if newpos < 0: newpos = 0 self.order(key, newpos)
Hi Lennart! Lennart Regebro wrote:
I'm all confused now.
I'll try to clear some things up: 1.) There is a complete implementation on yuppie-ordersupport-branch. I startet this branch to get feedback on implementation details and changes to the proposal. 2.) We have to structure the discussion the way you startet. use cases =========
For me, ordered support is useful in two cases:
1. For people want to make menues or lists of document/objects, and want them to be in a specific order. This requires ordering of the objects, and to display that ordering.
2. When you make objects and services that rely on an ordered list of subobjects. For example, say that you have a service of some kind that uses several plugins to perform functions, and it has to call these plugins in a particular order.
Is there anything I have missed?
Don't think so. But there are also special use cases why and how people do 1. or 2. UI ==
When it comes to UI, you need to have a way of ordering and sorting the objects, and of course displaying the cureent order. There are two ways to do that as I can see it.
1. Use the currentZMI object listing, "main.dtml". That saves you from having two user interfaces. It would be nice to have a sorting function too, to sort on id, title and date, and this is alredy availiable in the ZMI, and that means it doesn't have to be duplicated it.
2 Having two separate interfaces, one being the normal ZMI view, and the second being a ZMI tab where you order and sort the objects. There are benefits to this, for example it means that you can sort the ZMI object list without changing the ordering. It also keeps the main.dtml exactly as it is today, since the ordered support would instead add a separate tab, and it would keep the main display less cluttered.
I do not as of today have an opinion on this last matter.
Well. We chose to use main.dtml, but you just see the ordering UI if you switch to position sorting. API === This is the Interface we defined: <http://cvs.zope.org/Zope/lib/python/OFS/Attic/IOrderSupport.py?rev=1.1.2.2&content-type=text/vnd.viewcvs-markup>
When it comes to API, I would expect an API with two methods. One to move to a particular position, where 0 is first and -1 is last, as per normal Python standard, and the other where you move relatively, where negative numbers move you towards the front and positive towards the back.
As an example of this I give you my OrderedDictionary.py, which have: def order(self, key, order) and def move(self, key, distance)
Have a look at 'moveObjectsByDelta' and 'moveObjectToPosition'.
There would also be functions to move a set of keys one step forward, one step backwards, first and last that are callable through the ZMI with a list of ids, to make it easier to do web user interfaces.
'moveObjectsUp', 'moveObjectsDown', 'moveObjectsToTop' and 'moveObjectsToBottom'. again UI ========
I do have ONE opinion (wow!): I personally preferr the type of UI where you check the boxes of the objects you want to move, and then click a button to move all of them up/down/first/last as opposed to the UI that has one up/down/first/last button per object.
That's the way we did it. Cheers, Yuppie
Yuppie wrote:
This is the Interface we defined: <http://cvs.zope.org/Zope/lib/python/OFS/Attic/IOrderSupport.py?rev=1.1.2.2&content-type=text/vnd.viewcvs-markup>
Right, more or less as expected. Although the moveObjectsUp and moveObjectsDown, moveObjectsToTop and moveObjectsToBottom is a bit redundant it doesn't hurt to have them there either.
That's the way we did it.
Perfect. All that is left if then the question if it should be implemented more as a 'mixin' than as a replacement for ObjectManager. Since, as far as I understand from the code, the ordered support is really done by a mixin class, and the OrderedFolder is just a Fodler+OrderSupport, this is really how it is done already, as a mixin, where you have a list that contain an order of Id's. That means that the question of this being a replacement or a mixin is mostly a question of replacing the main.dtml or having a separate tab. As the code is now, OrderedFolder is using a replacement manage_main taken from OrderSupport. OrderSupport doesn't have a manage_main, so it will acquire it, but I assume this is just a temporary ommision, and that OrderSupport is supposed to have a specialized 'ordered_main.dtml'. It would in that case be no problems in supplying a management tag that only supplies ordering too, of you need ordering mixin, but can't override manage_main. The last question, as I understand it, is if the mixin should really be just a mixin where you not only order keys, but supply a storage for what should be ordered, so that the mixin has no ordering by itself, but instead order other sets. It would indeed be possible to do this, if these sets implement a standard ordering interface, for example the one above, or the simple ordering interface of being a list. It can be done, and quite simply, by replacing the references to self._objects with a call to a method, like this one: def getOrderStorage(self): return self._objects You could then override this getOrderStorage() method with whatever you want in your object, and get it to point to whatever. In this case, the order storage must be a list. Is this what you have been discussing, or have I misunderstood something?
Hi Lennart! Lennart Regebro wrote:
That means that the question of this being a replacement or a mixin is mostly a question of replacing the main.dtml or having a separate tab. As the code is now, OrderedFolder is using a replacement manage_main taken from OrderSupport. OrderSupport doesn't have a manage_main, so it will acquire it, but I assume this is just a temporary ommision, and that OrderSupport is supposed to have a specialized 'ordered_main.dtml'. It would in that case be no problems in supplying a management tag that only supplies ordering too, of you need ordering mixin, but can't override manage_main.
Ok. It isn't obvious what we did with manage_main: Quoting myself:
3.) For the ZMI, we use the same 'main.dtml' as the ObjectManager. This way we avoid redundant code and make it easier for products that need to change the 'main.dtml'.
The only reason OrderSupport has its own manage_options is that OrderSupport has its own help file. main.dtml has some sections like: <dtml-if hasOrderSupport> ... </dtml-if> We couldn't find a way to do something similar with the help file. I'm not sure if I did get your destinction between mixin and replacement.
The last question, as I understand it, is if the mixin should really be just a mixin where you not only order keys, but supply a storage for what should be ordered, so that the mixin has no ordering by itself, but instead order other sets. It would indeed be possible to do this, if these sets implement a standard ordering interface, for example the one above, or the simple ordering interface of being a list.
It can be done, and quite simply, by replacing the references to self._objects with a call to a method, like this one:
def getOrderStorage(self): return self._objects
You could then override this getOrderStorage() method with whatever you want in your object, and get it to point to whatever. In this case, the order storage must be a list.
Is this what you have been discussing, or have I misunderstood something?
I guess the main point is to have an implementation that allows to add or remove OrderSupport and IndexSupport like a local service, without changing the Folder class itself. But Magnus should better know if you did get his point. Cheers, Yuppie
Yuppie wrote:
I guess the main point is to have an implementation that allows to add or remove OrderSupport and IndexSupport like a local service, without changing the Folder class itself.
Ah.
But Magnus should better know if you did get his point.
Nope, totally missed it, and I can't really see any use cases for it. If Magnus can come up with any I'd be interested, but it seems complicated though.
hi all. I just caught this and excited to see this discussion. I have been using OrderedFolder for a while and not aware of OrderedObjectManager. My inquiry is more about implementation. I have a requirement on my plate right now to develop an interface to enable a user to custom order about 350 items. For simplicity, I have decided not to allow batching for now and make them do the reordering on one large page. I agree that moveObjectsToTop and moveObjectsToBottom are great API as long as they subclass moveObjectsUp and moveObjectsDown. I mainly want to use these methods outside the ZMI for a custom report that displays more custom data that assists the user in ordering (mainly meta-properties of the objects). It would also be great to be able to use the same scripts for data in an RDB as well. ex: each table would be required to have a 'position' that is altered by the OrderSuuport. anyway... I think the real challenge is in the usability of using serialized "position #'s". the current UI is completely unusable to make object "jump" position. And how do you handle it when multiple objects are selected to "jump".? I am currently getting usability feedback from the users on this issue. The feedback so far is to let the "position" be altered inline with the object. And I also think... OrderedObjectManager should be an optional attribute on a container. Because of the interface bloat, I am leery of something like this that forces itself onto every container, whether you need ordering or not. I apologize if I am very late in the discussion and missing some facts here. Thanks, Trevor
-----Original Message----- From: zope-dev-admin@zope.org [mailto:zope-dev-admin@zope.org]On Behalf Of Lennart Regebro Sent: Wednesday, May 07, 2003 8:38 AM To: Yuppie; zope-dev@zope.org Subject: [Zope-dev] Re: Zope 2.7: OrderSupport for ObjectManager
Yuppie wrote:
This is the Interface we defined:
<http://cvs.zope.org/Zope/lib/python/OFS/Attic/IOrderSupport.py?re v=1.1.2.2&content-type=text/vnd.viewcvs-markup>
Right, more or less as expected. Although the moveObjectsUp and moveObjectsDown, moveObjectsToTop and moveObjectsToBottom is a bit redundant it doesn't hurt to have them there either.
That's the way we did it.
Perfect.
All that is left if then the question if it should be implemented more as a 'mixin' than as a replacement for ObjectManager. Since, as far as I understand from the code, the ordered support is really done by a mixin class, and the OrderedFolder is just a Fodler+OrderSupport, this is really how it is done already, as a mixin, where you have a list that contain an order of Id's.
That means that the question of this being a replacement or a mixin is mostly a question of replacing the main.dtml or having a separate tab. As the code is now, OrderedFolder is using a replacement manage_main taken from OrderSupport. OrderSupport doesn't have a manage_main, so it will acquire it, but I assume this is just a temporary ommision, and that OrderSupport is supposed to have a specialized 'ordered_main.dtml'. It would in that case be no problems in supplying a management tag that only supplies ordering too, of you need ordering mixin, but can't override manage_main.
The last question, as I understand it, is if the mixin should really be just a mixin where you not only order keys, but supply a storage for what should be ordered, so that the mixin has no ordering by itself, but instead order other sets. It would indeed be possible to do this, if these sets implement a standard ordering interface, for example the one above, or the simple ordering interface of being a list.
It can be done, and quite simply, by replacing the references to self._objects with a call to a method, like this one:
def getOrderStorage(self): return self._objects
You could then override this getOrderStorage() method with whatever you want in your object, and get it to point to whatever. In this case, the order storage must be a list.
Is this what you have been discussing, or have I misunderstood something?
_______________________________________________ Zope-Dev maillist - Zope-Dev@zope.org http://mail.zope.org/mailman/listinfo/zope-dev ** No cross posts or HTML encoding! ** (Related lists - http://mail.zope.org/mailman/listinfo/zope-announce http://mail.zope.org/mailman/listinfo/zope )
Hello Yuppie! I was initially somewhat uncomfortable with the fact that you have changed the ordering API completely. Where has 'move_object_up' gone, and where is 'manage_move_object_up'? Is there an upgrade path for code using the classic API of OrderedFolder or the OrderedFolderSupportPatch? Well, at least the names do not collide and both APIs will be able to coexist. ;-) I am however less convinced about the changes you made to the Folder class on Friday: <http://cvs.zope.org/Zope/lib/python/OFS/Folder.py.diff?r1=1.101.66.1&r2=1. 101.66.2&only_with_tag=yuppie-ordersupport-branch> Adding an __init__() method is quite a significant change! Furthermore, the way you did it alters the behaviour of the Folder class which is not acceptable. If you absolutely want to add a Folder constructor, please do it in a b/w compatible way. I suggest you consider the implementation proposed here: <http://mail.zope.org/pipermail/zope-dev/2002-July/016913.html> Oh, and the up/down GIFs are hideous. ;-) IMO, Stefan --On Montag, 05. Mai 2003 13:35 +0200 Yuppie <schubbe@web.de> wrote:
Implementing the OrderedObjectManager proposal, we fleshed it out and modified it a bit. I made an initial checkin on a branch which reflects our current thinking. So this is your chance to discuss the changes before we merge it into the trunk.
The code: yuppie-ordersupport-branch (Creating the branch went wrong a bit. Please just checkout lib/python/AccessControl, lib/python/OFS and lib/python/Products/OFSP.)
The original proposal: <http://dev.zope.org/Wikis/DevSite/Proposals/OrderedObjectManager>
-- The time has come to start talking about whether the emperor is as well dressed as we are supposed to think he is. /Pete McBreen/
Hi Stefan! Thanks for your feedback. Stefan H. Holek wrote:
I was initially somewhat uncomfortable with the fact that you have changed the ordering API completely. Where has 'move_object_up' gone, and where is 'manage_move_object_up'? Is there an upgrade path for code using the classic API of OrderedFolder or the OrderedFolderSupportPatch?
I don't know what you mean by the "classic API of OrderedFolder". The last version of the OrderedFolder product has no 'move_object_up' and no 'manage_move_object_up' method. The OrderedFolderSupportPatch has no 'manage_move_object_up', just a 'move_object_up' method. We can't provide backwards compatibility to all versions of the ordering API that exist. I might change the manage_ methods in OrderSupport so they take the arguments in the same order as the OrderedFolder product.
I am however less convinced about the changes you made to the Folder class on Friday:
<http://cvs.zope.org/Zope/lib/python/OFS/Folder.py.diff?r1=1.101.66.1&r2=1. 101.66.2&only_with_tag=yuppie-ordersupport-branch>
Adding an __init__() method is quite a significant change! Furthermore, the way you did it alters the behaviour of the Folder class which is not acceptable. If you absolutely want to add a Folder constructor, please do it in a b/w compatible way. I suggest you consider the implementation proposed here: <http://mail.zope.org/pipermail/zope-dev/2002-July/016913.html>
I did that on request of Florent and thought it would be a no-brainer. <http://mail.zope.org/pipermail/zope-checkins/2003-April/022598.html> But apparently I did it wrong. Would it be ok to change it to: def __init__(id=None): if id is not None: self.id = str(id) Or should I revert that change completely?
Oh, and the up/down GIFs are hideous. ;-)
You are missing the up/down buttons on the right side? They were a redundant UI and broke the ZMI UI philosophy: 1. select the items 2. select the action Cheers, Yuppie
--On Montag, 05. Mai 2003 20:41 +0200 Yuppie <schubbe@web.de> wrote:
Stefan H. Holek wrote:
<http://mail.zope.org/pipermail/zope-dev/2002-July/016913.html>
I did that on request of Florent and thought it would be a no-brainer. <http://mail.zope.org/pipermail/zope-checkins/2003-April/022598.html>
But apparently I did it wrong. Would it be ok to change it to:
def __init__(id=None): if id is not None: self.id = str(id)
Or should I revert that change completely?
Why not add the title as well? It seems common for constructors that accept an id parameter to also accept a title.
Oh, and the up/down GIFs are hideous. ;-)
You are missing the up/down buttons on the right side?
Nah, I'm not missing them at all. I was referring to the screenshot on Maik's page. If you say they are gone I'm fine. ;-) Stefan -- The time has come to start talking about whether the emperor is as well dressed as we are supposed to think he is. /Pete McBreen/
Stefan H. Holek wrote:
Oh, and the up/down GIFs are hideous. ;-)
You are missing the up/down buttons on the right side?
Nah, I'm not missing them at all. I was referring to the screenshot on Maik's page. If you say they are gone I'm fine. ;-)
You're right, they are ugly... ;) But they make things sometimes a little bit easier for visual oriented users. And I have a lot of them... As Yuppie already said, they are only integrated in the OrderedObjectManager-Product and will not be integrated in the OrderSupport for Zope2.7. Cheers, Maik
Hi Stefan! Stefan H. Holek wrote:
--On Montag, 05. Mai 2003 20:41 +0200 Yuppie <schubbe@web.de> wrote:
Stefan H. Holek wrote:
<http://mail.zope.org/pipermail/zope-dev/2002-July/016913.html>
I did that on request of Florent and thought it would be a no-brainer. <http://mail.zope.org/pipermail/zope-checkins/2003-April/022598.html>
But apparently I did it wrong. Would it be ok to change it to:
def __init__(id=None): if id is not None: self.id = str(id)
Or should I revert that change completely?
Why not add the title as well? It seems common for constructors that accept an id parameter to also accept a title.
ZopePageTemplate and PythonScript constructors don't accept title. Florent just asked for id. But I can live with both solutions. Cheers, Yuppie
In article <3EB78D0E.3030903@web.de> you write:
<http://mail.zope.org/pipermail/zope-dev/2002-July/016913.html>
I did that on request of Florent and thought it would be a no-brainer. <http://mail.zope.org/pipermail/zope-checkins/2003-April/022598.html>
But apparently I did it wrong. Would it be ok to change it to:
def __init__(id=None): if id is not None: self.id = str(id)
Or should I revert that change completely?
Why not add the title as well? It seems common for constructors that accept an id parameter to also accept a title.
ZopePageTemplate and PythonScript constructors don't accept title. Florent just asked for id. But I can live with both solutions.
I think that having the constructor set id is the thing that minimises surprises. But that's just a small cleanup I requested, if it poses problem just forget about it. Florent -- Florent Guillaume, Nuxeo (Paris, France) +33 1 40 33 79 87 http://nuxeo.com mailto:fg@nuxeo.com
Well, you're the one with checkin privileges ;-) If I was to add that constructor I'd include the title param as well. The only currently existing constructor in the OFS package (File/Image) *does* accept title... Stefan --On Dienstag, 06. Mai 2003 12:23 +0200 Yuppie <schubbe@web.de> wrote:
ZopePageTemplate and PythonScript constructors don't accept title. Florent just asked for id. But I can live with both solutions.
-- The time has come to start talking about whether the emperor is as well dressed as we are supposed to think he is. /Pete McBreen/
Implementing the OrderedObjectManager proposal, we fleshed it out and modified it a bit. I made an initial checkin on a branch which reflects our current thinking. So this is your chance to discuss the changes before we merge it into the trunk.
I would rather see OrderedObjectManager not being a container/folder. It should be a type that you can add, configure from where to get ids, and a way to order and/or sort. That would be much more flexible, and not depend on the implementation of the actual folder. imho -- /Magnus
Hi Magnus! Magnus Heino wrote:
Implementing the OrderedObjectManager proposal, we fleshed it out and modified it a bit. I made an initial checkin on a branch which reflects our current thinking. So this is your chance to discuss the changes before we merge it into the trunk.
I would rather see OrderedObjectManager not being a container/folder. It should be a type that you can add, configure from where to get ids, and a way to order and/or sort.
You mean an object of that type should be placed inside the container?
That would be much more flexible, and not depend on the implementation of the actual folder.
It's a bit late to bring that up. The proposal was OK'ed months ago. Cheers, Yuppie
participants (12)
-
Andrew Sawyers -
Chris McDonough -
Florent Guillaume -
Lennart Regebro -
Magnus Heino -
Magnus Heino -
Maik Jablonski -
Shane Hathaway -
Stefan H. Holek -
Toby Dickenson -
Trevor Toenjes -
Yuppie