Skip to content

Commit ff3bfbf

Browse files
committed
Remodel will for better logic
1 parent c58d3d8 commit ff3bfbf

File tree

2 files changed

+43
-19
lines changed

2 files changed

+43
-19
lines changed

tests/test_varname.py

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -410,14 +410,34 @@ def do(self):
410410
result = c.iwill.do()
411411
assert result == 'I will do something'
412412

413+
def test_will_malformat():
414+
"""Function will has to be used in the format of `inst.attr` or
415+
`inst.attr()`"""
416+
class C1:
417+
def __getitem__(self, name):
418+
return will(raise_exc=True)
419+
420+
class C2:
421+
def __getitem__(self, name):
422+
return will(raise_exc=False)
423+
424+
c1 = C1()
425+
with pytest.raises(VarnameRetrievingError):
426+
c1[1]
427+
428+
c2_will = C2()[1]
429+
assert c2_will is None
430+
413431
def test_will_fail():
414432

415-
def get_will():
416-
return {'a': will(raise_exc=True)}
433+
def get_will(raise_exc):
434+
return will(raise_exc=raise_exc)
417435

418436
with pytest.raises(VarnameRetrievingError):
419-
get_will()['a']
437+
get_will(True)
420438

439+
the_will = get_will(False)
440+
assert the_will is None
421441

422442
def test_frame_fail(no_getframe):
423443
"""Test when failed to retrieve the frame"""

varname.py

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -160,24 +160,28 @@ def i_will():
160160
raise VarnameRetrievingError("Unable to retrieve the frame.")
161161
return None
162162

163-
ret = None
164-
try:
165-
# have to be used in a call
166-
assert isinstance(node, (ast.Attribute, ast.Call)), (
167-
"Invalid use of function `will`"
168-
)
169-
node = node.parent
170-
except (AssertionError, AttributeError):
171-
pass
172-
else:
173-
if isinstance(node, ast.Attribute):
174-
ret = node.attr
163+
# have to be called like: inst.attr or inst.attr()
164+
# see test_will_malformat
165+
if not isinstance(node, (ast.Attribute, ast.Call)):
166+
if raise_exc:
167+
raise VarnameRetrievingError("Invalid use of function `will`")
168+
return None
175169

176-
if not ret and raise_exc:
177-
raise VarnameRetrievingError('Unable to retrieve the '
178-
'next attribute name')
170+
if isinstance(node, ast.Call):
171+
# try to get not inst.attr from inst.attr()
172+
# seemingly ast.Call always has parent, at least, ast.Expr
173+
node = node.parent
179174

180-
return ret
175+
# see test_will_fail
176+
if not isinstance(node, ast.Attribute):
177+
if raise_exc:
178+
raise VarnameRetrievingError(
179+
"Function `will` has to be called within "
180+
"a method/property of a class."
181+
) from None
182+
return None
183+
# ast.Attribute
184+
return node.attr
181185

182186
def inject(obj):
183187
"""Inject attribute `__varname__` to an object

0 commit comments

Comments
 (0)