Skip to content

Commit 24bb42e

Browse files
committed
Disallow full=True in _bytecode_nameof for nameof
1 parent 842a964 commit 24bb42e

File tree

2 files changed

+29
-7
lines changed

2 files changed

+29
-7
lines changed

tests/test_varname.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -647,15 +647,21 @@ def test_nameof_full():
647647
# we are not able to retreive full names without source code available
648648
with pytest.raises(
649649
VarnameRetrievingError,
650-
match='Are you trying to call nameof from evaluation'
650+
match='Are you trying to call nameof from exec/eval'
651651
):
652-
eval('nameof(a.b.c, full=True)')
652+
eval('nameof(a.b, full=False)')
653+
654+
with pytest.raises(
655+
VarnameRetrievingError,
656+
match='Cannot retrieve full name by nameof'
657+
):
658+
eval('nameof(a.b, full=True)')
653659

654660
def test_nameof_from_stdin():
655661
code = ('from varname import nameof; '
656662
'x = lambda: 0; '
657663
'x.y = x; '
658-
'print(nameof(x.y, full=True))')
664+
'print(nameof(x.y, full=False))')
659665
p = subprocess.Popen([sys.executable],
660666
stdin=subprocess.PIPE,
661667
stdout=subprocess.PIPE,

varname.py

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,16 @@ def nameof(var, *more_vars, # pylint: disable=unused-argument
180180
181181
>>> x = lambda: None
182182
>>> x.y = 1
183-
>>> nameof(x.y) # 'x.y'
183+
>>> nameof(x.y, full=True) # 'x.y'
184+
185+
Note:
186+
This function works with the environments where source code is
187+
available, in other words, the callee's node can be retrieved by
188+
`executing`. In some cases, for example, running code from python
189+
shell/REPL or from `exec`/`eval`, we try to fetch the variable name
190+
from the bytecode. This requires only a single variable name is passed
191+
to this function and no keyword arguments, meaning that getting full
192+
names of attribute calls are not supported in such cases.
184193
185194
Args:
186195
var: The variable to retrieve the name of
@@ -200,10 +209,16 @@ def nameof(var, *more_vars, # pylint: disable=unused-argument
200209
"""
201210
node = _get_node(caller - 1, raise_exc=True)
202211
if not node:
212+
if full:
213+
raise VarnameRetrievingError(
214+
"Cannot retrieve full name by nameof when called "
215+
"in shell/REPL, exec/eval or other situations "
216+
"where sourcecode is unavailable."
217+
)
203218
# only works with nameof(a) or nameof(a.b)
204219
# no keyword arguments is supposed to be passed in
205220
# that means we cannot retrieve the full name without
206-
# soucecode available and you can't wrap this function in such a case
221+
# sourcecode available
207222
if not more_vars:
208223
return _bytecode_nameof(caller + 1)
209224
raise VarnameRetrievingError("Unable to retrieve callee's node.")
@@ -362,7 +377,7 @@ def _bytecode_nameof(caller: int = 1) -> str:
362377
def _bytecode_nameof_cached(code: CodeType, offset: int, source: str) -> str:
363378
"""Cached Bytecode version of nameof
364379
365-
We are trying this version only when the soucecode is unavisible. In most
380+
We are trying this version only when the sourcecode is unavisible. In most
366381
cases, this will happen when user is trying to run a script in REPL/
367382
python shell, with `eval`, or other circumstances where the code is
368383
manipulated to run but sourcecode is not available.
@@ -383,7 +398,7 @@ def _bytecode_nameof_cached(code: CodeType, offset: int, source: str) -> str:
383398
)
384399
if source == '<string>':
385400
raise VarnameRetrievingError(
386-
"Are you trying to call nameof from evaluation? "
401+
"Are you trying to call nameof from exec/eval? "
387402
"In such a case, nameof can only be called with single "
388403
"argument and no keyword arguments."
389404
)
@@ -392,6 +407,7 @@ def _bytecode_nameof_cached(code: CodeType, offset: int, source: str) -> str:
392407
name_instruction = instructions[
393408
current_instruction_index - 1
394409
]
410+
395411
if not name_instruction.opname.startswith("LOAD_"):
396412
raise VarnameRetrievingError("Argument must be a variable or attribute")
397413

0 commit comments

Comments
 (0)