adafruit / Adafruit_CircuitPython_AdafruitIO

Adafruit IO for CircuitPython
http://io.adafruit.com
MIT License
49 stars 33 forks source link

locals() returning wrong results #96

Closed robert-billing closed 1 year ago

robert-billing commented 1 year ago

I have tried this on versions

adafruit-circuitpython-raspberry_pi_pico-en_GB-7.3.3.uf2 adafruit-circuitpython-raspberry_pi_pico-en_GB-8.0.0-beta.0.uf2 adafruit-circuitpython-raspberry_pi_pico-en_GB-8.0.0-beta.5.uf2

with the same results. This test program

# Investigate symbol tables

def tst ( p, q, r, s ):
    pp = p
    qq = q
    rr = r
    ss = s
    a = 1
    b = 2
    print ( "\nlocals=", locals () )
    print ( "globals=", globals () )

tst ( 1, 2, 3, 4 )

gives results which would imply that locals() is returning the global symbol table:

code.py output:

locals= {'tst': <function tst at 0x20008b50>, '__name__': '__main__', '__file__': 'code.py'}
globals= {'tst': <function tst at 0x20008b50>, '__name__': '__main__', '__file__': 'code.py'}

Code done running.

Running this on

Python 3.10.8 (main, Nov 14 2022, 00:00:00) [GCC 12.2.1 20220819 (Red Hat 12.2.1-2)] on linux

gives me the expected result

locals= {'p': 1, 'q': 2, 'r': 3, 's': 4, 'pp': 1, 'qq': 2, 'rr': 3, 'ss': 4, 'a': 1, 'b': 2}
globals= {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x7fea5ad21b40>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': '/data/unclebob/Company/Customers/Cranborne/Panel/devel/symtst.py', '__cached__': None, 'tst': <function tst at 0x7fea68687d90>}

Since eval() is supposed to use the local symbol table, and the circuitpython eval() does not have a locals= option this is giving me anomalous results from eval().

I suspect that this is a fairly simple bug.

Neradoc commented 1 year ago

Hi, that's not a bug, it's an optimization in the core, see the Micropython docs on that: https://docs.micropython.org/en/latest/genrst/core_language.html#local-variables-aren-t-included-in-locals-result

Local variables aren’t included in locals() result

Cause: MicroPython doesn’t maintain symbolic local environment, it is optimized to an array of slots. Thus, local variables can’t be accessed by a name.

Code running in eval() function doesn’t have access to local variables¶

Cause: MicroPython doesn’t maintain symbolic local environment, it is optimized to an array of slots. Thus, local variables can’t be accessed by a name. Effectively, eval(expr) in MicroPython is equivalent to eval(expr, globals(), globals()).

tekktrik commented 1 year ago

Closing since this isn't an issue with the library and is a known, specified deviation between CircuitPython/MicroPython and CPython.