0
# Configuration and Exceptions
1
2
Configuration options and comprehensive exception hierarchy for error handling in varname operations. Understanding these components is essential for robust error handling and debugging.
3
4
## Configuration
5
6
### Global Configuration
7
8
Central configuration object for controlling varname behavior across the application.
9
10
```python { .api }
11
class config:
12
"""Global configurations for varname."""
13
14
debug: bool = False
15
"""Show debug information for frames being ignored.
16
17
When True, varname will print detailed information about which frames
18
are being skipped during the ignore process. Useful for debugging
19
complex ignore scenarios or when varname is not finding the expected frame.
20
21
Example output when debug=True:
22
VARNAME DEBUG: Ignored frame: <frame at 0x...> (file: decorator.py, func: wrapper)
23
VARNAME DEBUG: Target frame found: <frame at 0x...> (file: main.py, func: <module>)
24
"""
25
```
26
27
#### Usage Examples
28
29
```python
30
from varname import config, varname
31
32
# Enable debug mode
33
config.debug = True
34
35
def logged(func):
36
def wrapper(*args, **kwargs):
37
# With debug=True, will show ignored frames
38
name = varname(ignore=logged)
39
print(f"Calling {name}")
40
return func(*args, **kwargs)
41
return wrapper
42
43
@logged
44
def process_data():
45
return "processed"
46
47
# This will show debug output about ignored frames
48
result = process_data()
49
50
# Disable debug mode
51
config.debug = False
52
```
53
54
## Exception Hierarchy
55
56
Varname provides a comprehensive exception hierarchy for different types of errors that can occur during variable name retrieval and introspection.
57
58
### Base Exception
59
60
```python { .api }
61
class VarnameException(Exception):
62
"""Root exception for all varname-related errors.
63
64
All other varname exceptions inherit from this base class, allowing
65
for unified exception handling when needed.
66
"""
67
```
68
69
### Core Exceptions
70
71
#### Variable Name Retrieval Errors
72
73
```python { .api }
74
class VarnameRetrievingError(VarnameException):
75
"""Raised when failed to retrieve the variable name.
76
77
This is the most common exception raised by varname functions when
78
they cannot determine the variable name due to:
79
- AST node retrieval failures
80
- Unsupported calling contexts
81
- Frame analysis problems
82
- Source code unavailability
83
84
Common scenarios:
85
- Using varname in REPL without source code
86
- Complex call chains that confuse frame analysis
87
- Missing or corrupted AST information
88
- Calling from unsupported contexts (e.g., some decorators)
89
"""
90
```
91
92
#### Improper Usage Errors
93
94
```python { .api }
95
class ImproperUseError(VarnameException):
96
"""Raised when varname functions are used improperly.
97
98
This exception indicates incorrect usage patterns that violate
99
varname's assumptions or requirements:
100
101
For varname():
102
- Multiple target assignment when multi_vars=False
103
- Non-direct assignment when strict=True (e.g., a = [func()])
104
- Using in contexts where variable assignment detection is impossible
105
106
For will():
107
- Not followed by attribute access
108
- Used in contexts where next attribute cannot be determined
109
110
For argname():
111
- Called from functions that cannot be analyzed
112
- Requesting non-existent arguments
113
- Invalid argument specifications
114
"""
115
```
116
117
#### Qualified Name Errors
118
119
```python { .api }
120
class QualnameNonUniqueError(VarnameException):
121
"""Raised when a qualified name refers to multiple objects.
122
123
This occurs in the ignore system when a qualified name (module.function)
124
is used as an ignore element but matches multiple different objects,
125
making it ambiguous which one should be ignored.
126
127
Example:
128
- import math; from math import sin
129
- Using "math.sin" as ignore element is ambiguous
130
"""
131
```
132
133
### Exception Usage Examples
134
135
```python
136
from varname import (
137
varname, will, argname, nameof,
138
VarnameException,
139
VarnameRetrievingError,
140
ImproperUseError,
141
QualnameNonUniqueError
142
)
143
144
# Catching specific varname errors
145
def safe_varname():
146
try:
147
return varname()
148
except VarnameRetrievingError as e:
149
print(f"Could not retrieve variable name: {e}")
150
return "unknown"
151
except ImproperUseError as e:
152
print(f"Improper varname usage: {e}")
153
return "improper"
154
155
# Usage in unsupported context
156
try:
157
# This will raise VarnameRetrievingError in REPL
158
name = safe_varname()
159
except Exception as e:
160
print(f"Error: {e}")
161
162
# Catching all varname exceptions
163
def robust_operation():
164
try:
165
a, b = varname(multi_vars=False) # Will raise ImproperUseError
166
return a, b
167
except VarnameException as e:
168
print(f"Varname operation failed: {type(e).__name__}: {e}")
169
return None, None
170
171
# Example with improper will() usage
172
class BadWillUsage:
173
def method(self):
174
try:
175
attr = will()
176
# Not followed by attribute access - will cause issues
177
return attr
178
except ImproperUseError as e:
179
print(f"Will() used improperly: {e}")
180
return None
181
182
obj = BadWillUsage()
183
result = obj.method() # Direct call, no attribute access
184
185
# Example with argname errors
186
def analyze_function():
187
try:
188
# Requesting non-existent argument
189
name = argname('nonexistent_arg')
190
return name
191
except VarnameRetrievingError as e:
192
print(f"Argument analysis failed: {e}")
193
return None
194
195
def caller():
196
return analyze_function()
197
198
result = caller()
199
```
200
201
## Warning System
202
203
Varname includes warnings for situations that are not errors but may indicate potential issues or unexpected behavior.
204
205
### Warning Hierarchy
206
207
```python { .api }
208
class VarnameWarning(Warning):
209
"""Root warning for all varname-related warnings."""
210
211
class MultiTargetAssignmentWarning(VarnameWarning):
212
"""Warning for multiple target assignments like a = b = func().
213
214
Issued when varname() detects multiple assignment targets, which can
215
lead to ambiguous variable name detection. The warning helps identify
216
potential issues in complex assignment patterns.
217
218
Example triggering code:
219
def create(): return varname()
220
a = b = create() # Triggers warning
221
"""
222
223
class MaybeDecoratedFunctionWarning(VarnameWarning):
224
"""Warning when suspicious decorated function used as ignore directly.
225
226
Issued when a function that appears to be decorated is used directly
227
in the ignore parameter instead of using proper ignore handling for
228
decorated functions.
229
230
Example:
231
@decorator
232
def func(): pass
233
234
varname(ignore=func) # May trigger warning
235
# Should use: varname(ignore=(func, 1)) for decorated functions
236
"""
237
238
class UsingExecWarning(VarnameWarning):
239
"""Warning when exec is used to retrieve function name for argname().
240
241
Issued when argname() needs to use exec with temporary files to analyze
242
function calls in environments where source code is not directly available.
243
This indicates a fallback mechanism is being used.
244
"""
245
```
246
247
### Warning Configuration
248
249
```python
250
import warnings
251
from varname import VarnameWarning
252
253
# Control varname warnings
254
warnings.filterwarnings('ignore', category=VarnameWarning) # Suppress all
255
warnings.filterwarnings('error', category=VarnameWarning) # Make them errors
256
warnings.filterwarnings('always', category=VarnameWarning) # Always show
257
258
# Filter specific warning types
259
from varname import MultiTargetAssignmentWarning
260
261
warnings.filterwarnings('ignore', category=MultiTargetAssignmentWarning)
262
```
263
264
## Error Handling Best Practices
265
266
### Graceful Degradation
267
268
```python
269
from varname import varname, VarnameRetrievingError
270
271
def create_with_fallback(default_name="object"):
272
"""Create object with varname, falling back to default name."""
273
try:
274
name = varname()
275
except VarnameRetrievingError:
276
name = default_name
277
278
return {
279
'name': name,
280
'created_at': '2023-01-01',
281
'data': []
282
}
283
284
# Works in normal contexts
285
user_data = create_with_fallback() # name='user_data'
286
287
# Works in problematic contexts
288
items = [create_with_fallback() for _ in range(3)] # name='object' (fallback)
289
```
290
291
### Context-Aware Error Handling
292
293
```python
294
from varname import argname, nameof, ImproperUseError, VarnameRetrievingError
295
296
def smart_debug_function(*args, **kwargs):
297
"""Debug function that adapts to available context."""
298
try:
299
# Try to get argument names
300
if args:
301
arg_names = nameof(*args)
302
print(f"Arguments: {arg_names}")
303
except VarnameRetrievingError:
304
# Fall back to positions
305
print(f"Arguments: {len(args)} positional args")
306
except ImproperUseError:
307
# Handle complex expressions
308
print(f"Arguments: complex expressions ({len(args)} args)")
309
310
try:
311
# Try to get keyword argument names
312
if kwargs:
313
kwarg_info = argname('kwargs')
314
print(f"Keyword args: {kwarg_info}")
315
except (VarnameRetrievingError, ImproperUseError):
316
print(f"Keyword args: {list(kwargs.keys())}")
317
318
# Usage examples
319
x, y = 1, 2
320
smart_debug_function(x, y, debug=True) # Will try name detection
321
322
smart_debug_function(x + 1, y * 2, mode="test") # Will handle expressions gracefully
323
```
324
325
### Production-Ready Error Handling
326
327
```python
328
import logging
329
from varname import VarnameException, config
330
331
# Set up logging for varname issues
332
logger = logging.getLogger('varname_ops')
333
334
def production_varname_operation():
335
"""Example of production-ready varname usage."""
336
try:
337
# Enable debug only in development
338
if __debug__:
339
config.debug = True
340
341
name = varname()
342
logger.debug(f"Retrieved variable name: {name}")
343
return name
344
345
except VarnameException as e:
346
# Log the specific error type and context
347
logger.warning(
348
f"Varname operation failed: {type(e).__name__}: {e}",
349
exc_info=True
350
)
351
# Return sensible default
352
return "unnamed_variable"
353
354
finally:
355
# Clean up debug mode
356
config.debug = False
357
358
# Usage
359
try:
360
result_data = production_varname_operation()
361
logger.info(f"Created {result_data}")
362
except Exception as e:
363
logger.error(f"Unexpected error: {e}", exc_info=True)
364
```