In this Python 2.7 code, what should take the place of GET_MY_COMPILER_FLAGS()
?
from __future__ import print_function
def ReportCompilerFlags():
myFlags = GET_MY_COMPILER_FLAGS() # how?
import __future__
for featureName in __future__.all_feature_names:
thisFlag = getattr(__future__, featureName).compiler_flag
print('File {fileName} has {featureName} turned {status}.'.format(
fileName = __file__,
featureName = featureName,
status = 'ON' if (myFlags & thisFlag) else 'off',
))
ReportCompilerFlags()
Desired output:
File /path/to/this/script.py has nested_scopes turned off.
File /path/to/this/script.py has generators turned off.
File /path/to/this/script.py has division turned off.
File /path/to/this/script.py has absolute_import turned off.
File /path/to/this/script.py has with_statement turned off.
File /path/to/this/script.py has print_function turned ON.
File /path/to/this/script.py has unicode_literals turned off.
I know I could inspect globals()
to see if it contains the appropriately named symbols instead of looking at the flags, but false positives and false negatives are clearly both possible that way.
Update: I updated the title to dig this question out of the classic XY problem. To query activation status of language features, it turns out I should be looking at more than just compiler flags, since the compiler does not actually use the flag for a feature that is already mandatory.
You can inspect the code object's co_flags
. This includes all __future__
flags and a bunch of flags used for other things, like whether the code object is for a generator.
import inspect
all_flags = inspect.currentframe().f_code.co_flags
Note that this tells you what flags are active, not necessarily what features are active. If a feature is on by default in your version of Python, its flag probably won't be set. You can check the feature object's getMandatoryRelease
to determine whether a flag is on by default:
import sys
def on_by_default(feature):
return feature.getMandatoryRelease() <= sys.version_info
Also, make sure you have the right code object. For example, if you wrap this in a library function, you should make sure you're not looking at the library function's own flags:
import inspect
import types
def code_flags(target=None):
"""
Returns code flags for the caller of this function, or for a
specified code or frame object.
"""
if target is None:
target = inspect.currentframe().f_back
if isinstance(target, types.FrameType):
target = target.f_code
return target.co_flags
Based on user2357112's answer and others' helpful comments, here's the library function I ended up writing:
import sys
import inspect
import __future__
def features(stackBack=0):
featureStatus = set()
frame = None
for featureName in __future__.all_feature_names:
feature = getattr( __future__, featureName)
if feature.getMandatoryRelease() <= sys.version_info:
activated = True
else:
if frame is None:
frame = inspect.stack()[abs(stackBack) + 1][0]
activated = (frame.f_code.co_flags & feature.compiler_flag) != 0
if activated:
featureStatus.add(featureName)
return featureStatus
Let's say I save this as language.py
. The respective outputs for Python 2.7.12 and 3.6.8 are:
$ python -c 'import language; print(language.features())'
set(['with_statement', 'generators', 'nested_scopes'])
$ python3 -c 'import language; print(language.features())'
{'unicode_literals', 'with_statement', 'print_function', 'absolute_import', 'generators', 'division', 'nested_scopes'}
A typical use case might be the test 'unicode_literals' in features()
to check whether you currently have that particular feature active, or 'unicode_literals' in features(stackBack=1)
to check whether it's active in whichever module called you.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With