From 79fcf9e36b3f2efa5a98f650032918239aed9909 Mon Sep 17 00:00:00 2001 From: Thomas Sader Date: Sun, 13 Oct 2024 14:55:05 +0200 Subject: [PATCH] Update python docs --- doc/sphinx_source/using/python.rst | 58 +++++++++++++++++++++++++---- src/mod/python.mod/scripts/greet.py | 15 +++++++- 2 files changed, 64 insertions(+), 9 deletions(-) diff --git a/doc/sphinx_source/using/python.rst b/doc/sphinx_source/using/python.rst index 520aa1810..e848724e5 100644 --- a/doc/sphinx_source/using/python.rst +++ b/doc/sphinx_source/using/python.rst @@ -9,6 +9,8 @@ System Requirements ------------------- Similar to Tcl requirements, Eggdrop requires both python and python development libraries to be installed on the host machine. On Debian/Ubuntu machines, this requires the packages python-dev AND python-is-python3 to be installed. The python-is-python3 updates symlinks on the host system that allow Eggdrop to find it. +The minimum supported Python version is 3.8 and we do require the Global Interpreter Lock for thread safety, even if you use latest Python. + -------------- Loading Python -------------- @@ -21,6 +23,50 @@ To load a python script from your config file, place the .py file in the scripts pysource scripts/myscript.py +If you need to install dependencies we recommend using virtual environments, see https://docs.python.org/3/library/venv.html for more details. + +To create the virtual environment in a hidden directory called .venv (only necessary once):: + + cd eggdrop && python3 -m venv .venv + +To install a python package in the above .venv directory (in this example, the requests package):: + + cd eggdrop && source .venv/bin/activate && pip install requests + +Starting eggdrop with activated venv (must be run every time for proper functionality):: + + cd eggdrop && source .venv/bin/activate && ./eggdrop + +You always need to start Eggdrop with the activated venv to set the necessary environment variables. + +------------------------ +Reloading Python Scripts +------------------------ + +Unfortunately, reloading python scripts with rehash like Tcl scripts is currently unsupported. Scripts can unbind their existing binds and re-bind them on being loaded again (see the bind section). For now, you should restart your bot when the Python scripts change. + +You can (should?) also write scripts that manually unload their binds upon a reshash, example code looks like this: + + # Create a list to track the join binds + if 'JOIN_BINDS' in globals(): + for joinbind in JOIN_BINDS: + joinbind.unbind() + del JOIN_BINDS + + JOIN_BINDS = list() + + <...> + + # Create the binds in the script like this + JOIN_BINDS.append(bind("join", "*", "*", joinGreetUser)) + JOIN_BINDS.append(bind("join", "o", "*", joinGreetOp)) + +------------------------ +Multithreading and async +------------------------ + +``pysource`` loads a Python script in the main Eggdrop thread but is free to use both async Python and threads. + ----------------------- Eggdrop Python Commands ----------------------- @@ -49,6 +95,11 @@ An important difference to note is that Eggdrop Python has its own ``bind`` comm The python version of the bind command is used to create a bind that triggers a python function. The python bind takes the same arguments as the Tcl binds, but here each argument is passed individually. For example, a bind that would look like ``bind pub * !foo myproc`` in Tcl is written as ``bind("pub", "*", "!foo", myproc)``. For more information on Eggsrop bind argument syntax please see :ref:`bind_types`. The eggdrop.tcl.bind command should not be used as it will attempt to call a Tcl proc. +The ``bind`` command returns a PythonBind object that has an ``unbind`` method:: + + x = bind("pub", "*", "!foo", myproc) + x.unbind() + ^^^^^^^^^^^^^^^^^^^^^^^ parse_tcl_list ^^^^^^^^^^^^^^^^^^^^^^^ @@ -101,13 +152,6 @@ and then call it using:: An important difference to note is that Eggdrop Python has its own ``bind`` command implemented. You will generally want to create binds using the Python ``bind`` command and not import bind from eggdrop.tcl because a Python bind will call a Python function, whereas using the Tcl bind will call a Tcl function (not one from the script you are writing). -Where does python print go? - -------------------------------------- -Writing a module for use with Eggdrop -------------------------------------- - -This is how you import a module for use with an egg python script. Copyright (C) 2000 - 2024 Eggheads Development Team diff --git a/src/mod/python.mod/scripts/greet.py b/src/mod/python.mod/scripts/greet.py index 9400f8d30..e93f07c18 100644 --- a/src/mod/python.mod/scripts/greet.py +++ b/src/mod/python.mod/scripts/greet.py @@ -15,9 +15,20 @@ def joinGreetUser(nick, host, handle, channel, **kwargs): def joinGreetOp(nick, host, handle, channel, **kwargs): putmsg(channel, f"{nick} is an operator on this channel!") +# For now, unfortunately if Eggdrop is rehashed, previously existing binds will be duplicated. +# This is example code to check for previously-existbing binds after the script reloaded and +# delete them. +if 'GREET_BINDS' in globals(): + for greetbind in GREET_BINDS: + greetbind.unbind() + del GREET_BINDS + +# Continuing from the above section of code, the GREET_BINDS list is created to track the binds +# created by this script, and then the binds are added to it. +GREET_BINDS = list() # Call binds at the end of the script, not the top- the functions must be defined! -bind("join", "*", "*", joinGreetUser) +GREET_BINDS.append(bind("join", "*", "*", joinGreetUser)) # Again, arguments are separated with a comma. This bind requires the 'o' flag to be triggered. -bind("join", "o", "*", joinGreetOp) +GREET_BINDS.append(bind("join", "o", "*", joinGreetOp)) print('Loaded greet.py')