Skip to content

Running Lib/test/test_funcattrs.py directly fails #122864

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Eclips4 opened this issue Aug 9, 2024 · 4 comments
Closed

Running Lib/test/test_funcattrs.py directly fails #122864

Eclips4 opened this issue Aug 9, 2024 · 4 comments
Labels
tests Tests in the Lib/test dir type-bug An unexpected behavior, bug, or error

Comments

@Eclips4
Copy link
Member

Eclips4 commented Aug 9, 2024

Bug report

Bug description:

eclips4@nixos ~/p/p/cpython (tests_for_ast_opt) [1]> ./python Lib/test/test_funcattrs.py
............F.....................
======================================================================
FAIL: test___builtins__ (__main__.FunctionPropertiesTest.test___builtins__)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/eclips4/programming/programming-languages/cpython/Lib/test/test_funcattrs.py", line 101, in test___builtins__
    self.assertIs(self.b.__builtins__, __builtins__)
    ~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AssertionError: {'__name__': 'builtins', '__doc__': "Built-in functions, types, exceptions, and other objects.\n\nThis module provides direct access to all 'built-in'\nidentifiers of Python; for example, builtins.len is\nthe full name for the built-in function len().\n\nThis module is not normally accessed explicitly by most\napplications, but can be useful in modules that provide\nobjects with the same name as a built-in value, but in\nwhich the built-in of that name is also needed.", '__package__': '', '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': ModuleSpec(name='builtins', loader=<class '_frozen_importlib.BuiltinImporter'>, origin='built-in'), '__build_class__': <built-in function __build_class__>, '__import__': <built-in function __import__>, 'abs': <built-in function abs>, 'all': <built-in function all>, 'any': <built-in function any>, 'ascii': <built-in function ascii>, 'bin': <built-in function bin>, 'breakpoint': <built-in function breakpoint>, 'callable': <built-in function callable>, 'chr': <built-in function chr>, 'compile': <built-in function compile>, 'delattr': <built-in function delattr>, 'dir': <built-in function dir>, 'divmod': <built-in function divmod>, 'eval': <built-in function eval>, 'exec': <built-in function exec>, 'format': <built-in function format>, 'getattr': <built-in function getattr>, 'globals': <built-in function globals>, 'hasattr': <built-in function hasattr>, 'hash': <built-in function hash>, 'hex': <built-in function hex>, 'id': <built-in function id>, 'input': <built-in function input>, 'isinstance': <built-in function isinstance>, 'issubclass': <built-in function issubclass>, 'iter': <built-in function iter>, 'aiter': <built-in function aiter>, 'len': <built-in function len>, 'locals': <built-in function locals>, 'max': <built-in function max>, 'min': <built-in function min>, 'next': <built-in function next>, 'anext': <built-in function anext>, 'oct': <built-in function oct>, 'ord': <built-in function ord>, 'pow': <built-in function pow>, 'print': <built-in function print>, 'repr': <built-in function repr>, 'round': <built-in function round>, 'setattr': <built-in function setattr>, 'sorted': <built-in function sorted>, 'sum': <built-in function sum>, 'vars': <built-in function vars>, 'None': None, 'Ellipsis': Ellipsis, 'NotImplemented': NotImplemented, 'False': False, 'True': True, 'bool': <class 'bool'>, 'memoryview': <class 'memoryview'>, 'bytearray': <class 'bytearray'>, 'bytes': <class 'bytes'>, 'classmethod': <class 'classmethod'>, 'complex': <class 'complex'>, 'dict': <class 'dict'>, 'enumerate': <class 'enumerate'>, 'filter': <class 'filter'>, 'float': <class 'float'>, 'frozenset': <class 'frozenset'>, 'property': <class 'property'>, 'int': <class 'int'>, 'list': <class 'list'>, 'map': <class 'map'>, 'object': <class 'object'>, 'range': <class 'range'>, 'reversed': <class 'reversed'>, 'set': <class 'set'>, 'slice': <class 'slice'>, 'staticmethod': <class 'staticmethod'>, 'str': <class 'str'>, 'super': <class 'super'>, 'tuple': <class 'tuple'>, 'type': <class 'type'>, 'zip': <class 'zip'>, '__debug__': True, 'BaseException': <class 'BaseException'>, 'BaseExceptionGroup': <class 'BaseExceptionGroup'>, 'Exception': <class 'Exception'>, 'GeneratorExit': <class 'GeneratorExit'>, 'KeyboardInterrupt': <class 'KeyboardInterrupt'>, 'SystemExit': <class 'SystemExit'>, 'ArithmeticError': <class 'ArithmeticError'>, 'AssertionError': <class 'AssertionError'>, 'AttributeError': <class 'AttributeError'>, 'BufferError': <class 'BufferError'>, 'EOFError': <class 'EOFError'>, 'ImportError': <class 'ImportError'>, 'LookupError': <class 'LookupError'>, 'MemoryError': <class 'MemoryError'>, 'NameError': <class 'NameError'>, 'OSError': <class 'OSError'>, 'ReferenceError': <class 'ReferenceError'>, 'RuntimeError': <class 'RuntimeError'>, 'StopAsyncIteration': <class 'StopAsyncIteration'>, 'StopIteration': <class 'StopIteration'>, 'SyntaxError': <class 'SyntaxError'>, 'SystemError': <class 'SystemError'>, 'TypeError': <class 'TypeError'>, 'ValueError': <class 'ValueError'>, 'Warning': <class 'Warning'>, 'FloatingPointError': <class 'FloatingPointError'>, 'OverflowError': <class 'OverflowError'>, 'ZeroDivisionError': <class 'ZeroDivisionError'>, 'BytesWarning': <class 'BytesWarning'>, 'DeprecationWarning': <class 'DeprecationWarning'>, 'EncodingWarning': <class 'EncodingWarning'>, 'FutureWarning': <class 'FutureWarning'>, 'ImportWarning': <class 'ImportWarning'>, 'PendingDeprecationWarning': <class 'PendingDeprecationWarning'>, 'ResourceWarning': <class 'ResourceWarning'>, 'RuntimeWarning': <class 'RuntimeWarning'>, 'SyntaxWarning': <class 'SyntaxWarning'>, 'UnicodeWarning': <class 'UnicodeWarning'>, 'UserWarning': <class 'UserWarning'>, 'BlockingIOError': <class 'BlockingIOError'>, 'ChildProcessError': <class 'ChildProcessError'>, 'ConnectionError': <class 'ConnectionError'>, 'FileExistsError': <class 'FileExistsError'>, 'FileNotFoundError': <class 'FileNotFoundError'>, 'InterruptedError': <class 'InterruptedError'>, 'IsADirectoryError': <class 'IsADirectoryError'>, 'NotADirectoryError': <class 'NotADirectoryError'>, 'PermissionError': <class 'PermissionError'>, 'ProcessLookupError': <class 'ProcessLookupError'>, 'TimeoutError': <class 'TimeoutError'>, 'IndentationError': <class 'IndentationError'>, '_IncompleteInputError': <class '_IncompleteInputError'>, 'IndexError': <class 'IndexError'>, 'KeyError': <class 'KeyError'>, 'ModuleNotFoundError': <class 'ModuleNotFoundError'>, 'NotImplementedError': <class 'NotImplementedError'>, 'PythonFinalizationError': <class 'PythonFinalizationError'>, 'RecursionError': <class 'RecursionError'>, 'UnboundLocalError': <class 'UnboundLocalError'>, 'UnicodeError': <class 'UnicodeError'>, 'BrokenPipeError': <class 'BrokenPipeError'>, 'ConnectionAbortedError': <class 'ConnectionAbortedError'>, 'ConnectionRefusedError': <class 'ConnectionRefusedError'>, 'ConnectionResetError': <class 'ConnectionResetError'>, 'TabError': <class 'TabError'>, 'UnicodeDecodeError': <class 'UnicodeDecodeError'>, 'UnicodeEncodeError': <class 'UnicodeEncodeError'>, 'UnicodeTranslateError': <class 'UnicodeTranslateError'>, 'ExceptionGroup': <class 'ExceptionGroup'>, 'EnvironmentError': <class 'OSError'>, 'IOError': <class 'OSError'>, 'open': <built-in function open>, 'quit': Use quit() or Ctrl-D (i.e. EOF) to exit, 'exit': Use exit() or Ctrl-D (i.e. EOF) to exit, 'copyright': Copyright (c) 2001-2024 Python Software Foundation.
All Rights Reserved.

Copyright (c) 2000 BeOpen.com.
All Rights Reserved.

Copyright (c) 1995-2001 Corporation for National Research Initiatives.
All Rights Reserved.

Copyright (c) 1991-1995 Stichting Mathematisch Centrum, Amsterdam.
All Rights Reserved., 'credits':     Thanks to CWI, CNRI, BeOpen.com, Zope Corporation and a cast of thousands
    for supporting Python development.  See www.python.org for more information., 'license': Type license() to see the full license text, 'help': Type help() for interactive help, or help(object) for help about object.} is not <module 'builtins' (built-in)>

----------------------------------------------------------------------
Ran 34 tests in 0.007s

FAILED (failures=1)

CPython versions tested on:

CPython main branch

Operating systems tested on:

Linux

Linked PRs

@Eclips4 Eclips4 added type-bug An unexpected behavior, bug, or error tests Tests in the Lib/test dir labels Aug 9, 2024
@Eclips4
Copy link
Member Author

Eclips4 commented Aug 9, 2024

The culprit is the test___builtins__ which has this line:
self.assertIs(self.b.__builtins__, __builtins__), which translates to

def b(): pass

assert b.__builtins__ is __builtins__

I'm wondering why running this test using ./python -m test doesn't failing.

@picnixz
Copy link
Member

picnixz commented Aug 10, 2024

Could be something where there is an exec/eval polluting a namespace? I don't have access to sources so I cannot even check nut might be worth changing the name of the object being tested, or look at whether builtins is reloaded at some point?

@mbyrnepr2
Copy link
Contributor

mbyrnepr2 commented Sep 26, 2024

I think this part of the docs explains the behaviour:

By default, when in the __main__ module, __builtins__ is the built-in module [builtins]; when in any other module, __builtins__ is an alias for the dictionary of the builtins module itself.

./python.exe -m test.test_funcattrs:

markbyrne@Marks-Air-2 cpython % ./python.exe -m test.test_funcattrs
> /Users/markbyrne/programming/cpython/Lib/test/test_funcattrs.py(101)test___builtins__()
-> breakpoint()
(Pdb) __name__
'__main__'
(Pdb) __builtins__
<module 'builtins' (built-in)>
(Pdb) __builtins__.__dict__ is __builtins__
False
(Pdb)

./python.exe -m test:

> /Users/markbyrne/programming/cpython/Lib/test/test_funcattrs.py(101)test___builtins__()
(Pdb) __name__
'test.test_funcattrs'
(Pdb) import builtins
(Pdb) builtins.__dict__ is __builtins__
True
(Pdb)

So, one way forward could be to update the test to first check if we are inside __main__ and update the value of __builtins__ accordingly with a basic if/else.

Edit: However, it isn't clear why self.b.__builtins__ is the same value in each scenario. I understood from the Changelog that it should be equal to the value of globals()["__builtins__"] which is different in each scenario:
Functions have a new __builtins__ attribute which is used to look for builtin symbols when a function is executed, instead of looking into __globals__['__builtins__']. The attribute is initialized from __globals__["__builtins__"] if it exists, else from the current builtins.

Edit 2: I gather from https://bugs.python.org/issue42990 that func.__builtins__ is builtins.__dict__. The following could work?

--- a/Lib/test/test_funcattrs.py
+++ b/Lib/test/test_funcattrs.py
@@ -98,7 +98,23 @@ def test___globals__(self):
                              (AttributeError, TypeError))

     def test___builtins__(self):
-        self.assertIs(self.b.__builtins__, __builtins__)
+        if __name__ == "__main__":
+            # `func.__builtins__` is `builtins.__dict__`.
+            # See:https://bugs.python.org/issue42990
+
+            # When this test is run by executing the current module,
+            # `__builtins__` is the built-in module `builtins`.
+
+            # When this test is run from another module, `__builtins__` is
+            # `builtins.__dict__`
+            # See: https://docs.python.org/3/reference/executionmodel.html#builtins-and-restricted-execution
+
+            import builtins
+            builtins_dict = builtins.__dict__
+        else:
+            builtins_dict = __builtins__
+
+        self.assertIs(self.b.__builtins__, builtins_dict)
         self.cannot_set_attr(self.b, '__builtins__', 2,
                              (AttributeError, TypeError))

@@ -108,7 +124,7 @@ def func(s): return len(s)
         ns = {}
         func2 = type(func)(func.__code__, ns)
         self.assertIs(func2.__globals__, ns)
-        self.assertIs(func2.__builtins__, __builtins__)
+        self.assertIs(func2.__builtins__, builtins_dict)

         # Make sure that the function actually works.

mbyrnepr2 added a commit to mbyrnepr2/cpython that referenced this issue Oct 1, 2024
…le was

run directly via: `python -m test.test_funcattrs`.
Eclips4 pushed a commit that referenced this issue Oct 2, 2024
…directly (#124845)

Previously when executing ``test_functattrs.test___builtins__`` directly, it failed because the fact, that ``__builtins__`` is refers to the built-in module ``builtins`` while it's expects a ``__builtins__.__dict__``. But when this test is being run from another module, then ``__builtins__`` is refers to ``builtins.__dict__``. Now this part of the behaviour is covered.
---------

Co-authored-by: Victor Stinner <[email protected]>
miss-islington pushed a commit to miss-islington/cpython that referenced this issue Oct 2, 2024
…uting directly (pythonGH-124845)

Previously when executing ``test_functattrs.test___builtins__`` directly, it failed because the fact, that ``__builtins__`` is refers to the built-in module ``builtins`` while it's expects a ``__builtins__.__dict__``. But when this test is being run from another module, then ``__builtins__`` is refers to ``builtins.__dict__``. Now this part of the behaviour is covered.
---------

(cherry picked from commit 8fbf10d)

Co-authored-by: Mark Byrne <[email protected]>
Co-authored-by: Victor Stinner <[email protected]>
miss-islington pushed a commit to miss-islington/cpython that referenced this issue Oct 2, 2024
…uting directly (pythonGH-124845)

Previously when executing ``test_functattrs.test___builtins__`` directly, it failed because the fact, that ``__builtins__`` is refers to the built-in module ``builtins`` while it's expects a ``__builtins__.__dict__``. But when this test is being run from another module, then ``__builtins__`` is refers to ``builtins.__dict__``. Now this part of the behaviour is covered.
---------

(cherry picked from commit 8fbf10d)

Co-authored-by: Mark Byrne <[email protected]>
Co-authored-by: Victor Stinner <[email protected]>
Eclips4 pushed a commit that referenced this issue Oct 2, 2024
…cuting directly (GH-124845) (#124885)

gh-122864: Fix a ``test_funcattrs.test___builtins__`` when executing directly (GH-124845)

Previously when executing ``test_functattrs.test___builtins__`` directly, it failed because the fact, that ``__builtins__`` is refers to the built-in module ``builtins`` while it's expects a ``__builtins__.__dict__``. But when this test is being run from another module, then ``__builtins__`` is refers to ``builtins.__dict__``. Now this part of the behaviour is covered.
---------

(cherry picked from commit 8fbf10d)

Co-authored-by: Mark Byrne <[email protected]>
Co-authored-by: Victor Stinner <[email protected]>
Yhg1s pushed a commit that referenced this issue Oct 3, 2024
…cuting directly (GH-124845) (#124884)

gh-122864: Fix a ``test_funcattrs.test___builtins__`` when executing directly (GH-124845)

Previously when executing ``test_functattrs.test___builtins__`` directly, it failed because the fact, that ``__builtins__`` is refers to the built-in module ``builtins`` while it's expects a ``__builtins__.__dict__``. But when this test is being run from another module, then ``__builtins__`` is refers to ``builtins.__dict__``. Now this part of the behaviour is covered.
---------

(cherry picked from commit 8fbf10d)

Co-authored-by: Mark Byrne <[email protected]>
Co-authored-by: Victor Stinner <[email protected]>
@Eclips4
Copy link
Member Author

Eclips4 commented Oct 9, 2024

Thanks @mbyrnepr2!

@Eclips4 Eclips4 closed this as completed Oct 9, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
tests Tests in the Lib/test dir type-bug An unexpected behavior, bug, or error
Projects
None yet
Development

No branches or pull requests

3 participants