varname 0.13.4__py3-none-any.whl → 0.14.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
varname/__init__.py CHANGED
@@ -11,6 +11,6 @@ from .utils import (
11
11
  MaybeDecoratedFunctionWarning,
12
12
  UsingExecWarning,
13
13
  )
14
- from .core import varname, nameof, will, argname
14
+ from .core import varname, will, argname
15
15
 
16
- __version__ = "0.13.4"
16
+ __version__ = "0.14.0"
varname/core.py CHANGED
@@ -1,13 +1,13 @@
1
1
  """Provide core features for varname"""
2
+ from __future__ import annotations
2
3
  import ast
3
4
  import re
4
5
  import warnings
5
- from typing import Any, List, Union, Tuple, Type, Callable, overload
6
+ from typing import List, Union, Tuple, Type, Callable, overload
6
7
 
7
8
  from executing import Source
8
9
 
9
10
  from .utils import (
10
- bytecode_nameof,
11
11
  get_node,
12
12
  get_node_by_frame,
13
13
  lookfor_parent_assign,
@@ -217,134 +217,6 @@ def will(frame: int = 1, raise_exc: bool = True) -> str:
217
217
  return node.attr
218
218
 
219
219
 
220
- @overload
221
- def nameof(
222
- var: Any,
223
- *,
224
- frame: int = 1,
225
- vars_only: bool = True,
226
- ) -> str: # pragma: no cover
227
- ...
228
-
229
-
230
- @overload
231
- def nameof(
232
- var: Any,
233
- more_var: Any,
234
- /, # introduced in python 3.8
235
- *more_vars: Any,
236
- frame: int = 1,
237
- vars_only: bool = True,
238
- ) -> Tuple[str, ...]: # pragma: no cover
239
- ...
240
-
241
-
242
- def nameof(
243
- var: Any,
244
- *more_vars: Any,
245
- frame: int = 1,
246
- vars_only: bool = True,
247
- ) -> Union[str, Tuple[str, ...]]:
248
- """Get the names of the variables passed in
249
-
250
- Examples:
251
- >>> a = 1
252
- >>> nameof(a) # 'a'
253
-
254
- >>> b = 2
255
- >>> nameof(a, b) # ('a', 'b')
256
-
257
- >>> x = lambda: None
258
- >>> x.y = 1
259
- >>> nameof(x.y, vars_only=False) # 'x.y'
260
-
261
- Note:
262
- This function works with the environments where source code is
263
- available, in other words, the callee's node can be retrieved by
264
- `executing`. In some cases, for example, running code from python
265
- shell/REPL or from `exec`/`eval`, we try to fetch the variable name
266
- from the bytecode. This requires only a single variable name is passed
267
- to this function and no keyword arguments, meaning that getting full
268
- names of attribute calls are not supported in such cases.
269
-
270
- Args:
271
- var: The variable to retrieve the name of
272
- *more_vars: Other variables to retrieve the names of
273
- frame: The this function is called from the wrapper of it. `frame=1`
274
- means no wrappers.
275
- Note that the calls from standard libraries are ignored.
276
- Also note that the wrapper has to have signature as this one.
277
- vars_only: Whether only allow variables/attributes as arguments or
278
- any expressions. If `False`, then the sources of the arguments
279
- will be returned.
280
-
281
- Returns:
282
- The names/sources of variables/expressions passed in.
283
- If a single argument is passed, return the name/source of it.
284
- If multiple variables are passed, return a tuple of their
285
- names/sources.
286
- If the argument is an attribute (e.g. `a.b`) and `vars_only` is
287
- `True`, only `"b"` will returned. Set `vars_only` to `False` to
288
- get `"a.b"`.
289
-
290
- Raises:
291
- VarnameRetrievingError: When the callee's node cannot be retrieved or
292
- trying to retrieve the full name of non attribute series calls.
293
- """
294
- warnings.warn(
295
- "`nameof` is deprecated and will be removed in the future. "
296
- "Please use `argname` instead.",
297
- DeprecationWarning,
298
- )
299
- # Frame is anyway used in get_node
300
- frameobj = IgnoreList.create(
301
- ignore_lambda=False,
302
- ignore_varname=False,
303
- ).get_frame(frame)
304
-
305
- node = get_node_by_frame(frameobj, raise_exc=True)
306
- if not node:
307
- # We can't retrieve the node by executing.
308
- # It can be due to running code from python/shell, exec/eval or
309
- # other environments where sourcecode cannot be reached
310
- # make sure we keep it simple (only single variable passed and no
311
- # full passed) to use bytecode_nameof
312
- #
313
- # We don't have to check keyword arguments here, as the instruction
314
- # will then be CALL_FUNCTION_KW.
315
- if not more_vars:
316
- return bytecode_nameof(frameobj.f_code, frameobj.f_lasti)
317
-
318
- # We are anyway raising exceptions, no worries about additional burden
319
- # of frame retrieval again
320
- source = frameobj.f_code.co_filename
321
- if source == "<stdin>":
322
- raise VarnameRetrievingError(
323
- "Are you trying to call nameof in REPL/python shell? "
324
- "In such a case, nameof can only be called with single "
325
- "argument and no keyword arguments."
326
- )
327
- if source == "<string>":
328
- raise VarnameRetrievingError(
329
- "Are you trying to call nameof from exec/eval? "
330
- "In such a case, nameof can only be called with single "
331
- "argument and no keyword arguments."
332
- )
333
- raise VarnameRetrievingError(
334
- "Source code unavailable, nameof can only retrieve the name of "
335
- "a single variable, and argument `full` should not be specified."
336
- )
337
-
338
- out = argname(
339
- "var",
340
- "*more_vars",
341
- func=nameof,
342
- frame=frame,
343
- vars_only=vars_only,
344
- )
345
- return out if more_vars else out[0] # type: ignore
346
-
347
-
348
220
  @overload
349
221
  def argname(
350
222
  arg: str,
varname/utils.py CHANGED
@@ -10,7 +10,6 @@ Attributes:
10
10
  `inspect.getmodule(frame)`
11
11
  """
12
12
  import sys
13
- import dis
14
13
  import ast
15
14
  import warnings
16
15
  import inspect
@@ -18,7 +17,7 @@ from os import path
18
17
  from pathlib import Path
19
18
  from functools import lru_cache, singledispatch
20
19
  from types import ModuleType, FunctionType, CodeType, FrameType
21
- from typing import Tuple, Union, List, Mapping, Callable, Dict
20
+ from typing import Tuple, Union, List, Mapping, Callable
22
21
 
23
22
  from executing import Source
24
23
 
@@ -163,11 +162,11 @@ def get_node_by_frame(frame: FrameType, raise_exc: bool = True) -> ast.AST:
163
162
  exect.node.__frame__ = frame
164
163
  return exect.node
165
164
 
166
- if exect.source.text and exect.source.tree and raise_exc:
165
+ if exect.source.text and exect.source.tree and raise_exc: # pragma: no cover
167
166
  raise VarnameRetrievingError(
168
167
  "Couldn't retrieve the call node. "
169
168
  "This may happen if you're using some other AST magic at the "
170
- "same time, such as pytest, ipython, macropy, or birdseye."
169
+ "same time, such as pytest, macropy, or birdseye."
171
170
  )
172
171
 
173
172
  return None
@@ -244,71 +243,6 @@ def node_name(
244
243
  )
245
244
 
246
245
 
247
- @lru_cache()
248
- def bytecode_nameof(code: CodeType, offset: int) -> str:
249
- """Cached Bytecode version of nameof
250
-
251
- We are trying this version only when the sourcecode is unavisible. In most
252
- cases, this will happen when user is trying to run a script in REPL/
253
- python shell, with `eval`, or other circumstances where the code is
254
- manipulated to run but sourcecode is not available.
255
- """
256
- kwargs: Dict[str, bool] = (
257
- {"show_caches": True} if sys.version_info[:2] >= (3, 11) else {}
258
- )
259
-
260
- instructions = list(dis.get_instructions(code, **kwargs))
261
- ((current_instruction_index, current_instruction),) = (
262
- (index, instruction)
263
- for index, instruction in enumerate(instructions)
264
- if instruction.offset == offset
265
- )
266
-
267
- while current_instruction.opname == "CACHE": # pragma: no cover
268
- current_instruction_index -= 1
269
- current_instruction = instructions[current_instruction_index]
270
-
271
- pos_only_error = VarnameRetrievingError(
272
- "'nameof' can only be called with a single positional argument "
273
- "when source code is not avaiable."
274
- )
275
- if current_instruction.opname in ( # pragma: no cover
276
- "CALL_FUNCTION_EX",
277
- "CALL_FUNCTION_KW",
278
- ):
279
- raise pos_only_error
280
-
281
- if current_instruction.opname not in (
282
- "CALL_FUNCTION",
283
- "CALL_METHOD",
284
- "CALL",
285
- "CALL_KW",
286
- ):
287
- raise VarnameRetrievingError("Did you call 'nameof' in a weird way?")
288
-
289
- current_instruction_index -= 1
290
- name_instruction = instructions[current_instruction_index]
291
- while name_instruction.opname in ("CACHE", "PRECALL"): # pragma: no cover
292
- current_instruction_index -= 1
293
- name_instruction = instructions[current_instruction_index]
294
-
295
- if name_instruction.opname in ("KW_NAMES", "LOAD_CONST"): # LOAD_CONST python 3.13
296
- raise pos_only_error
297
-
298
- if not name_instruction.opname.startswith("LOAD_"):
299
- raise VarnameRetrievingError("Argument must be a variable or attribute")
300
-
301
- name = name_instruction.argrepr
302
- if not name.isidentifier():
303
- raise VarnameRetrievingError(
304
- f"Found the variable name {name!r} which is obviously wrong. "
305
- "This may happen if you're using some other AST magic at the "
306
- "same time, such as pytest, ipython, macropy, or birdseye."
307
- )
308
-
309
- return name
310
-
311
-
312
246
  def attach_ignore_id_to_module(module: ModuleType) -> None:
313
247
  """Attach the ignore id to module
314
248
 
@@ -550,7 +484,7 @@ def _(node: Union[ast.Attribute, ast.Subscript]) -> ast.Call:
550
484
  args=[keynode],
551
485
  keywords=[],
552
486
  )
553
- else:
487
+ else: # pragma: no cover
554
488
  return ast.Call( # type: ignore
555
489
  func=ast.Attribute(
556
490
  value=node.value,
@@ -597,7 +531,7 @@ def _(node: Union[ast.Attribute, ast.Subscript]) -> ast.Call:
597
531
  args=[keynode, node.parent.value], # type: ignore
598
532
  keywords=[],
599
533
  )
600
- else:
534
+ else: # pragma: no cover
601
535
  return ast.Call(
602
536
  func=ast.Attribute(
603
537
  value=node.value,
@@ -638,7 +572,7 @@ def _(node: ast.Compare) -> ast.Call:
638
572
  args=[node.comparators[0]],
639
573
  keywords=[],
640
574
  )
641
- else:
575
+ else: # pragma: no cover
642
576
  return ast.Call( # type: ignore
643
577
  func=ast.Attribute(
644
578
  value=node.left,
@@ -672,7 +606,7 @@ def _(node: ast.BinOp) -> ast.Call:
672
606
  args=[node.right],
673
607
  keywords=[],
674
608
  )
675
- else:
609
+ else: # pragma: no cover
676
610
  return ast.Call( # type: ignore
677
611
  func=ast.Attribute(
678
612
  value=node.left,
@@ -1,8 +1,7 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.3
2
2
  Name: varname
3
- Version: 0.13.4
3
+ Version: 0.14.0
4
4
  Summary: Dark magics about variable names in python.
5
- Home-page: https://github.com/pwwang/python-varname
6
5
  License: MIT
7
6
  Author: pwwang
8
7
  Author-email: pwwang@pwwang.com
@@ -14,10 +13,12 @@ Classifier: Programming Language :: Python :: 3.9
14
13
  Classifier: Programming Language :: Python :: 3.10
15
14
  Classifier: Programming Language :: Python :: 3.11
16
15
  Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Programming Language :: Python :: 3.13
17
17
  Provides-Extra: all
18
- Requires-Dist: asttokens (==2.*) ; extra == "all"
19
- Requires-Dist: executing (>=2.0,<3.0)
18
+ Requires-Dist: asttokens (==3.*) ; extra == "all"
19
+ Requires-Dist: executing (>=2.1,<3.0)
20
20
  Requires-Dist: pure_eval (==0.*) ; extra == "all"
21
+ Project-URL: Homepage, https://github.com/pwwang/python-varname
21
22
  Project-URL: Repository, https://github.com/pwwang/python-varname
22
23
  Description-Content-Type: text/markdown
23
24
 
@@ -44,7 +45,6 @@ Note if you use `python < 3.8`, install `varname < 0.11`
44
45
  - Core features:
45
46
 
46
47
  - Retrieving names of variables a function/class call is assigned to from inside it, using `varname`.
47
- - Retrieving variable names directly, using `nameof`
48
48
  - Detecting next immediate attribute name, using `will`
49
49
  - Fetching argument names/sources passed to a function using `argname`
50
50
 
@@ -268,31 +268,6 @@ Special thanks to [@HanyuuLu][2] to give up the name `varname` in pypi for this
268
268
  # foo.__varname__ == 'foo'
269
269
  ```
270
270
 
271
- ### Getting variable names directly using `nameof`
272
-
273
- ```python
274
- from varname import varname, nameof
275
-
276
- a = 1
277
- nameof(a) # 'a'
278
-
279
- b = 2
280
- nameof(a, b) # ('a', 'b')
281
-
282
- def func():
283
- return varname() + '_suffix'
284
-
285
- f = func() # f == 'f_suffix'
286
- nameof(f) # 'f'
287
-
288
- # get full names of (chained) attribute calls
289
- func.a = func
290
- nameof(func.a, vars_only=False) # 'func.a'
291
-
292
- func.a.b = 1
293
- nameof(func.a.b, vars_only=False) # 'func.a.b'
294
- ```
295
-
296
271
  ### Detecting next immediate attribute name
297
272
 
298
273
  ```python
@@ -438,22 +413,27 @@ obj.argnames # ['1', '2']
438
413
  `varname` is all depending on `executing` package to look for the node.
439
414
  The node `executing` detects is ensured to be the correct one (see [this][19]).
440
415
 
441
- It partially works with environments where other AST magics apply, including
442
- `pytest`, `ipython`, `macropy`, `birdseye`, `reticulate` with `R`, etc. Neither
416
+ It partially works with environments where other AST magics apply, including [`exec`][24] function,
417
+ [`macropy`][21], [`birdseye`][22], [`reticulate`][23] with `R`, etc. Neither
443
418
  `executing` nor `varname` is 100% working with those environments. Use
444
419
  it at your own risk.
445
420
 
446
421
  For example:
447
422
 
448
- - This will not work with `pytest`:
423
+ - This will not work:
449
424
 
450
425
  ```python
426
+ from varname import argname
427
+
428
+ def getname(x):
429
+ print(argname("x"))
430
+
451
431
  a = 1
452
- assert nameof(a) == 'a' # pytest manipulated the ast here
432
+ exec("getname(a)") # Cannot retrieve the node where the function is called.
453
433
 
454
- # do this instead
455
- name_a = nameof(a)
456
- assert name_a == 'a'
434
+ ## instead
435
+ # from varname.helpers import exec_code
436
+ # exec_code("getname(a)")
457
437
  ```
458
438
 
459
439
  [1]: https://github.com/pwwang/python-varname
@@ -475,4 +455,8 @@ For example:
475
455
  [17]: https://img.shields.io/pypi/dm/varname?style=flat-square
476
456
  [19]: https://github.com/alexmojaki/executing#is-it-reliable
477
457
  [20]: https://stackoverflow.com/a/59364138/5088165
458
+ [21]: https://github.com/lihaoyi/macropy
459
+ [22]: https://github.com/alexmojaki/birdseye
460
+ [23]: https://rstudio.github.io/reticulate/
461
+ [24]: https://docs.python.org/3/library/functions.html#exec
478
462
 
@@ -0,0 +1,10 @@
1
+ varname/__init__.py,sha256=J1-VOils3vUZH4QxbbtCH1likQee7vyTo_ocYxTz-kQ,361
2
+ varname/core.py,sha256=hFDoefsMc4TWBEzM-oMfzuCVFpmSv7iE82-m7cBv5s0,15027
3
+ varname/helpers.py,sha256=jZaP-qWQJwi8T2f886eHOj-llXAPHk5SMU6PfVn-9dg,9558
4
+ varname/ignore.py,sha256=-VC3oqag44y2UlAw0ErYKHotx616qJL3Sjb_5y7Tw1c,14400
5
+ varname/py.typed,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
6
+ varname/utils.py,sha256=l1eIuZhXrrLgS1wM3MbVh10LQChLPOkfHz9F67fQnoY,20580
7
+ varname-0.14.0.dist-info/LICENSE,sha256=3bS8O2tMbBPz8rWmZBAOzkHQjcK-b7KwFHyyghEZ-Ak,1063
8
+ varname-0.14.0.dist-info/METADATA,sha256=jmqGTlr-MZDjGG47OQzeoWOuLVgILhmPzhoaqTZkUQs,12746
9
+ varname-0.14.0.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
10
+ varname-0.14.0.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 1.9.0
2
+ Generator: poetry-core 2.0.1
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
@@ -1,10 +0,0 @@
1
- varname/__init__.py,sha256=Kwx6Bac3gQwx6y-nL8tmkBXotCWDefqnktF_uc3tyVs,369
2
- varname/core.py,sha256=HKcvZAIq6gQQlzuBgUsqeM0USZFDJ8pkYdQC9z8uJjs,19474
3
- varname/helpers.py,sha256=jZaP-qWQJwi8T2f886eHOj-llXAPHk5SMU6PfVn-9dg,9558
4
- varname/ignore.py,sha256=-VC3oqag44y2UlAw0ErYKHotx616qJL3Sjb_5y7Tw1c,14400
5
- varname/py.typed,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
6
- varname/utils.py,sha256=JCOGoLEXq3mQvQeobEyGiP4N2y1_42ULjwPvDn5SNSo,22882
7
- varname-0.13.4.dist-info/LICENSE,sha256=3bS8O2tMbBPz8rWmZBAOzkHQjcK-b7KwFHyyghEZ-Ak,1063
8
- varname-0.13.4.dist-info/METADATA,sha256=PUOgy7_nnnqyVZvE64E97P5IqHYlMVdeyCoCrIhEWCI,12845
9
- varname-0.13.4.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
10
- varname-0.13.4.dist-info/RECORD,,