|
2 | 2 | Global state initialized at import time. |
3 | 3 | Used for hidden arguments and developer features. |
4 | 4 | """ |
5 | | -from line_profiler import _logger |
6 | 5 | import os |
| 6 | +import sys |
| 7 | +from types import ModuleType |
| 8 | +from line_profiler import _logger |
7 | 9 |
|
8 | 10 |
|
9 | | -def _boolean_environ(key): |
10 | | - """ |
| 11 | +def _boolean_environ( |
| 12 | + envvar, |
| 13 | + truey=frozenset({'1', 'on', 'true', 'yes'}), |
| 14 | + falsy=frozenset({'0', 'off', 'false', 'no'}), |
| 15 | + default=False): |
| 16 | + r""" |
11 | 17 | Args: |
12 | | - key (str) |
| 18 | + envvar (str) |
| 19 | + Name for the environment variable to read from. |
| 20 | + truey (Collection[str]) |
| 21 | + Values to be considered truey. |
| 22 | + falsy (Collection[str]) |
| 23 | + Values to be considered falsy. |
| 24 | + default (bool) |
| 25 | + Default boolean value to resolve to. |
13 | 26 |
|
14 | 27 | Returns: |
15 | | - bool |
| 28 | + :py:data:`True` |
| 29 | + If the (case-normalized) environment variable is equal to |
| 30 | + any of ``truey``. |
| 31 | + :py:data:`False` |
| 32 | + If the (case-normalized) environment variable is equal to |
| 33 | + any of ``falsy``. |
| 34 | + ``default`` |
| 35 | + Otherwise. |
| 36 | +
|
| 37 | + Example: |
| 38 | + >>> from os import environ |
| 39 | + >>> from subprocess import run |
| 40 | + >>> from sys import executable |
| 41 | + >>> from textwrap import dedent |
| 42 | + >>> |
| 43 | + >>> |
| 44 | + >>> def resolve_in_subproc(value, default, |
| 45 | + ... envvar='MY_ENVVAR', |
| 46 | + ... truey=('foo',), falsy=('bar',)): |
| 47 | + ... code = dedent(''' |
| 48 | + ... from {0.__module__} import {0.__name__} |
| 49 | + ... print({0.__name__}({1!r}, {2!r}, {3!r}, {4!r})) |
| 50 | + ... ''').strip('\n').format(_boolean_environ, envvar, |
| 51 | + ... tuple(truey), tuple(falsy), |
| 52 | + ... bool(default)) |
| 53 | + ... env = environ.copy() |
| 54 | + ... env[envvar] = value |
| 55 | + ... proc = run([executable, '-c', code], |
| 56 | + ... capture_output=True, env=env, text=True) |
| 57 | + ... proc.check_returncode() |
| 58 | + ... return {'True': True, |
| 59 | + ... 'False': False}[proc.stdout.strip()] |
| 60 | + ... |
| 61 | + >>> |
| 62 | + >>> # Truey value |
| 63 | + >>> assert resolve_in_subproc('FOO', True) == True |
| 64 | + >>> assert resolve_in_subproc('FOO', False) == True |
| 65 | + >>> # Falsy value |
| 66 | + >>> assert resolve_in_subproc('BaR', True) == False |
| 67 | + >>> assert resolve_in_subproc('BaR', False) == False |
| 68 | + >>> # Mismatch -> fall back to default |
| 69 | + >>> assert resolve_in_subproc('baz', True) == True |
| 70 | + >>> assert resolve_in_subproc('baz', False) == False |
16 | 71 | """ |
17 | | - value = os.environ.get(key, '').lower() |
18 | | - TRUTHY_ENVIRONS = {'true', 'on', 'yes', '1'} |
19 | | - return value in TRUTHY_ENVIRONS |
| 72 | + # (TODO: migrate to `line_profiler.cli_utils.boolean()` after |
| 73 | + # merging #335) |
| 74 | + try: |
| 75 | + value = os.environ.get(envvar).casefold() |
| 76 | + except AttributeError: # None |
| 77 | + return default |
| 78 | + non_default_values = falsy if default else truey |
| 79 | + if value in {v.casefold() for v in non_default_values}: |
| 80 | + return not default |
| 81 | + return default |
20 | 82 |
|
21 | 83 |
|
| 84 | +# `kernprof` switches |
22 | 85 | DEBUG = _boolean_environ('LINE_PROFILER_DEBUG') |
23 | 86 | NO_EXEC = _boolean_environ('LINE_PROFILER_NO_EXEC') |
24 | 87 | KEEP_TEMPDIRS = _boolean_environ('LINE_PROFILER_KEEP_TEMPDIRS') |
25 | 88 | STATIC_ANALYSIS = _boolean_environ('LINE_PROFILER_STATIC_ANALYSIS') |
26 | 89 |
|
| 90 | +# `line_profiler._line_profiler` switches |
| 91 | +WRAP_TRACE = _boolean_environ('LINE_PROFILER_WRAP_TRACE') |
| 92 | +SET_FRAME_LOCAL_TRACE = _boolean_environ('LINE_PROFILER_SET_FRAME_LOCAL_TRACE') |
| 93 | +_MUST_USE_LEGACY_TRACE = not isinstance( |
| 94 | + getattr(sys, 'monitoring', None), ModuleType) |
| 95 | +USE_LEGACY_TRACE = ( |
| 96 | + _MUST_USE_LEGACY_TRACE |
| 97 | + or _boolean_environ('LINE_PROFILER_CORE', |
| 98 | + # Also provide `coverage-style` aliases |
| 99 | + truey={'old', 'legacy', 'ctrace'}, |
| 100 | + falsy={'new', 'sys.monitoring', 'sysmon'}, |
| 101 | + default=_MUST_USE_LEGACY_TRACE)) |
| 102 | + |
27 | 103 | log = _logger.Logger('line_profiler', backend='auto') |
0 commit comments