Skip to content

Commit 35cc085

Browse files
committed
-
1 parent 741dff3 commit 35cc085

File tree

5 files changed

+55
-5
lines changed

5 files changed

+55
-5
lines changed

source_py2/python_toolbox/misc_tools/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
_ascii_variable_pattern, is_legal_ascii_variable_name,
99
is_magic_variable_name, get_actual_type, is_number, identity_function,
1010
do_nothing, OwnNameDiscoveringDescriptor, find_clear_place_on_circle,
11-
general_sum, general_product, is_legal_email_address, is_type, NonInstatiable
11+
general_sum, general_product, is_legal_email_address, is_type, NonInstatiable,
12+
repeat_getattr
1213
)
1314
from . import name_mangling
1415
from .proxy_property import ProxyProperty

source_py2/python_toolbox/misc_tools/misc_tools.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -284,4 +284,21 @@ class NonInstatiable(object):
284284
constants and settings.
285285
'''
286286
def __new__(self, *args, **kwargs):
287-
raise RuntimeError('This class may not be instatiated.')
287+
raise RuntimeError('This class may not be instatiated.')
288+
289+
def repeat_getattr(thing, query):
290+
'''
291+
Perform a repeated `getattr` operation.
292+
293+
i.e., when given `repeat_getattr(x, '.y.z')`, will return `x.y.z`.
294+
'''
295+
if not query:
296+
return thing
297+
assert isinstance(query, str)
298+
if not query.startswith('.'):
299+
raise Exception('''`query` must start with '.', e.g. '.foo.bar.baz'.''')
300+
attribute_names = filter(None, query.split('.'))
301+
current = thing
302+
for attribute_name in attribute_names:
303+
current = getattr(current, attribute_name)
304+
return current

source_py2/python_toolbox/temp_value_setting/temp_value_setter.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
See its documentation for more details.
88
'''
99

10-
from python_toolbox import address_tools
1110
from python_toolbox.context_management import ContextManager
1211

1312

source_py2/test_python_toolbox/test_address_tools/test_describe.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,7 @@
1010
from python_toolbox.temp_value_setting import TempValueSetter
1111

1212
import python_toolbox
13-
from python_toolbox.address_tools import (describe,
14-
resolve)
13+
from python_toolbox.address_tools import describe, resolve
1514

1615
# todo: Make test that when a root or namespace is given, it's top priority to
1716
# use it, even if it prevents shorterning and results in an overall longer
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# Copyright 2009-2013 Ram Rachum.
2+
# This program is distributed under the MIT license.
3+
4+
'''Testing module for name demangling.'''
5+
6+
from python_toolbox import cute_testing
7+
8+
from python_toolbox.misc_tools import repeat_getattr
9+
10+
11+
class Object(object):
12+
def __init__(self, tag):
13+
self.tag = tag
14+
__eq__ = lambda self, other: (self.tag == other.tag)
15+
16+
17+
x = Object('x')
18+
x.y = Object('y')
19+
x.y.z = Object('z')
20+
x.y.meow = Object('meow')
21+
22+
23+
def test():
24+
assert repeat_getattr(x, None) == repeat_getattr(x, '') == x
25+
with cute_testing.RaiseAssertor():
26+
repeat_getattr(x, 'y')
27+
28+
assert x != x.y != x.y.z != x.y.meow
29+
assert repeat_getattr(x, '.y') == x.y
30+
assert repeat_getattr(x, '.y.z') == x.y.z
31+
assert repeat_getattr(x, '.y.meow') == x.y.meow
32+
33+
assert repeat_getattr(x.y, '.meow') == x.y.meow
34+
assert repeat_getattr(x.y, '.z') == x.y.z

0 commit comments

Comments
 (0)