[Zope-dev] TreeVocabulary in zope.schema.vocabulary
Jan-Carel Brand
lists at opkode.com
Mon Jan 30 13:33:16 UTC 2012
On Sun, 2012-01-29 at 16:17 +0100, Charlie Clark wrote:
<snip>
> > From the zope.schema 4.0.0 release notes:
> > "Port to Python 3. This adds a dependency on six and removes support for
> > Python 2.5"
>
> Shouldn't that also mean a preference of
> "for key in _dict" over "for key in _dict.keys()" ?
>
> Though you might prefer .items() in _getPathToTreeNode()
>
> i.e
> def _getPathToTreeNode(self, tree, node)
>
> path = []
> for parent, child in tree.items():
> if node == parent.value:
> return [node]
> path = self._getPathToTreeNode(child, node)
> if path:
> path.insert(0, parent.value)
> break
> return path
Thanks, I've taken this code from the diff file you gave.
> > So if we want to use OrderedDict (which is from Python >= 2.7), we just
> > need to bridge the Python 2.6 version with the ordereddict package:
> > http://pypi.python.org/pypi/ordereddict/1.1
> > This would introduce a new dependency for zope.schema on Python 2.6, I
> > don't know if that's acceptable or not.
>
> I think it's perfectly justified in this case and similar to what has
> happened with other libraries like ElementTree in the past that have made
> life easier and subsequently been adopted by the standard library.
Marius and Souheil, what do you think about this? I think it probably
still makes sense to have a dict_factory as Souheil suggested, but then
we make the default type OrderedDict and not dict.
Any objections?
> > In setup.py one could specify the extra dependency only for Python <
> > 2.7:
> >
> >> import sys
> >>
> >> REQUIRES = ['setuptools',
> >> 'zope.interface >= 3.6.0',
> >> 'zope.event',
> >> 'six',
> >> ]
> >>
> >> if sys.version_info < (2 , 7):
> >> REQUIRES += ['ordereddict'],
> >>
> >> setup(
> >> # [...]
> >> install_requires=REQUIRES,
> >> # [...]
>
> Yep.
<snip>
> > I however don't see how one could use a generator for the recursive
> > methods that return dictionaries.
> > With regards to the "recurse" method (now called _getPathToTreeNode), I
> > don't see how one could use a generator in a more efficient manner than
> > the normal recursion that's being used currently.
> > I played around with it and the best I could come up with is this:
> > def generator(_dict, value, path=[]):
> > if value in _dict.keys():
> > yield path+[value]
> > for key in _dict.keys():
> > for path in recurse(_dict[key], value, path+[key]):
> > if value in path:
> > yield path
> > You still have to recurse through the different branches until you find
> > the node that you are looking for and you still need to store the path
> > in a list. So what would be the added value?
> > What's more, the generator returns a list within a list, like so:
> > [['Regions', 'Germany', 'Bavaria']], which I find clunky.
>
> You're probably right. I think I was getting ahead of myself wondering
> about possible issues with deeply nested vocabularies.
> Any real improvement would probably involve a node index.
> I notice that the examples do not allow for departments in regions to have the same name as
> the region (common enough in some countries) so you could simply add the
> index keyed by node value with the path as the value when the class is
> created.
Yes, the values must be unique, because we do value lookups.
The "title" attr doesn't have to be unique though. You could have a
"Forestry" department for two different regions. The title will be the
same, but the value and token attrs can't.
> This should be possible by calling _getPathToTreeNode during one
> of the passes through _flattenTree. getTermPath would then just need to do
> a lookup on this.
I don't like the way the path_node gets implicitly populated during a
call to _flattenTree.
I'd rather have a separate method that calculates the path and then
explicitly assign it to self.path_node.
In any case, there is now a node_index in the code :)
<snip>
> >> but I don't see the advantage of
> >> cls.createTerm(*args) over SimpleTerm(*args)
> > See above. "createTerm" is there to let developers override it and
> > provide their own term objects.
>
> Do you have a concrete use case for this?
Not really, but that doesn't mean it doesn't exist.
> Remember that createTerm is a
> convenience method only. Frankly, I don't see the need for it in what is a
> fairly specialised class.
I like consistency and symmetry, so if SimpleVocabulary has it, as an
add-on developer I'd expect for TreeVocabulary to also have it.
I don't however feel very strongly about it though, and I wanna get this
done, so I removed it.
J-C
More information about the Zope-Dev
mailing list