commit | author | age
|
cbdc36
|
1 |
############################################################################## |
CM |
2 |
# |
|
3 |
# Copyright (c) 2003 Zope Corporation and Contributors. |
|
4 |
# All Rights Reserved. |
|
5 |
# |
|
6 |
# This software is subject to the provisions of the Zope Public License, |
|
7 |
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. |
|
8 |
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED |
|
9 |
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
|
10 |
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS |
|
11 |
# FOR A PARTICULAR PURPOSE. |
|
12 |
# |
|
13 |
############################################################################## |
|
14 |
|
0c29cf
|
15 |
|
3e2f12
|
16 |
def inside(resource1, resource2): |
CM |
17 |
"""Is ``resource1`` 'inside' ``resource2``? Return ``True`` if so, else |
cbdc36
|
18 |
``False``. |
CM |
19 |
|
3e2f12
|
20 |
``resource1`` is 'inside' ``resource2`` if ``resource2`` is a |
CM |
21 |
:term:`lineage` ancestor of ``resource1``. It is a lineage ancestor |
8b1f6e
|
22 |
if its parent (or one of its parent's parents, etc.) is an |
CM |
23 |
ancestor. |
cbdc36
|
24 |
""" |
3e2f12
|
25 |
while resource1 is not None: |
CM |
26 |
if resource1 is resource2: |
cbdc36
|
27 |
return True |
3e2f12
|
28 |
resource1 = resource1.__parent__ |
cbdc36
|
29 |
|
CM |
30 |
return False |
0c29cf
|
31 |
|
cbdc36
|
32 |
|
3e2f12
|
33 |
def lineage(resource): |
cbdc36
|
34 |
""" |
8b1f6e
|
35 |
Return a generator representing the :term:`lineage` of the |
3e2f12
|
36 |
:term:`resource` object implied by the ``resource`` argument. The |
CM |
37 |
generator first returns ``resource`` unconditionally. Then, if |
f4f41f
|
38 |
``resource`` supplies a ``__parent__`` attribute, return the resource |
CM |
39 |
represented by ``resource.__parent__``. If *that* resource has a |
|
40 |
``__parent__`` attribute, return that resource's parent, and so on, |
|
41 |
until the resource being inspected either has no ``__parent__`` |
8b1f6e
|
42 |
attribute or which has a ``__parent__`` attribute of ``None``. |
f4f41f
|
43 |
For example, if the resource tree is:: |
cbdc36
|
44 |
|
CM |
45 |
thing1 = Thing() |
|
46 |
thing2 = Thing() |
|
47 |
thing2.__parent__ = thing1 |
|
48 |
|
|
49 |
Calling ``lineage(thing2)`` will return a generator. When we turn |
|
50 |
it into a list, we will get:: |
a54bc1
|
51 |
|
cbdc36
|
52 |
list(lineage(thing2)) |
CM |
53 |
[ <Thing object at thing2>, <Thing object at thing1> ] |
|
54 |
""" |
3e2f12
|
55 |
while resource is not None: |
CM |
56 |
yield resource |
02e1fe
|
57 |
# The common case is that the AttributeError exception below |
CM |
58 |
# is exceptional as long as the developer is a "good citizen" |
|
59 |
# who has a root object with a __parent__ of None. Using an |
|
60 |
# exception here instead of a getattr with a default is an |
|
61 |
# important micro-optimization, because this function is |
|
62 |
# called in any non-trivial application over and over again to |
|
63 |
# generate URLs and paths. |
|
64 |
try: |
3e2f12
|
65 |
resource = resource.__parent__ |
02e1fe
|
66 |
except AttributeError: |
3e2f12
|
67 |
resource = None |