[Zope3-dev] Notations for paths
Phillip J. Eby
pje@telecommunity.com
Thu, 19 Dec 2002 13:01:47 -0500
At 06:15 PM 12/19/02 +0100, Florent Guillaume wrote:
>On Thu, 2002-12-19 at 18:01, Phillip J. Eby wrote:
> > >So, there are special functions for correctly converting between the
> > >string form and the tuple form.
> > >
> > >I've had to correct a number of bugs where the naive conversion had been
> > >used. These bugs were somewhat tricky to track down, becuase the effects
> > >didn't point to this as the obvious cause.
> >
> > I think you missed my point. This is *precisely* why Zope shouldn't
> use an
> > unencapsulated representation like tuples for this in the first place!
> >
> > Nobody should be doing any conversions directly. There should be a
> > location class, and only strings or instances of the location class should
> > be allowed. Code which uses locations should invoke the location
> > constructor on any input, to ensure that strings become locations.
>
>Why go to those lengths when we can have a perfectly effective location
>as a tuple of names in trivial bijection with a string?
What lengths? Having a class? Calling it? Seems to me like very little
work to ensure correct behavior. Heck, I'll write the class myself, if you
want. :)
The point is that it's bad design to:
1) shuffle around tuples for something that *isn't* a tuple
2) Create functions for manipulating tuples that people are supposed to use
(but won't, because it'll seem too simple to just "do it themselves" and
manipulate the tuple directly)
Now that it has become clear that it doesn't work, the simple and obvious
solution is to subclass tuple, i.e.:
from types import StringTypes
class ZopeLocation(tuple):
def __new__(klass, stringOrLocation):
if isinstance(stringOrLocation,klass):
return stringOrLocation
if isinstance(stringOrLocation,StringTypes):
path = stringOrLocation.split('/')
if not filter(None,path):
# string was all '/'... remove one empty element
path.pop()
return super(ZopeLocation,klass).__new__(klass,path)
raise TypeError("Not a string or location", stringOrLocation)
def __str__(self):
path = list(self):
if not filter(None,path):
# all empty parts, add one extra
path.append('')
return '/'.join(path)
def traverse(self, start):
# XXX do something useful...
def commonPrefix(self,other):
# XXX do something useful...
# etc...
Now any other functionality associated with locations can be added to the
class. And, if it's decided the string format or the internal
representation needs to be different for some reason, why then it can be
changed in one place. And, because nobody knows it's a tuple unless they
read the code, they won't go messing with it and spreading bugs all over
the place. (Even if they do know it's a tuple, my example specifically
disallows conversion from tuples.)
If y'all think path manipulation problems are widespread *now*, just wait
till non-core Zope developers get a hold of it.