• Persisting functions typed into the shell

    From Stefan Ram@21:1/5 to All on Sat Nov 12 13:01:25 2022
    Many readers here know interactive Python sessions with
    prompts like ">>>". But a "session" could be something else.
    One could imagine that when starting a new session, one
    still sees all the variables and constants defined in
    preceding sessions.

    I have implemented something like a "restore()" and a "save()"
    call. "restore()" will restore the names from the last "save()".
    "save()" will look for user-defined names (it excludes certain
    standard names and certain other names from my software) and
    save them using the "shelve" package from the standard library.

    I you know "shelve" or have read the subject line, you can
    guess what comes now:

    I cannot save user-defined functions this way!

    When a user types into the console:

    def f():
    |... print( "example" )
    |...

    he gives source code to shell and hopes that the shell will
    cherish the memory of that function. But instead it acts as
    if from now on it does not know the source code of "f"!

    So, there seems to be no way now to persist this function
    to a file? as if by "save( f )" or something similar?
    If not the source code, then maybe some other form?

    So much for the topic of "In Python, /everything/ is an
    object"! There seem to be first and second-class objects:
    Shelveable and non-shelveable objects.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Stefan Ram@21:1/5 to Wayne Harris on Sat Nov 12 16:05:30 2022
    Wayne Harris <[email protected]> writes:
    Wow. Could the dis module help at all?

    Thank you for this idea! I think this should work, but only
    under CPython and not necessarily across different Python
    versions. Still, I might use dis.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Wayne Harris@21:1/5 to Stefan Ram on Sat Nov 12 12:56:25 2022
    On 12/11/2022 10:01, Stefan Ram wrote:
    Many readers here know interactive Python sessions with
    prompts like ">>>". But a "session" could be something else.
    One could imagine that when starting a new session, one
    still sees all the variables and constants defined in
    preceding sessions.

    I have implemented something like a "restore()" and a "save()"
    call. "restore()" will restore the names from the last "save()".
    "save()" will look for user-defined names (it excludes certain
    standard names and certain other names from my software) and
    save them using the "shelve" package from the standard library.

    I you know "shelve" or have read the subject line, you can
    guess what comes now:

    I cannot save user-defined functions this way!

    When a user types into the console:

    def f():
    |... print( "example" )
    |...

    he gives source code to shell and hopes that the shell will
    cherish the memory of that function. But instead it acts as
    if from now on it does not know the source code of "f"!

    So, there seems to be no way now to persist this function
    to a file? as if by "save( f )" or something similar?
    If not the source code, then maybe some other form?

    So much for the topic of "In Python, /everything/ is an
    object"! There seem to be first and second-class objects:
    Shelveable and non-shelveable objects.

    Wow. Could the dis module help at all? Say by getting the bytes of the compiled function and then saving them to a file, then reading them off
    later and rebuilding the function with dis again?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From dn@21:1/5 to Stefan Ram on Sun Nov 13 08:02:31 2022
    On 13/11/2022 05.05, Stefan Ram wrote:
    Wayne Harris <[email protected]> writes:
    Wow. Could the dis module help at all?

    Thank you for this idea! I think this should work, but only
    under CPython and not necessarily across different Python
    versions. Still, I might use dis.

    Was constructing a two-part tutorial. When it came to the preparing for
    the second meeting, was surprised to discover that PyCharm retained code
    and values in its Python Console (its REPL tab/window) - I'm presuming,
    within its 'project' structure.

    Was more interested in ensuring all-parties would be able to re-create
    the ending/re-starting position, regardless of IDE. Accordingly, never
    looked any further.

    Depending upon the full range of criteria, may be worth a look...


    Disclaimer: JetBrains sponsor our local PUG with a one-year 'pro'
    license, as a monthly 'door prize'. Apart from using the product, have
    no other connection!

    Similarly, have not looked at such within VS-Codium or other editors/IDEs...
    --
    Regards,
    =dn

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Weatherby,Gerard@21:1/5 to All on Sat Nov 12 19:33:20 2022
    Sounds like Jupyter Notebooks: https://jupyter.org


    From: Python-list <python-list-bounces+gweatherby=[email protected]> on behalf of Stefan Ram <[email protected]>
    Date: Saturday, November 12, 2022 at 1:48 PM
    To: [email protected] <[email protected]>
    Subject: Persisting functions typed into the shell
    *** Attention: This is an external email. Use caution responding, opening attachments or clicking on links. ***

    Many readers here know interactive Python sessions with
    prompts like ">>>". But a "session" could be something else.
    One could imagine that when starting a new session, one
    still sees all the variables and constants defined in
    preceding sessions.

    I have implemented something like a "restore()" and a "save()"
    call. "restore()" will restore the names from the last "save()".
    "save()" will look for user-defined names (it excludes certain
    standard names and certain other names from my software) and
    save them using the "shelve" package from the standard library.

    I you know "shelve" or have read the subject line, you can
    guess what comes now:

    I cannot save user-defined functions this way!

    When a user types into the console:

    def f():
    |... print( "example" )
    |...

    he gives source code to shell and hopes that the shell will
    cherish the memory of that function. But instead it acts as
    if from now on it does not know the source code of "f"!

    So, there seems to be no way now to persist this function
    to a file? as if by "save( f )" or something similar?
    If not the source code, then maybe some other form?

    So much for the topic of "In Python, /everything/ is an
    object"! There seem to be first and second-class objects:
    Shelveable and non-shelveable objects.


    -- https://urldefense.com/v3/__https://mail.python.org/mailman/listinfo/python-list__;!!Cn_UX_p3!kVssvGre00pk5iMVIWUbuGXUwcZ8veRBEuSiX-VLlkRVlJoQ96fl6CZG9zQ72Hky8qqofZhhhA5qZpkneyEz4-4$<https://urldefense.com/v3/__https:/mail.python.org/mailman/listinfo/
    python-list__;!!Cn_UX_p3!kVssvGre00pk5iMVIWUbuGXUwcZ8veRBEuSiX-VLlkRVlJoQ96fl6CZG9zQ72Hky8qqofZhhhA5qZpkneyEz4-4$>

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Stefan Ram@21:1/5 to [email protected] on Sat Nov 12 19:26:45 2022
    dn <[email protected]> writes:
    Was constructing a two-part tutorial. When it came to the preparing for
    the second meeting, was surprised to discover that PyCharm retained code
    and values in its Python Console (its REPL tab/window) - I'm presuming, >within its 'project' structure.

    I was already wondering whether some Python-Implementations
    offer something like this.

    I have started to work on a Newsreader. The first version of
    the Newsreader is not to have any user interface at all. So,
    the user directly calls Python functions to use the program.
    The program is started in Idle and then one gets the usual
    shell prompt of Idle and can excute Python code, using all
    the definitions of the program.

    For example, to configure the newsreader, the user creates
    on object representing a newsserver:

    s = newsaccount_class( "news.example.com" )

    , then he can get a list of all the Python newsgroups:

    s.groups( '*python*' )

    . The abbreviated output is:

    ['comp.lang.python', 'pl.rec.humor.monty-python', ... ]

    . It would be too cumbersome if the user would have to repeat
    the configuration with "s = newsaccount_class( . . . )" every
    time he starts the program, so I am offering a function to
    save all the variables he has defined and try to find a way
    to make it easy to write and save "macros" (= nothing else
    than standard Python functions).

    (This "zero user interface" does not exclude that at a later
    date a more traditional user interface is added,
    for example, via the standard package "cmd" or using tkinter.)

    PS: While writing this post, by chance, I came across the
    documentation of the standard package "code". This might
    help me to find a way to get the source code of function
    definitions if I use it to write my own shell!

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Chris Angelico@21:1/5 to Stefan Ram on Sun Nov 13 08:15:05 2022
    On Sun, 13 Nov 2022 at 05:48, Stefan Ram <[email protected]> wrote:
    So much for the topic of "In Python, /everything/ is an
    object"! There seem to be first and second-class objects:
    Shelveable and non-shelveable objects.


    That's a bit unfair. Everything IS an object, but not all objects can
    be treated the same way. Complex numbers can't be compared for greater-than/less-than, but they are still first-class objects.

    Is it acceptable to you if the reconstituted function doesn't have
    source code (which will affect tracebacks and such), as long as it
    behaves the same way? If so, save the __code__.co_code attribute, and
    build a new function from that.

    ChrisA

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Stefan Ram@21:1/5 to Stefan Ram on Sun Nov 13 10:45:16 2022
    [email protected] (Stefan Ram) writes:
    PS: While writing this post, by chance, I came across the
    documentation of the standard package "code". This might
    help me to find a way to get the source code of function
    definitions if I use it to write my own shell!

    Session transcript and my source code below:

    transcript

    This Python Interpreter is now ready to accept statements.
    x = 7
    x
    7
    def f(): print( 'example' )
    ...

    *** Function definition found: ***
    def f(): print( 'example' )


    f()
    example
    def g():
    ... print( 'example' )
    ...

    *** Function definition found: ***
    def g():
    print( 'example' )


    g()
    example


    main.py

    import codeop
    print( 'This Python Interpreter is now ready to accept statements.' )

    def check_for_function_definition( listing ):
    stripped = listing[ 0 ].strip()
    found0 = stripped.startswith( "def" )
    found1 = len( stripped )> 3 and stripped[ 3 ].strip() == ''
    found = found0 and found1
    if found:
    print()
    print( '*** Function definition found: ***' )
    print( '\n'.join( listing ))
    print()

    class Interpreter:
    def __init__( self ):
    self.locals={}
    self.prepare_statement()
    self.mainloop()
    def prepare_statement( self ):
    self.listing = []
    print( end='>>> ' )
    self.multiline = False
    def process_possible_code( self ):
    code = codeop.compile_command( '\n'.join( self.listing ))
    if code:
    check_for_function_definition( self.listing )
    lines = '\n'.join( self.listing )
    exec( code, self.locals, self.locals )
    self.prepare_statement()
    else:
    self.multiline = True
    print( end='... ' )
    def mainloop( self ):
    while True:
    line = input()
    self.listing.append( line )
    if self.multiline:
    if line.strip() != '':
    print( end='... ' )
    continue
    else:
    self.process_possible_code()
    else:
    self.process_possible_code()

    Interpreter()

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)