diff --git a/README.md b/README.md index 3ce9b55..ed2302d 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ Add `:venomous` to your list of dependencies in `mix.exs`: ```elixir def deps do [ - {:venomous, "~> 0.6.0"} + {:venomous, "~> 0.6.1"} ] end ``` diff --git a/docs/.build b/docs/.build index 847f8ff..a351524 100644 --- a/docs/.build +++ b/docs/.build @@ -30,7 +30,7 @@ dist/lato-latin-ext-300-normal-VPGGJKJL.woff2 dist/lato-latin-ext-400-normal-N27NCBWW.woff2 dist/lato-latin-ext-700-normal-Q2L5DVMW.woff2 dist/remixicon-NKANDIL5.woff2 -dist/search_data-191F28C9.js +dist/search_data-C54F6743.js dist/sidebar_items-09B092B5.js index.html python.html diff --git a/docs/404.html b/docs/404.html index 6c004fc..8261b7e 100644 --- a/docs/404.html +++ b/docs/404.html @@ -5,12 +5,12 @@ - + -
- Hex Package + Hex Package - Hex Preview + Hex Preview diff --git a/docs/Mix.Tasks.Venomous.Watchdog.html b/docs/Mix.Tasks.Venomous.Watchdog.html index 19c743c..a1c1e55 100644 --- a/docs/Mix.Tasks.Venomous.Watchdog.html +++ b/docs/Mix.Tasks.Venomous.Watchdog.html @@ -5,10 +5,10 @@ - + -
- Hex Package + Hex Package - Hex Preview + Hex Preview diff --git a/docs/Venomous.Application.html b/docs/Venomous.Application.html index 2185c3b..b5fb6c6 100644 --- a/docs/Venomous.Application.html +++ b/docs/Venomous.Application.html @@ -5,10 +5,10 @@ - + -
- Hex Package + Hex Package - Hex Preview + Hex Preview diff --git a/docs/Venomous.PetSnakeManager.html b/docs/Venomous.PetSnakeManager.html index 273132b..1674e19 100644 --- a/docs/Venomous.PetSnakeManager.html +++ b/docs/Venomous.PetSnakeManager.html @@ -5,10 +5,10 @@ - + -
- Hex Package + Hex Package - Hex Preview + Hex Preview diff --git a/docs/Venomous.PetSnakeSupervisor.html b/docs/Venomous.PetSnakeSupervisor.html index d23e147..4ee9a70 100644 --- a/docs/Venomous.PetSnakeSupervisor.html +++ b/docs/Venomous.PetSnakeSupervisor.html @@ -5,10 +5,10 @@ - + -
- Hex Package + Hex Package - Hex Preview + Hex Preview diff --git a/docs/Venomous.SerpentWatcher.html b/docs/Venomous.SerpentWatcher.html index 0bb14bc..fcb8cef 100644 --- a/docs/Venomous.SerpentWatcher.html +++ b/docs/Venomous.SerpentWatcher.html @@ -5,10 +5,10 @@ - + -
mix venomous.watchdog install
Whenever file is edited/created/deleted watcher casts :reload
with module name to SnakeManager.
The default reload module function imports and reloads the module from its name.## Configuration
config :venomous,
- serpent_watcher: [
+ serpent_watcher: [
enable: true, # Disabled by default
logging: true, # Hot reload logging. Enabled by default
module: :serpent_watcher, # default
func: :watch_directories, #default
manager_pid: Venomous.SnakeManager # default
- ]
config :venomous, :snake_manager, %{
+ ]
config :venomous, :snake_manager, %{
...
reload_module: :reload, # default. reload function is hard coded to :reload
...
-}
+}
@@ -316,9 +316,9 @@ - Hex Package + Hex Package - Hex Preview + Hex Preview diff --git a/docs/Venomous.SnakeArgs.html b/docs/Venomous.SnakeArgs.html index ff162db..08756ef 100644 --- a/docs/Venomous.SnakeArgs.html +++ b/docs/Venomous.SnakeArgs.html @@ -5,10 +5,10 @@ - + -
- Hex Package + Hex Package - Hex Preview + Hex Preview diff --git a/docs/Venomous.SnakeError.html b/docs/Venomous.SnakeError.html index 1dad6db..7f784ac 100644 --- a/docs/Venomous.SnakeError.html +++ b/docs/Venomous.SnakeError.html @@ -5,10 +5,10 @@ - + -
- Hex Package + Hex Package - Hex Preview + Hex Preview diff --git a/docs/Venomous.SnakeManager.html b/docs/Venomous.SnakeManager.html index 5642960..7b206a2 100644 --- a/docs/Venomous.SnakeManager.html +++ b/docs/Venomous.SnakeManager.html @@ -5,10 +5,10 @@ - + -
- Hex Package + Hex Package - Hex Preview + Hex Preview diff --git a/docs/Venomous.SnakeOpts.html b/docs/Venomous.SnakeOpts.html index def150e..23a6979 100644 --- a/docs/Venomous.SnakeOpts.html +++ b/docs/Venomous.SnakeOpts.html @@ -5,10 +5,10 @@ - + -
- Hex Package + Hex Package - Hex Preview + Hex Preview diff --git a/docs/Venomous.SnakeSupervisor.html b/docs/Venomous.SnakeSupervisor.html index 3617525..ca6489b 100644 --- a/docs/Venomous.SnakeSupervisor.html +++ b/docs/Venomous.SnakeSupervisor.html @@ -5,10 +5,10 @@ - + -
- Hex Package + Hex Package - Hex Preview + Hex Preview diff --git a/docs/Venomous.SnakeWorker.html b/docs/Venomous.SnakeWorker.html index 8b1ac96..7f845c1 100644 --- a/docs/Venomous.SnakeWorker.html +++ b/docs/Venomous.SnakeWorker.html @@ -5,10 +5,10 @@ - + -
Python options can be configured inside :venomous :python_opts config key
All of these are optional. However you will most likely want to set module_paths
@available_opts [
+ Python options can be configured inside :venomous :python_opts config key
All of these are optional. However you will most likely want to set module_paths
@available_opts [
:module_paths, # List of paths to your python modules
:cd, # Change python's directory on spawn. Default is $PWD
:compressed, # Can be set from 0-9. May affect performance. Read more on [Erlport documentation](http://erlport.org/docs/python.html#erlang-api)
:envvars, # additional python process envvars
:packet_bytes, # Size of erlport python packet. Default: 4 = max 4GB of data. Can be set to 1 = 256 bytes or 2 = ? bytes if you are sure you won't be transfering a lot of data.
:python_executable # path to python executable to use.
-]
+]
@@ -375,9 +375,9 @@ - Hex Package + Hex Package - Hex Preview + Hex Preview diff --git a/docs/Venomous.epub b/docs/Venomous.epub index e37989d..d171512 100644 Binary files a/docs/Venomous.epub and b/docs/Venomous.epub differ diff --git a/docs/Venomous.html b/docs/Venomous.html index 3911b62..c2a4c47 100644 --- a/docs/Venomous.html +++ b/docs/Venomous.html @@ -5,10 +5,10 @@ - + -
The behavior and management of Snakes can be configured through the following options:
:venomous, :snake_manager, %{
- snake_ttl_minutes: non_neg_integer(), # Time-to-live for a Snake in minutes. Default is 15 min.
- perpetual_workers: non_neg_integer(), # Number of Snakes to keep alive perpetually. Default is 10.
- cleaner_interval: non_neg_integer(), # Interval in milliseconds for cleaning up inactive Snakes. Default is 60_000 ms.
- erlport_encoder: %{module: atom(), func: atom(), args: list(any())}, # Optional :erlport encoder/decoder python function for converting types. This function is applied to every unnamed python process started by SnakeManager. For more information see [Handling Erlport API](PYTHON.md)
- }
The behavior and management of Snakes can be configured through the following options:
:venomous, :snake_manager, %{
+ snake_ttl_minutes: non_neg_integer(), # Time-to-live for a Snake in minutes. Default is 15 min.
+ perpetual_workers: non_neg_integer(), # Number of Snakes to keep alive perpetually. Default is 10.
+ cleaner_interval: non_neg_integer(), # Interval in milliseconds for cleaning up inactive Snakes. Default is 60_000 ms.
+ erlport_encoder: %{module: atom(), func: atom(), args: list(any())}, # Optional :erlport encoder/decoder python function for converting types. This function is applied to every unnamed python process started by SnakeManager. For more information see [Handling Erlport API](PYTHON.md)
+ }
All of these are optional. However you will most likely want to set module_paths
config :venomous, :snake_manager, %{
+ All of these are optional. However you will most likely want to set module_paths
config :venomous, :snake_manager, %{
...
- python_opts: [
- module_paths: [], # List of paths to your python modules.
+ python_opts: [
+ module_paths: [], # List of paths to your python modules.
cd: "", # Change python's directory on spawn. Default is $PWD
compressed: 0, # Can be set from 0-9. May affect performance. Read more on [Erlport documentation](http://erlport.org/docs/python.html#erlang-api)
- envvars: [], # additional python process envvars
+ envvars: [], # additional python process envvars
packet_bytes: 4, # Size of erlport python packet. Default: 4 = max 4GB of data. Can be set to 1 = 256 bytes or 2 = ? bytes if you are sure you won't be transfering a lot of data.
python_executable: "" # path to python executable to use. defaults to PATH
- ]
+ ]
...
-}
### Hot reloading
+
}
### Hot reloading
Requires watchdog python module, which can be installed with mix venomous.watchdog install
.
Only files inside module_paths
config are watched.
config :venomous, :serpent_watcher, enable: true
Python options can be configured inside :venomous :python_opts config key
All of these are optional. However you will most likely want to set module_paths
erlport_encoder: %{module: atom(), func: atom(), args: list(any())}
: Optional :erlport encoder/decoder python function for converting types. This function is applied to every unnamed python process started by SnakeManager. For more information see Handling Erlport API@available_opts [
+ Python options can be configured inside :venomous :python_opts config key
All of these are optional. However you will most likely want to set module_paths
erlport_encoder: %{module: atom(), func: atom(), args: list(any())}
: Optional :erlport encoder/decoder python function for converting types. This function is applied to every unnamed python process started by SnakeManager. For more information see Handling Erlport API@available_opts [
:module_paths, # List of paths to your python modules
:cd, # Change python's directory on spawn. Default is $PWD
:compressed, # Can be set from 0-9. May affect performance. Read more on [Erlport documentation](http://erlport.org/docs/python.html#erlang-api)
:envvars, # additional python process envvars
:packet_bytes, # Size of erlport python packet. Default: 4 = max 4GB of data. Can be set to 1 = 256 bytes or 2 = ? bytes if you are sure you won't be transfering a lot of data.
:python_executable # path to python executable to use.
-]
+
]
- Hex Package + Hex Package - Hex Preview + Hex Preview diff --git a/docs/api-reference.html b/docs/api-reference.html index b024c34..53f0368 100644 --- a/docs/api-reference.html +++ b/docs/api-reference.html @@ -5,10 +5,10 @@ - + -
- Hex Package + Hex Package - Hex Preview + Hex Preview diff --git a/docs/dist/search_data-191F28C9.js b/docs/dist/search_data-C54F6743.js similarity index 99% rename from docs/dist/search_data-191F28C9.js rename to docs/dist/search_data-C54F6743.js index c3d5163..2765d45 100644 --- a/docs/dist/search_data-191F28C9.js +++ b/docs/dist/search_data-C54F6743.js @@ -1 +1 @@ -searchData={"content_type":"text/markdown","items":[{"doc":"Used for installing/uninstalling python watchdog module into python/ directory.","ref":"Mix.Tasks.Venomous.Watchdog.html","title":"mix venomous.watchdog","type":"task"},{"doc":"","ref":"Mix.Tasks.Venomous.Watchdog.html#uninstall_watchdog/0","title":"Mix.Tasks.Venomous.Watchdog.uninstall_watchdog/0","type":"function"},{"doc":"Venomous is a wrapper around erlport python Ports, designed to simplify concurrent use. It focuses dynamic extensibility, like spawning, reusing and killing processes on demand. Furthermore, unused processes get automatically killed by scheduled process which can be configured inside config.exs. Venomous core functions capture and handle :EXIT calls ensuring that all python process die with it and do not continue their execution.\n\nThe core concept revolves around \"Snakes\" which represent Python worker processes. These `Venomous.SnakeWorker` are managed and supervised with `Venomous.SnakeManager` GenServer to allow concurrent and efficient execution of Python code. The `Snakes` pids and python pids are stored inside `:ets` table and the Processes are handled by `DymanicSupervisor` called `Venomous.SnakeSupervisor`. The unused `Snakes` get automatically killed by `SnakeManager` depending on the given configuration.\n\nYou can checkout examples [here](https://github.com/RustySnek/venomous-examples)\n\nBe sure to also check the [README](readme.html)","ref":"Venomous.html","title":"Venomous","type":"module"},{"doc":"","ref":"Venomous.html#module-main-functionality","title":"Main Functionality - Venomous","type":"module"},{"doc":"These are automatically managed and made for concurrent operations\n - `python/2`: The primary function to execute a Python function. It retrieves a Snake (Python worker process) and runs the specified Python function using the arguments provided in a `SnakeArgs` struct. If no ready Snakes are available, a new one is spawned. If max_children is reached it will return an error with appropriate message.\n - `python!/2` | `python!/1`: Will wait until any `Venomous.SnakeWorker` is freed, requesting it with the given interval.","ref":"Venomous.html#module-basic-processes","title":"Basic processes - Venomous","type":"module"},{"doc":"Python processes with unique names. Meant for miscellaneous processes.\n - `adopt_snake_pet/2`: Creates a new `Venomous.SnakeWorker` with a name inside `Venomous.PetSnakeSupervisor`\n - `pet_snake_run/3`: Runs given `Venomous.SnakeArgs` inside the named python process","ref":"Venomous.html#module-named-processes","title":"Named processes - Venomous","type":"module"},{"doc":"Venomous consists of several key components:\n\n- `Venomous.SerpentWatcher`: Manages hot reloading.\n- `Venomous.SnakeWorker`: Manages the execution of Python processes.\n- `Venomous.SnakeSupervisor`: A DynamicSupervisor that oversees the SnakeWorkers.\n- `Venomous.SnakeManager`: A GenServer that coordinates the SnakeWorkers and handles operations like spawning, retrieval and cleanup.\n- `Venomous.PetSnakeSupervisor`: Similar to SnakeSupervisor but for named processes.\n- `Venomous.PetSnakeManager`: Manages named python processes","ref":"Venomous.html#module-architecture","title":"Architecture - Venomous","type":"module"},{"doc":"","ref":"Venomous.html#module-configuration-options","title":"Configuration Options - Venomous","type":"module"},{"doc":"The behavior and management of Snakes can be configured through the following options:\n```elixir\n:venomous, :snake_manager, %{\n snake_ttl_minutes: non_neg_integer(), # Time-to-live for a Snake in minutes. Default is 15 min.\n perpetual_workers: non_neg_integer(), # Number of Snakes to keep alive perpetually. Default is 10.\n cleaner_interval: non_neg_integer(), # Interval in milliseconds for cleaning up inactive Snakes. Default is 60_000 ms.\n erlport_encoder: %{module: atom(), func: atom(), args: list(any())}, # Optional :erlport encoder/decoder python function for converting types. This function is applied to every unnamed python process started by SnakeManager. For more information see [Handling Erlport API](PYTHON.md)\n }\n```","ref":"Venomous.html#module-snakemanager","title":"SnakeManager - Venomous","type":"module"},{"doc":"All of these are optional. However you will most likely want to set module_paths\n ```elixir\n config :venomous, :snake_manager, %{\n ...\n python_opts: [\n module_paths: [], # List of paths to your python modules.\n cd: \"\", # Change python's directory on spawn. Default is $PWD\n compressed: 0, # Can be set from 0-9. May affect performance. Read more on [Erlport documentation](http://erlport.org/docs/python.html#erlang-api)\n envvars: [], # additional python process envvars\n packet_bytes: 4, # Size of erlport python packet. Default: 4 = max 4GB of data. Can be set to 1 = 256 bytes or 2 = ? bytes if you are sure you won't be transfering a lot of data.\n python_executable: \"\" # path to python executable to use. defaults to PATH\n ]\n ...\n}\n```","ref":"Venomous.html#module-python-options","title":"Python options - Venomous","type":"module"},{"doc":"Requires watchdog python module, which can be installed with `mix venomous.watchdog install`.\n Only files inside `module_paths` config are watched.\n ```elixir\n config :venomous, :serpent_watcher, enable: true\n ```","ref":"Venomous.html#module-hot-reloading","title":"Hot reloading - Venomous","type":"module"},{"doc":"Venomous provides an easy way to convert structs into classes and back with VenomousTrait class and `mix venomous.structs ...` task.\n ```\n $ mix venomous.structs\n Simple utility to create python elixir compatible classes.\n\n VenomousTrait class provides 2 functions: \n - def from_dict(cls, erl_map: Map | Dict, structs: Dict = {}) -> cls\n # converts Erlport Map or a Dict into the object class\n - def into_erl(self) -> Map\n # returns erlang compatible struct from self\n\n \n To create basic python classes and encode/decode functions based on structs: \n - mix venomous.structs MyModule.MyStruct MyModule.MoreStructs ...\n\n To create extended classes depending on existing python class: \n - mix venomous.structs MyModule.MyStruct:PythonClassName ...\n\n To create for all available structs inside an application\n - mix venomous.structs all my_application\n ```\n\n You can see this used in the [struct_test.exs](https://github.com/RustySnek/Venomous/blob/struct_class_handling/test/struct_test.exs) and [test_venomous.py](https://github.com/RustySnek/Venomous/blob/struct_class_handling/python/test_venomous.py)","ref":"Venomous.html#module-struct-class-comp","title":"Struct/Class comp - Venomous","type":"module"},{"doc":"- `list_alive_snakes/0`: Returns a list of :ets table containing currently alive Snakes.\n\n- `clean_inactive_snakes/0`: Manually clears inactive Snakes depending on their ttl and returns the number of Snakes cleared.\n\n- `slay_python_worker/2`: Kills a specified Python worker process and its SnakeWorker. :brutal can be specified as option, which will `kill -9` the os process of python which prevents the code from executing until it finalizes or goes through iteration.\n\n- `slay_pet_worker/2`: Kills a named Python process\n\n- `retrieve_snake/0`: Retrieves a `Venomous.SnakeWorker` and sets its status to :retrieved\n \n- `get_snakes_ready/1`: Retrieves given amount of `Venomous.SnakeWorker`s","ref":"Venomous.html#module-auxiliary-functions","title":"Auxiliary Functions - Venomous","type":"module"},{"doc":"Creates a named `Venomous.SnakeWorker` inside `Venomous.PetSnakeSupervisor`","ref":"Venomous.html#adopt_snake_pet/2","title":"Venomous.adopt_snake_pet/2","type":"function"},{"doc":"- an atom() name.\n - opts for python process","ref":"Venomous.html#adopt_snake_pet/2-parameters","title":"Parameters - Venomous.adopt_snake_pet/2","type":"function"},{"doc":"Python options can be configured inside :venomous :python_opts config key\n\n All of these are optional. However you will most likely want to set module_paths\n\n - `erlport_encoder: %{module: atom(), func: atom(), args: list(any())}`: Optional :erlport encoder/decoder python function for converting types. This function is applied to every unnamed python process started by SnakeManager. For more information see [Handling Erlport API](PYTHON.md)\n - ```elixir\n @available_opts [\n :module_paths, # List of paths to your python modules\n :cd, # Change python's directory on spawn. Default is $PWD\n :compressed, # Can be set from 0-9. May affect performance. Read more on [Erlport documentation](http://erlport.org/docs/python.html#erlang-api)\n :envvars, # additional python process envvars\n :packet_bytes, # Size of erlport python packet. Default: 4 = max 4GB of data. Can be set to 1 = 256 bytes or 2 = ? bytes if you are sure you won't be transfering a lot of data.\n :python_executable # path to python executable to use.\n]\n```","ref":"Venomous.html#adopt_snake_pet/2-options","title":"Options - Venomous.adopt_snake_pet/2","type":"function"},{"doc":"- :ok, name - in case of success\n - :error, message - in case of failure","ref":"Venomous.html#adopt_snake_pet/2-returns","title":"Returns - Venomous.adopt_snake_pet/2","type":"function"},{"doc":"Clears inactive snakes manually, returns number of snakes cleared.","ref":"Venomous.html#clean_inactive_snakes/0","title":"Venomous.clean_inactive_snakes/0","type":"function"},{"doc":"Retrieves x amount of ready snakes and sets their status to :retrieved. In case of hitting max_children cap, stops and returns all available snakes.\n> #### Warning {: .warning}\n> In case of retrieving all available snakes and not using them right away, functions like `python!/2` and `retrieve_snake!/0` will loop until they are freed.","ref":"Venomous.html#get_snakes_ready/1","title":"Venomous.get_snakes_ready/1","type":"function"},{"doc":"- amount of snakes to retrieve","ref":"Venomous.html#get_snakes_ready/1-parameters","title":"Parameters - Venomous.get_snakes_ready/1","type":"function"},{"doc":"- A list of `Venomous.SnakeWorker` structs","ref":"Venomous.html#get_snakes_ready/1-returns","title":"Returns - Venomous.get_snakes_ready/1","type":"function"},{"doc":"Returns list of :ets table containing alive snakes","ref":"Venomous.html#list_alive_snakes/0","title":"Venomous.list_alive_snakes/0","type":"function"},{"doc":"Used to run given `Venomous.SnakeArgs` inside named snake\nDoes not handle :EXIT signals like `snake_run/2` does.\nIf pet snake with name does not exist will return :not_found","ref":"Venomous.html#pet_snake_run/3","title":"Venomous.pet_snake_run/3","type":"function"},{"doc":"Wrapper for calling python process\nTries to retrieve `Venomous.SnakeWorker` which then runs the given `Venomous.SnakeArgs`. In case of failure will return {:retrieve_error, message}.\nIn case :EXIT happens, it will kill python os process along with its worker and exit(reason)","ref":"Venomous.html#python/2","title":"Venomous.python/2","type":"function"},{"doc":"- `Venomous.SnakeArgs` struct of :module, :func, :args \n - opts \\ []","ref":"Venomous.html#python/2-parameters","title":"Parameters - Venomous.python/2","type":"function"},{"doc":"- `:python_timeout` ms timeout. Kills python OS process on timeout. Default: 15_000\n- `:kill_python_on_exception` Should python process be killed on exception. Should be set to true if your python process exits by itself. Default: false","ref":"Venomous.html#python/2-opts","title":"Opts - Venomous.python/2","type":"function"},{"doc":"- any() | {:error, :timeout} | {retrieve_error: any()} retrieves output of python function or error","ref":"Venomous.html#python/2-returns","title":"Returns - Venomous.python/2","type":"function"},{"doc":"If no Snake is available will continue requesting it with the given interval until any gets freed or receives :EXIT signal","ref":"Venomous.html#python!/2","title":"Venomous.python!/2","type":"function"},{"doc":"- `:retrieve_interval` ms to wait before requesting snake again Default: 200\n- `:python_timeout` ms timeout. Kills python OS process on timeout. Default: 15_000\n- `:kill_python_on_exception` Should python process be killed on exception. Should be set to true if your python process exits by itself. Default: false","ref":"Venomous.html#python!/2-opts","title":"Opts - Venomous.python!/2","type":"function"},{"doc":"Retrieves `Venomous.SnakeWorker` struct and sets it's status to :retrieved preventing other processes from accessing it.\nIf all processes are busy and exceeds max_children will return {:retrieve_error, message}.","ref":"Venomous.html#retrieve_snake/0","title":"Venomous.retrieve_snake/0","type":"function"},{"doc":"- `Venomous.SnakeWorker` struct. In case of error `{:retrieve_error, message}`","ref":"Venomous.html#retrieve_snake/0-returns","title":"Returns - Venomous.retrieve_snake/0","type":"function"},{"doc":"If all processes are busy and exceeds max_children will wait for interval ms and try again. Traps the exit signals, to safely escape loop.","ref":"Venomous.html#retrieve_snake!/1","title":"Venomous.retrieve_snake!/1","type":"function"},{"doc":"- interval: The time to wait in milliseconds before retrying. Default is `@wait_for_snake_interval`.","ref":"Venomous.html#retrieve_snake!/1-parameters","title":"Parameters - Venomous.retrieve_snake!/1","type":"function"},{"doc":"- `Venomous.SnakeWorker` struct.","ref":"Venomous.html#retrieve_snake!/1-returns","title":"Returns - Venomous.retrieve_snake!/1","type":"function"},{"doc":"Kills the named python process\n:brutal also kills the OS process of python, ensuring the process does not continue execution.","ref":"Venomous.html#slay_pet_worker/2","title":"Venomous.slay_pet_worker/2","type":"function"},{"doc":"- `name` atom\n- a Way to kill process. :brutal additionally kills with kill -9 ensuring the python does not execute further. Default: :peaceful","ref":"Venomous.html#slay_pet_worker/2-parameters","title":"Parameters - Venomous.slay_pet_worker/2","type":"function"},{"doc":":ok","ref":"Venomous.html#slay_pet_worker/2-returns","title":"Returns - Venomous.slay_pet_worker/2","type":"function"},{"doc":"Kills python process and its SnakeWorker\n:brutal also kills the OS process of python, ensuring the process does not continue execution.","ref":"Venomous.html#slay_python_worker/2","title":"Venomous.slay_python_worker/2","type":"function"},{"doc":"- `Venomous.SnakeWorker` struct\n - a Way to kill process. :brutal additionally kills with kill -9 ensuring the python does not execute further. Default: :peaceful","ref":"Venomous.html#slay_python_worker/2-parameters","title":"Parameters - Venomous.slay_python_worker/2","type":"function"},{"doc":":ok","ref":"Venomous.html#slay_python_worker/2-returns","title":"Returns - Venomous.slay_python_worker/2","type":"function"},{"doc":"Runs `Venomous.SnakeArgs` inside given `Venomous.SnakeWorker`.\nTraps exit and awaits signals [:SNAKE_DONE, :SNAKE_ERROR, :EXIT]\nIn case of an exit, brutally kills the python process ensuring it doesn't get executed any further.","ref":"Venomous.html#snake_run/3","title":"Venomous.snake_run/3","type":"function"},{"doc":"- `Venomous.SnakeArgs` struct of :module, :func, :args \n - `Venomous.SnakeWorker` struct\n - opts Keywords","ref":"Venomous.html#snake_run/3-parameters","title":"Parameters - Venomous.snake_run/3","type":"function"},{"doc":"- `:python_timeout` ms timeout. Kills python OS process on timeout. Default: 15_000\n- `:kill_python_on_exception` Should python process be killed on exception. Should be set to true if your python process exits by itself. Default: false","ref":"Venomous.html#snake_run/3-opts","title":"Opts - Venomous.snake_run/3","type":"function"},{"doc":"- any() | {:error, :timeout} | %SnakeError{} retrieves output of python function or error","ref":"Venomous.html#snake_run/3-returns","title":"Returns - Venomous.snake_run/3","type":"function"},{"doc":"Initializes Snake Manager/Supervisor/Watcher and handles config","ref":"Venomous.Application.html","title":"Venomous.Application","type":"module"},{"doc":"","ref":"Venomous.Application.html#start/2","title":"Venomous.Application.start/2","type":"function"},{"doc":"SnakeManager but for pets...","ref":"Venomous.PetSnakeManager.html","title":"Venomous.PetSnakeManager","type":"module"},{"doc":"Returns a specification to start this module under a supervisor.\n\nSee `Supervisor`.","ref":"Venomous.PetSnakeManager.html#child_spec/1","title":"Venomous.PetSnakeManager.child_spec/1","type":"function"},{"doc":"","ref":"Venomous.PetSnakeManager.html#init/1","title":"Venomous.PetSnakeManager.init/1","type":"function"},{"doc":"","ref":"Venomous.PetSnakeManager.html#start_link/1","title":"Venomous.PetSnakeManager.start_link/1","type":"function"},{"doc":"DynamicSupervisor for named `Venomous.SnakeWorker`\nThe maximum cap of `Venomous.SnakeWorker` is defined with :max_children option","ref":"Venomous.PetSnakeSupervisor.html","title":"Venomous.PetSnakeSupervisor","type":"module"},{"doc":"Returns a specification to start this module under a supervisor.\n\nSee `Supervisor`.","ref":"Venomous.PetSnakeSupervisor.html#child_spec/1","title":"Venomous.PetSnakeSupervisor.child_spec/1","type":"function"},{"doc":"Deploys a named snake with its own specified encoder and options","ref":"Venomous.PetSnakeSupervisor.html#deploy_snake_pet/1","title":"Venomous.PetSnakeSupervisor.deploy_snake_pet/1","type":"function"},{"doc":"","ref":"Venomous.PetSnakeSupervisor.html#init/1","title":"Venomous.PetSnakeSupervisor.init/1","type":"function"},{"doc":"","ref":"Venomous.PetSnakeSupervisor.html#start_link/1","title":"Venomous.PetSnakeSupervisor.start_link/1","type":"function"},{"doc":"🐍🔎 📁 A snake spy watching every step...\n\n\n Disabled by default. `config :venomous, :serpent_watcher, enable: true` to enable.\n\n Starts python watchdog process, watching over every python module inside module_paths directories.\n Default watcher requires watchdog module, which can be installed with `mix venomous.watchdog install` \n Whenever file is edited/created/deleted watcher casts `:reload` with module name to SnakeManager.\n The default reload module function imports and reloads the module from its name.","ref":"Venomous.SerpentWatcher.html","title":"Venomous.SerpentWatcher","type":"module"},{"doc":"```elixir\nconfig :venomous,\n serpent_watcher: [\n enable: true, # Disabled by default\n logging: true, # Hot reload logging. Enabled by default\n module: :serpent_watcher, # default\n func: :watch_directories, #default\n manager_pid: Venomous.SnakeManager # default\n ]\n```\n```elixir\nconfig :venomous, :snake_manager, %{\n ...\n reload_module: :reload, # default. reload function is hard coded to :reload\n ...\n}\n```","ref":"Venomous.SerpentWatcher.html#module-configuration","title":"Configuration - Venomous.SerpentWatcher","type":"module"},{"doc":"Returns a specification to start this module under a supervisor.\n\nSee `Supervisor`.","ref":"Venomous.SerpentWatcher.html#child_spec/1","title":"Venomous.SerpentWatcher.child_spec/1","type":"function"},{"doc":"","ref":"Venomous.SerpentWatcher.html#handle_continue/2","title":"Venomous.SerpentWatcher.handle_continue/2","type":"function"},{"doc":"","ref":"Venomous.SerpentWatcher.html#init/1","title":"Venomous.SerpentWatcher.init/1","type":"function"},{"doc":"","ref":"Venomous.SerpentWatcher.html#start_link/1","title":"Venomous.SerpentWatcher.start_link/1","type":"function"},{"doc":"A module to handle arguments for a Python function call.\n\nThis module defines a struct for storing the module name, function name,\nand the list of arguments that can be used to call a Python function.","ref":"Venomous.SnakeArgs.html","title":"Venomous.SnakeArgs","type":"module"},{"doc":"Builds SnakeArgs struct from params","ref":"Venomous.SnakeArgs.html#from_params/3","title":"Venomous.SnakeArgs.from_params/3","type":"function"},{"doc":"- module atom() of python module ex. :builtins\n - function atom() of function from given module ex. :sum\n - args list(any()) list of arguments for function ex. [ [1,2,3,4,5] ]","ref":"Venomous.SnakeArgs.html#from_params/3-parameters","title":"Parameters - Venomous.SnakeArgs.from_params/3","type":"function"},{"doc":"%SnakeArgs{}","ref":"Venomous.SnakeArgs.html#from_params/3-returns","title":"Returns - Venomous.SnakeArgs.from_params/3","type":"function"},{"doc":"","ref":"Venomous.SnakeArgs.html#t:t/0","title":"Venomous.SnakeArgs.t/0","type":"type"},{"doc":"A module to handle errors raised during Python function calls.\n\nThis module defines a struct for storing exception information,\nincluding the exception itself, the error message, and the backtrace.","ref":"Venomous.SnakeError.html","title":"Venomous.SnakeError","type":"module"},{"doc":"","ref":"Venomous.SnakeError.html#t:t/0","title":"Venomous.SnakeError.t/0","type":"type"},{"doc":"Manager for brave 🐍 workers\n\nThis module manages the snake workers, ensuring that inactive workers are cleaned up periodically.\n\nMain call `:get_ready_snake` retrieves/spawns a `Venomous.SnakeWorker` with :retrieved status.\nWorkers with status :ready and :retrieved are considered inactive and will be cleared up by main process loop running `:clean_inactive_workers` if they exceed their given TTL\nWorkers with :retrieved retrieved again until they are used.","ref":"Venomous.SnakeManager.html","title":"Venomous.SnakeManager","type":"module"},{"doc":"The following configurations are retrieved from :venomous :snake_manager Application env:\n\n- `erlport_encoder: %{module: atom(), func: atom(), args: list(any())}`: Optional :erlport encoder/decoder python function for converting types. The function can also provide any callbacks from :erlport documentation like .cast() message handler\n- `snake_ttl_minutes: non_neg_integer()`: Time-to-live for a Snake in minutes. Default is 15 min.\n- `perpetual_workers: non_neg_integer()`: Number of Snakes to keep alive perpetually. Default is 10.\n- `cleaner_interval: non_neg_integer()`: Interval in milliseconds for cleaning up inactive Snakes. Default is 60_000 ms.","ref":"Venomous.SnakeManager.html#module-configuration","title":"Configuration - Venomous.SnakeManager","type":"module"},{"doc":"Returns a specification to start this module under a supervisor.\n\nSee `Supervisor`.","ref":"Venomous.SnakeManager.html#child_spec/1","title":"Venomous.SnakeManager.child_spec/1","type":"function"},{"doc":"","ref":"Venomous.SnakeManager.html#get_snake_worker_status/2","title":"Venomous.SnakeManager.get_snake_worker_status/2","type":"function"},{"doc":"","ref":"Venomous.SnakeManager.html#handle_continue/2","title":"Venomous.SnakeManager.handle_continue/2","type":"function"},{"doc":"","ref":"Venomous.SnakeManager.html#init/1","title":"Venomous.SnakeManager.init/1","type":"function"},{"doc":"","ref":"Venomous.SnakeManager.html#start_link/1","title":"Venomous.SnakeManager.start_link/1","type":"function"},{"doc":"Module for converting Venomous python config keywords to erlport ones","ref":"Venomous.SnakeOpts.html","title":"Venomous.SnakeOpts","type":"module"},{"doc":"","ref":"Venomous.SnakeOpts.html#to_erlport_opts/1","title":"Venomous.SnakeOpts.to_erlport_opts/1","type":"function"},{"doc":"DynamicSupervisor for Snakes\nThe maximum cap of `Venomous.SnakeWorker` is defined with :max_children option\n> #### Warning {: .warning}\n>\n> The maximum amount of python processes is capped at your systems maximum number of open file-descriptors\n> `ulimit -n` to check your limit","ref":"Venomous.SnakeSupervisor.html","title":"Venomous.SnakeSupervisor","type":"module"},{"doc":"Returns a specification to start this module under a supervisor.\n\nSee `Supervisor`.","ref":"Venomous.SnakeSupervisor.html#child_spec/1","title":"Venomous.SnakeSupervisor.child_spec/1","type":"function"},{"doc":"Deploys snake with given opts Map containing :erlport encoder/decoder module, func and args","ref":"Venomous.SnakeSupervisor.html#deploy_snake_worker/1","title":"Venomous.SnakeSupervisor.deploy_snake_worker/1","type":"function"},{"doc":"","ref":"Venomous.SnakeSupervisor.html#init/1","title":"Venomous.SnakeSupervisor.init/1","type":"function"},{"doc":"","ref":"Venomous.SnakeSupervisor.html#start_link/1","title":"Venomous.SnakeSupervisor.start_link/1","type":"function"},{"doc":"🔨🐍\nA brave snake worker slithering across...\n\nThis module defines a GenServer that manages a snake worker, which interacts with a Python process to execute specified functions asynchronously.\nThe main :run_snake call, creates a `Task.async/1` which calls python and handles exceptions returning python result or an Error struct which gets sent with signal to the caller process. This `Task` gets awaited inside the :run cast(). The original call() returns :ok","ref":"Venomous.SnakeWorker.html","title":"Venomous.SnakeWorker","type":"module"},{"doc":"Python options can be configured inside :venomous :python_opts config key\n\n All of these are optional. However you will most likely want to set module_paths\n ```elixir\n @available_opts [\n :module_paths, # List of paths to your python modules\n :cd, # Change python's directory on spawn. Default is $PWD\n :compressed, # Can be set from 0-9. May affect performance. Read more on [Erlport documentation](http://erlport.org/docs/python.html#erlang-api)\n :envvars, # additional python process envvars\n :packet_bytes, # Size of erlport python packet. Default: 4 = max 4GB of data. Can be set to 1 = 256 bytes or 2 = ? bytes if you are sure you won't be transfering a lot of data.\n :python_executable # path to python executable to use.\n]\n```","ref":"Venomous.SnakeWorker.html#module-configuration","title":"Configuration - Venomous.SnakeWorker","type":"module"},{"doc":"Returns a specification to start this module under a supervisor.\n\nSee `Supervisor`.","ref":"Venomous.SnakeWorker.html#child_spec/1","title":"Venomous.SnakeWorker.child_spec/1","type":"function"},{"doc":"","ref":"Venomous.SnakeWorker.html#handle_continue/2","title":"Venomous.SnakeWorker.handle_continue/2","type":"function"},{"doc":"","ref":"Venomous.SnakeWorker.html#init/1","title":"Venomous.SnakeWorker.init/1","type":"function"},{"doc":"","ref":"Venomous.SnakeWorker.html#start_link/1","title":"Venomous.SnakeWorker.start_link/1","type":"function"},{"doc":"","ref":"Venomous.SnakeWorker.html#t:t/0","title":"Venomous.SnakeWorker.t/0","type":"type"},{"doc":"![Venomous](https://github.com/RustySnek/Venomous/blob/master/assets/venomous_logo.png)\n\n> A wrapper for managing concurrent [Erlport](http://erlport.org/) Python processes with ease.\n\n[![CI](https://github.com/rustysnek/venomous/actions/workflows/elixir.yml/badge.svg)](https://github.com/rustysnek/venomous/actions/workflows/elixir.yml)\n[![Hex.pm](https://img.shields.io/hexpm/v/venomous)](https://hex.pm/packages/venomous)\n[![Hex.pm](http://img.shields.io/hexpm/dt/venomous.svg)](https://hex.pm/packages/venomous)\n\nVenomous is a wrapper around erlport python Ports, designed to simplify concurrent use. It focuses on dynamic extensibility, like spawning, reusing and killing processes on demand. Furthermore, unused processes get automatically killed by scheduled process which can be configured inside config.exs. Venomous core functions capture and handle :EXIT calls ensuring that all python process die with it and do not continue their execution.","ref":"readme.html","title":"README","type":"extras"},{"doc":"Add `:venomous` to your list of dependencies in `mix.exs`:\n```elixir\ndef deps do\n [\n {:venomous, \"~> 0.6.0\"}\n ]\nend\n```","ref":"readme.html#installation","title":"Installation - README","type":"extras"},{"doc":"Check the [documentation](https://hexdocs.pm/venomous) for more in-depth information.\n \n For custom type conversion see the [Handling Erlport API](https://github.com/RustySnek/Venomous/blob/master/PYTHON.md)\n\n > By default the python modules to load are kept inside PYTHONPATH envvar.\n > but I highly recommend setting them inside python_opts[:module_paths] for hot reloading comp.\n\n You can checkout examples [here](https://github.com/RustySnek/venomous-examples)","ref":"readme.html#getting-started","title":"Getting Started - README","type":"extras"},{"doc":"```elixir\n config :venomous, :snake_manager, %{\n # Optional :erlport encoder/decoder for type conversion between elixir/python applied to all workers. The function may also include any :erlport callbacks from python api\n erlport_encoder: %{\n module: :my_encoder_module,\n func: :encode_my_snakes_please,\n args: []\n },\n # TTL whenever python process is inactive. Default: 15\n snake_ttl_minutes: 10,\n # Number of python workers that don't get cleared by SnakeManager when their TTL while inactive ends. Default: 10\n perpetual_workers: 1,\n # Interval for killing python processes past their ttl while inactive. Default: 60_000ms (1 min)\n cleaner_interval: 5_000,\n # reload module for hot reloading.\n # default is already provided inside venomous python/ directory\n reload_module: :reload,\n\n # Erlport python options\n python_opts: [\n module_paths: [\"/path/to/my/modules\", \"/path/to/other/modules\"], # List of paths to your python modules.\n cd: \"/\", # Change python's directory on spawn. Default is $PWD\n compressed: 0, # Can be set from 0-9. May affect performance. Read more on [Erlport documentation](http://erlport.org/docs/python.html#erlang-api)\n envvars: [SNAKE_VAR_ONE: \"I'm a snake\", SNAKE_VAR_TWO: \"No, you are not\"], # additional python process envvars\n packet_bytes: 4, # Size of erlport python packet. Default: 4 = max 4GB of data. Can also be set to 1 = 256 bytes or 2 = ? bytes if you are sure you won't be transfering a lot of data.\n python_executable: \"/bin/python\" # Change the path to python executable to use.\n ]\n }\n ```","ref":"readme.html#configure-the-snakemanager-options","title":"Configure the SnakeManager options - README","type":"extras"},{"doc":"Requires watchdog python module, which can be installed with `mix venomous.watchdog install`.\n Currently only supports the SnakeManager's processes. Watches only directories specified in `module_paths`\n ```elixir\n config :venomous, :serpent_watcher, [\n enable: true, # Defaults to false\n logging: true, # log every hot reload. Default: true\n module: :serpent_watcher, # Provided by default\n func: :watch_directories, # Provided by default\n manager_pid: Venomous.SnakeManager, # Provided by default\n ]\n ```","ref":"readme.html#enable-the-hot-reloading","title":"Enable the Hot reloading - README","type":"extras"},{"doc":"```elixir\n defmodule YourApp.Application do\n @moduledoc false\n\n use Application\n\n @doc false\n def start(_type, _args) do\n children = [\n {Venomous.SnakeSupervisor, [strategy: :one_for_one, max_restarts: 0, max_children: 50]},\n {Venomous.PetSnakeSupervisor, [strategy: :one_for_one, max_children: 10]} # not necessary\n ]\n opts = [strategy: :one_for_one, name: YourApp.Supervisor]\n Supervisor.start_link(children, opts)\n end\n end\n ```","ref":"readme.html#configure-the-snakesupervisor-and-petsnakesupervisor-if-needed-to-start-on-application-boot","title":"Configure the SnakeSupervisor and PetSnakeSupervisor (if needed) to start on application boot. - README","type":"extras"},{"doc":"","ref":"readme.html#quickstart","title":"Quickstart - README","type":"extras"},{"doc":"```elixir\nalias Venomous.SnakeArgs\nimport Venomous\n\ntimeout = 1_000\nargs = SnakeArgs.from_params(:builtins, :sum, [[0,1,2,3,4,5]])\n\ncase python(args, python_timeout: timeout) do\n {:retrieve_error, msg} -> \"No Snakes? #{inspect(msg)}\"\n %{error: :timeout} -> \"We timed out...\"\n sum -> assert sum == 15\nend\n\n# or just use python!/3 which waits for the available snake.\ntimeout = :infinity\nassert python!(args, python_timeout: timeout) == 15\n```","ref":"readme.html#basic-way-to-call-python-process","title":"Basic way to call python process - README","type":"extras"},{"doc":"Venomous is designed with concurrency, as well as proper exits in mind.\n```elixir\nalias Venomous.SnakeArgs\nimport Venomous\n\n# Venomous can handle as much concurrent python as you've setup\n# in your snake_manager configuration. However the python! will\n# wait for any process to free up in case none are available.\nargs = SnakeArgs.from_params(:time, :sleep, [0.5])\nEnum.map(1..100, fn _ -> \n Task.async(fn ->\n python!(args)\n end)\nend) |> Task.await_many(5_000)\n\n# You can view the spawned and ready snakes using the list_alive_snakes() \nlist_alive_snakes() |> dbg\n```\n```elixir\nalias Venomous.SnakeArgs\nimport Venomous\n\n# Venomous kills the OS pid of the python process on :EXIT\n# ensuring the process will not proceed with the execution further\nEnum.map(1..200, fn _ ->\n {:ok, pid} =\n Task.start(fn ->\n SnakeArgs.from_params(:time, :sleep, [1000]) |> python!()\n end)\n\n pid\nend)\n|> Enum.each(fn pid ->\n Process.send_after(pid, {:EXIT, :snake_slithered_away}, 100)\nend)\n\n# We'll sleep to make sure all exits got sent.\nProcess.sleep(1_000)\nassert list_alive_snakes() == []\n```","ref":"readme.html#concurrency-and-exit-signals","title":"Concurrency and :EXIT signals - README","type":"extras"},{"doc":"Venomous provides an easy way to convert structs into classes and back with VenomousTrait class and `mix venomous.structs ...` task.\n```\n$ mix venomous.structs\nSimple utility to create python elixir compatible classes.\n\n VenomousTrait class provides 2 functions: \n - def from_dict(cls, erl_map: Map | Dict, structs: Dict = {}) -> cls\n # converts Erlport Map or a Dict into the object class\n - def into_erl(self) -> Map\n # returns erlang compatible struct from self\n\n \n To create basic python classes and encode/decode functions based on structs: \n - mix venomous.structs MyModule.MyStruct MyModule.MoreStructs ...\n\n To create extended classes depending on existing python class: \n - mix venomous.structs MyModule.MyStruct:PythonClassName ...\n\n To create for all available structs inside an application\n - mix venomous.structs all my_application\n```\n\nYou can see this used in the [struct_test.exs](https://github.com/RustySnek/Venomous/blob/struct_class_handling/test/struct_test.exs) and [test_venomous.py](https://github.com/RustySnek/Venomous/blob/struct_class_handling/python/test_venomous.py)","ref":"readme.html#struct-class-comp","title":"Struct/Class comp - README","type":"extras"},{"doc":"# Quick guide on erlport Python API\nYou can read more about this in the [erlport documentation](http://erlport.org/docs/python.html)\n\nYou can find the default data types mapping [here](http://erlport.org/docs/python.html#data-types-mapping)","ref":"python.html","title":"Quick guide on erlport Python API","type":"extras"},{"doc":"The function passed to the snake_manager's erlport_encoder should be a main function containing everything you will setup further.\n```python\nfrom erlport.erlang import set_decoder, set_encoder, set_message_handler\nfrom erlport.erlterms import Atom\n\ndef main_encoder():\n set_decoder(decoder_func)\n set_encoder(encoder_func)\n set_message_handler(cast_handler_func)\n return Atom(\"ok\".encode(\"utf-8\"))\n```","ref":"python.html#creating-an-encoder-decoder","title":"Creating an encoder/decoder - Quick guide on erlport Python API","type":"extras"},{"doc":"Here is an example of encoding a simple class\n> While this is possible, a better way would be to handle them in a function that returns this type directly.\n```python\nfrom dataclasses import dataclass\nfrom erlport.erlterms import Atom\n\n@dataclass\nclass Cat:\n name: str\n color: str\n favorite_snacks: list[str]\n\n# By default erlport converts regular strings into charlists.\n# We can handle most of the cases by encoding strings into utf-8 with a simple function like this.\ndef encode_basic_type_strings(data):\n if isinstance(data, str):\n return data.encode(\"utf-8\")\n elif isinstance(data, list):\n return [encode_basic_type_strings(item) for item in data]\n elif isinstance(data, tuple):\n return tuple(encode_basic_type_strings(item) for item in data)\n elif isinstance(data, dict):\n return {key: encode_basic_type_strings(value) for key, value in data.items()}\n else:\n return data\n\ndef encoder(value: any):\n if isinstance(value, Cat):\n # We .__dict__ the class and normalize it's key,values.\n # Erlport will convert this dict into a Map\n return {\n Atom(encode_basic_type_strings(key)): # Convert the keys to atoms\n encode_basic_type_strings(val) # utf-8 Encode strings inside\n for key, val in value.__dict__.items()\n }\n # If none matches we encode strings, and return\n return encode_basic_type_strings(value)\n```","ref":"python.html#an-encoder-is-a-function-that-handles-conversion-python-elixir","title":"An Encoder is a function that handles conversion PYTHON -> ELIXIR - Quick guide on erlport Python API","type":"extras"},{"doc":"Here is an example of decoding elixir's parameters\n```python\nfrom erlport.erlterms import Atom, Map\n\ndef decoder(value: any):\n # Elixir strings convert to bytes, we can decode them into utf-8 strings.\n if isinstance(value, bytes):\n return value.decode('utf-8')\n if isinstance(value, Map):\n # If its a Map custom type we decode bytes into utf-8 strings\n return {\n key.decode(\"utf-8\"): [v.decode(\"utf-8\") for v in val]\n for key, val in value.items()\n }\n # if none get caught we just return the raw inputs\n return value\n\n```","ref":"python.html#a-decoder-is-a-function-that-handles-conversion-elixir-python","title":"A decoder is a function that handles conversion ELIXIR -> PYTHON - Quick guide on erlport Python API","type":"extras"}],"producer":{"name":"ex_doc","version":[48,46,51,52,46,48]}} \ No newline at end of file +searchData={"content_type":"text/markdown","items":[{"doc":"Used for installing/uninstalling python watchdog module into python/ directory.","ref":"Mix.Tasks.Venomous.Watchdog.html","title":"mix venomous.watchdog","type":"task"},{"doc":"","ref":"Mix.Tasks.Venomous.Watchdog.html#uninstall_watchdog/0","title":"Mix.Tasks.Venomous.Watchdog.uninstall_watchdog/0","type":"function"},{"doc":"Venomous is a wrapper around erlport python Ports, designed to simplify concurrent use. It focuses dynamic extensibility, like spawning, reusing and killing processes on demand. Furthermore, unused processes get automatically killed by scheduled process which can be configured inside config.exs. Venomous core functions capture and handle :EXIT calls ensuring that all python process die with it and do not continue their execution.\n\nThe core concept revolves around \"Snakes\" which represent Python worker processes. These `Venomous.SnakeWorker` are managed and supervised with `Venomous.SnakeManager` GenServer to allow concurrent and efficient execution of Python code. The `Snakes` pids and python pids are stored inside `:ets` table and the Processes are handled by `DymanicSupervisor` called `Venomous.SnakeSupervisor`. The unused `Snakes` get automatically killed by `SnakeManager` depending on the given configuration.\n\nYou can checkout examples [here](https://github.com/RustySnek/venomous-examples)\n\nBe sure to also check the [README](readme.html)","ref":"Venomous.html","title":"Venomous","type":"module"},{"doc":"","ref":"Venomous.html#module-main-functionality","title":"Main Functionality - Venomous","type":"module"},{"doc":"These are automatically managed and made for concurrent operations\n - `python/2`: The primary function to execute a Python function. It retrieves a Snake (Python worker process) and runs the specified Python function using the arguments provided in a `SnakeArgs` struct. If no ready Snakes are available, a new one is spawned. If max_children is reached it will return an error with appropriate message.\n - `python!/2` | `python!/1`: Will wait until any `Venomous.SnakeWorker` is freed, requesting it with the given interval.","ref":"Venomous.html#module-basic-processes","title":"Basic processes - Venomous","type":"module"},{"doc":"Python processes with unique names. Meant for miscellaneous processes.\n - `adopt_snake_pet/2`: Creates a new `Venomous.SnakeWorker` with a name inside `Venomous.PetSnakeSupervisor`\n - `pet_snake_run/3`: Runs given `Venomous.SnakeArgs` inside the named python process","ref":"Venomous.html#module-named-processes","title":"Named processes - Venomous","type":"module"},{"doc":"Venomous consists of several key components:\n\n- `Venomous.SerpentWatcher`: Manages hot reloading.\n- `Venomous.SnakeWorker`: Manages the execution of Python processes.\n- `Venomous.SnakeSupervisor`: A DynamicSupervisor that oversees the SnakeWorkers.\n- `Venomous.SnakeManager`: A GenServer that coordinates the SnakeWorkers and handles operations like spawning, retrieval and cleanup.\n- `Venomous.PetSnakeSupervisor`: Similar to SnakeSupervisor but for named processes.\n- `Venomous.PetSnakeManager`: Manages named python processes","ref":"Venomous.html#module-architecture","title":"Architecture - Venomous","type":"module"},{"doc":"","ref":"Venomous.html#module-configuration-options","title":"Configuration Options - Venomous","type":"module"},{"doc":"The behavior and management of Snakes can be configured through the following options:\n```elixir\n:venomous, :snake_manager, %{\n snake_ttl_minutes: non_neg_integer(), # Time-to-live for a Snake in minutes. Default is 15 min.\n perpetual_workers: non_neg_integer(), # Number of Snakes to keep alive perpetually. Default is 10.\n cleaner_interval: non_neg_integer(), # Interval in milliseconds for cleaning up inactive Snakes. Default is 60_000 ms.\n erlport_encoder: %{module: atom(), func: atom(), args: list(any())}, # Optional :erlport encoder/decoder python function for converting types. This function is applied to every unnamed python process started by SnakeManager. For more information see [Handling Erlport API](PYTHON.md)\n }\n```","ref":"Venomous.html#module-snakemanager","title":"SnakeManager - Venomous","type":"module"},{"doc":"All of these are optional. However you will most likely want to set module_paths\n ```elixir\n config :venomous, :snake_manager, %{\n ...\n python_opts: [\n module_paths: [], # List of paths to your python modules.\n cd: \"\", # Change python's directory on spawn. Default is $PWD\n compressed: 0, # Can be set from 0-9. May affect performance. Read more on [Erlport documentation](http://erlport.org/docs/python.html#erlang-api)\n envvars: [], # additional python process envvars\n packet_bytes: 4, # Size of erlport python packet. Default: 4 = max 4GB of data. Can be set to 1 = 256 bytes or 2 = ? bytes if you are sure you won't be transfering a lot of data.\n python_executable: \"\" # path to python executable to use. defaults to PATH\n ]\n ...\n}\n```","ref":"Venomous.html#module-python-options","title":"Python options - Venomous","type":"module"},{"doc":"Requires watchdog python module, which can be installed with `mix venomous.watchdog install`.\n Only files inside `module_paths` config are watched.\n ```elixir\n config :venomous, :serpent_watcher, enable: true\n ```","ref":"Venomous.html#module-hot-reloading","title":"Hot reloading - Venomous","type":"module"},{"doc":"Venomous provides an easy way to convert structs into classes and back with VenomousTrait class and `mix venomous.structs ...` task.\n ```\n $ mix venomous.structs\n Simple utility to create python elixir compatible classes.\n\n VenomousTrait class provides 2 functions: \n - def from_dict(cls, erl_map: Map | Dict, structs: Dict = {}) -> cls\n # converts Erlport Map or a Dict into the object class\n - def into_erl(self) -> Map\n # returns erlang compatible struct from self\n\n \n To create basic python classes and encode/decode functions based on structs: \n - mix venomous.structs MyModule.MyStruct MyModule.MoreStructs ...\n\n To create extended classes depending on existing python class: \n - mix venomous.structs MyModule.MyStruct:PythonClassName ...\n\n To create for all available structs inside an application\n - mix venomous.structs all my_application\n ```\n\n You can see this used in the [struct_test.exs](https://github.com/RustySnek/Venomous/blob/struct_class_handling/test/struct_test.exs) and [test_venomous.py](https://github.com/RustySnek/Venomous/blob/struct_class_handling/python/test_venomous.py)","ref":"Venomous.html#module-struct-class-comp","title":"Struct/Class comp - Venomous","type":"module"},{"doc":"- `list_alive_snakes/0`: Returns a list of :ets table containing currently alive Snakes.\n\n- `clean_inactive_snakes/0`: Manually clears inactive Snakes depending on their ttl and returns the number of Snakes cleared.\n\n- `slay_python_worker/2`: Kills a specified Python worker process and its SnakeWorker. :brutal can be specified as option, which will `kill -9` the os process of python which prevents the code from executing until it finalizes or goes through iteration.\n\n- `slay_pet_worker/2`: Kills a named Python process\n\n- `retrieve_snake/0`: Retrieves a `Venomous.SnakeWorker` and sets its status to :retrieved\n \n- `get_snakes_ready/1`: Retrieves given amount of `Venomous.SnakeWorker`s","ref":"Venomous.html#module-auxiliary-functions","title":"Auxiliary Functions - Venomous","type":"module"},{"doc":"Creates a named `Venomous.SnakeWorker` inside `Venomous.PetSnakeSupervisor`","ref":"Venomous.html#adopt_snake_pet/2","title":"Venomous.adopt_snake_pet/2","type":"function"},{"doc":"- an atom() name.\n - opts for python process","ref":"Venomous.html#adopt_snake_pet/2-parameters","title":"Parameters - Venomous.adopt_snake_pet/2","type":"function"},{"doc":"Python options can be configured inside :venomous :python_opts config key\n\n All of these are optional. However you will most likely want to set module_paths\n\n - `erlport_encoder: %{module: atom(), func: atom(), args: list(any())}`: Optional :erlport encoder/decoder python function for converting types. This function is applied to every unnamed python process started by SnakeManager. For more information see [Handling Erlport API](PYTHON.md)\n - ```elixir\n @available_opts [\n :module_paths, # List of paths to your python modules\n :cd, # Change python's directory on spawn. Default is $PWD\n :compressed, # Can be set from 0-9. May affect performance. Read more on [Erlport documentation](http://erlport.org/docs/python.html#erlang-api)\n :envvars, # additional python process envvars\n :packet_bytes, # Size of erlport python packet. Default: 4 = max 4GB of data. Can be set to 1 = 256 bytes or 2 = ? bytes if you are sure you won't be transfering a lot of data.\n :python_executable # path to python executable to use.\n]\n```","ref":"Venomous.html#adopt_snake_pet/2-options","title":"Options - Venomous.adopt_snake_pet/2","type":"function"},{"doc":"- :ok, name - in case of success\n - :error, message - in case of failure","ref":"Venomous.html#adopt_snake_pet/2-returns","title":"Returns - Venomous.adopt_snake_pet/2","type":"function"},{"doc":"Clears inactive snakes manually, returns number of snakes cleared.","ref":"Venomous.html#clean_inactive_snakes/0","title":"Venomous.clean_inactive_snakes/0","type":"function"},{"doc":"Retrieves x amount of ready snakes and sets their status to :retrieved. In case of hitting max_children cap, stops and returns all available snakes.\n> #### Warning {: .warning}\n> In case of retrieving all available snakes and not using them right away, functions like `python!/2` and `retrieve_snake!/0` will loop until they are freed.","ref":"Venomous.html#get_snakes_ready/1","title":"Venomous.get_snakes_ready/1","type":"function"},{"doc":"- amount of snakes to retrieve","ref":"Venomous.html#get_snakes_ready/1-parameters","title":"Parameters - Venomous.get_snakes_ready/1","type":"function"},{"doc":"- A list of `Venomous.SnakeWorker` structs","ref":"Venomous.html#get_snakes_ready/1-returns","title":"Returns - Venomous.get_snakes_ready/1","type":"function"},{"doc":"Returns list of :ets table containing alive snakes","ref":"Venomous.html#list_alive_snakes/0","title":"Venomous.list_alive_snakes/0","type":"function"},{"doc":"Used to run given `Venomous.SnakeArgs` inside named snake\nDoes not handle :EXIT signals like `snake_run/2` does.\nIf pet snake with name does not exist will return :not_found","ref":"Venomous.html#pet_snake_run/3","title":"Venomous.pet_snake_run/3","type":"function"},{"doc":"Wrapper for calling python process\nTries to retrieve `Venomous.SnakeWorker` which then runs the given `Venomous.SnakeArgs`. In case of failure will return {:retrieve_error, message}.\nIn case :EXIT happens, it will kill python os process along with its worker and exit(reason)","ref":"Venomous.html#python/2","title":"Venomous.python/2","type":"function"},{"doc":"- `Venomous.SnakeArgs` struct of :module, :func, :args \n - opts \\ []","ref":"Venomous.html#python/2-parameters","title":"Parameters - Venomous.python/2","type":"function"},{"doc":"- `:python_timeout` ms timeout. Kills python OS process on timeout. Default: 15_000\n- `:kill_python_on_exception` Should python process be killed on exception. Should be set to true if your python process exits by itself. Default: false","ref":"Venomous.html#python/2-opts","title":"Opts - Venomous.python/2","type":"function"},{"doc":"- any() | {:error, :timeout} | {retrieve_error: any()} retrieves output of python function or error","ref":"Venomous.html#python/2-returns","title":"Returns - Venomous.python/2","type":"function"},{"doc":"If no Snake is available will continue requesting it with the given interval until any gets freed or receives :EXIT signal","ref":"Venomous.html#python!/2","title":"Venomous.python!/2","type":"function"},{"doc":"- `:retrieve_interval` ms to wait before requesting snake again Default: 200\n- `:python_timeout` ms timeout. Kills python OS process on timeout. Default: 15_000\n- `:kill_python_on_exception` Should python process be killed on exception. Should be set to true if your python process exits by itself. Default: false","ref":"Venomous.html#python!/2-opts","title":"Opts - Venomous.python!/2","type":"function"},{"doc":"Retrieves `Venomous.SnakeWorker` struct and sets it's status to :retrieved preventing other processes from accessing it.\nIf all processes are busy and exceeds max_children will return {:retrieve_error, message}.","ref":"Venomous.html#retrieve_snake/0","title":"Venomous.retrieve_snake/0","type":"function"},{"doc":"- `Venomous.SnakeWorker` struct. In case of error `{:retrieve_error, message}`","ref":"Venomous.html#retrieve_snake/0-returns","title":"Returns - Venomous.retrieve_snake/0","type":"function"},{"doc":"If all processes are busy and exceeds max_children will wait for interval ms and try again. Traps the exit signals, to safely escape loop.","ref":"Venomous.html#retrieve_snake!/1","title":"Venomous.retrieve_snake!/1","type":"function"},{"doc":"- interval: The time to wait in milliseconds before retrying. Default is `@wait_for_snake_interval`.","ref":"Venomous.html#retrieve_snake!/1-parameters","title":"Parameters - Venomous.retrieve_snake!/1","type":"function"},{"doc":"- `Venomous.SnakeWorker` struct.","ref":"Venomous.html#retrieve_snake!/1-returns","title":"Returns - Venomous.retrieve_snake!/1","type":"function"},{"doc":"Kills the named python process\n:brutal also kills the OS process of python, ensuring the process does not continue execution.","ref":"Venomous.html#slay_pet_worker/2","title":"Venomous.slay_pet_worker/2","type":"function"},{"doc":"- `name` atom\n- a Way to kill process. :brutal additionally kills with kill -9 ensuring the python does not execute further. Default: :peaceful","ref":"Venomous.html#slay_pet_worker/2-parameters","title":"Parameters - Venomous.slay_pet_worker/2","type":"function"},{"doc":":ok","ref":"Venomous.html#slay_pet_worker/2-returns","title":"Returns - Venomous.slay_pet_worker/2","type":"function"},{"doc":"Kills python process and its SnakeWorker\n:brutal also kills the OS process of python, ensuring the process does not continue execution.","ref":"Venomous.html#slay_python_worker/2","title":"Venomous.slay_python_worker/2","type":"function"},{"doc":"- `Venomous.SnakeWorker` struct\n - a Way to kill process. :brutal additionally kills with kill -9 ensuring the python does not execute further. Default: :peaceful","ref":"Venomous.html#slay_python_worker/2-parameters","title":"Parameters - Venomous.slay_python_worker/2","type":"function"},{"doc":":ok","ref":"Venomous.html#slay_python_worker/2-returns","title":"Returns - Venomous.slay_python_worker/2","type":"function"},{"doc":"Runs `Venomous.SnakeArgs` inside given `Venomous.SnakeWorker`.\nTraps exit and awaits signals [:SNAKE_DONE, :SNAKE_ERROR, :EXIT]\nIn case of an exit, brutally kills the python process ensuring it doesn't get executed any further.","ref":"Venomous.html#snake_run/3","title":"Venomous.snake_run/3","type":"function"},{"doc":"- `Venomous.SnakeArgs` struct of :module, :func, :args \n - `Venomous.SnakeWorker` struct\n - opts Keywords","ref":"Venomous.html#snake_run/3-parameters","title":"Parameters - Venomous.snake_run/3","type":"function"},{"doc":"- `:python_timeout` ms timeout. Kills python OS process on timeout. Default: 15_000\n- `:kill_python_on_exception` Should python process be killed on exception. Should be set to true if your python process exits by itself. Default: false","ref":"Venomous.html#snake_run/3-opts","title":"Opts - Venomous.snake_run/3","type":"function"},{"doc":"- any() | {:error, :timeout} | %SnakeError{} retrieves output of python function or error","ref":"Venomous.html#snake_run/3-returns","title":"Returns - Venomous.snake_run/3","type":"function"},{"doc":"Initializes Snake Manager/Supervisor/Watcher and handles config","ref":"Venomous.Application.html","title":"Venomous.Application","type":"module"},{"doc":"","ref":"Venomous.Application.html#start/2","title":"Venomous.Application.start/2","type":"function"},{"doc":"SnakeManager but for pets...","ref":"Venomous.PetSnakeManager.html","title":"Venomous.PetSnakeManager","type":"module"},{"doc":"Returns a specification to start this module under a supervisor.\n\nSee `Supervisor`.","ref":"Venomous.PetSnakeManager.html#child_spec/1","title":"Venomous.PetSnakeManager.child_spec/1","type":"function"},{"doc":"","ref":"Venomous.PetSnakeManager.html#init/1","title":"Venomous.PetSnakeManager.init/1","type":"function"},{"doc":"","ref":"Venomous.PetSnakeManager.html#start_link/1","title":"Venomous.PetSnakeManager.start_link/1","type":"function"},{"doc":"DynamicSupervisor for named `Venomous.SnakeWorker`\nThe maximum cap of `Venomous.SnakeWorker` is defined with :max_children option","ref":"Venomous.PetSnakeSupervisor.html","title":"Venomous.PetSnakeSupervisor","type":"module"},{"doc":"Returns a specification to start this module under a supervisor.\n\nSee `Supervisor`.","ref":"Venomous.PetSnakeSupervisor.html#child_spec/1","title":"Venomous.PetSnakeSupervisor.child_spec/1","type":"function"},{"doc":"Deploys a named snake with its own specified encoder and options","ref":"Venomous.PetSnakeSupervisor.html#deploy_snake_pet/1","title":"Venomous.PetSnakeSupervisor.deploy_snake_pet/1","type":"function"},{"doc":"","ref":"Venomous.PetSnakeSupervisor.html#init/1","title":"Venomous.PetSnakeSupervisor.init/1","type":"function"},{"doc":"","ref":"Venomous.PetSnakeSupervisor.html#start_link/1","title":"Venomous.PetSnakeSupervisor.start_link/1","type":"function"},{"doc":"🐍🔎 📁 A snake spy watching every step...\n\n\n Disabled by default. `config :venomous, :serpent_watcher, enable: true` to enable.\n\n Starts python watchdog process, watching over every python module inside module_paths directories.\n Default watcher requires watchdog module, which can be installed with `mix venomous.watchdog install` \n Whenever file is edited/created/deleted watcher casts `:reload` with module name to SnakeManager.\n The default reload module function imports and reloads the module from its name.","ref":"Venomous.SerpentWatcher.html","title":"Venomous.SerpentWatcher","type":"module"},{"doc":"```elixir\nconfig :venomous,\n serpent_watcher: [\n enable: true, # Disabled by default\n logging: true, # Hot reload logging. Enabled by default\n module: :serpent_watcher, # default\n func: :watch_directories, #default\n manager_pid: Venomous.SnakeManager # default\n ]\n```\n```elixir\nconfig :venomous, :snake_manager, %{\n ...\n reload_module: :reload, # default. reload function is hard coded to :reload\n ...\n}\n```","ref":"Venomous.SerpentWatcher.html#module-configuration","title":"Configuration - Venomous.SerpentWatcher","type":"module"},{"doc":"Returns a specification to start this module under a supervisor.\n\nSee `Supervisor`.","ref":"Venomous.SerpentWatcher.html#child_spec/1","title":"Venomous.SerpentWatcher.child_spec/1","type":"function"},{"doc":"","ref":"Venomous.SerpentWatcher.html#handle_continue/2","title":"Venomous.SerpentWatcher.handle_continue/2","type":"function"},{"doc":"","ref":"Venomous.SerpentWatcher.html#init/1","title":"Venomous.SerpentWatcher.init/1","type":"function"},{"doc":"","ref":"Venomous.SerpentWatcher.html#start_link/1","title":"Venomous.SerpentWatcher.start_link/1","type":"function"},{"doc":"A module to handle arguments for a Python function call.\n\nThis module defines a struct for storing the module name, function name,\nand the list of arguments that can be used to call a Python function.","ref":"Venomous.SnakeArgs.html","title":"Venomous.SnakeArgs","type":"module"},{"doc":"Builds SnakeArgs struct from params","ref":"Venomous.SnakeArgs.html#from_params/3","title":"Venomous.SnakeArgs.from_params/3","type":"function"},{"doc":"- module atom() of python module ex. :builtins\n - function atom() of function from given module ex. :sum\n - args list(any()) list of arguments for function ex. [ [1,2,3,4,5] ]","ref":"Venomous.SnakeArgs.html#from_params/3-parameters","title":"Parameters - Venomous.SnakeArgs.from_params/3","type":"function"},{"doc":"%SnakeArgs{}","ref":"Venomous.SnakeArgs.html#from_params/3-returns","title":"Returns - Venomous.SnakeArgs.from_params/3","type":"function"},{"doc":"","ref":"Venomous.SnakeArgs.html#t:t/0","title":"Venomous.SnakeArgs.t/0","type":"type"},{"doc":"A module to handle errors raised during Python function calls.\n\nThis module defines a struct for storing exception information,\nincluding the exception itself, the error message, and the backtrace.","ref":"Venomous.SnakeError.html","title":"Venomous.SnakeError","type":"module"},{"doc":"","ref":"Venomous.SnakeError.html#t:t/0","title":"Venomous.SnakeError.t/0","type":"type"},{"doc":"Manager for brave 🐍 workers\n\nThis module manages the snake workers, ensuring that inactive workers are cleaned up periodically.\n\nMain call `:get_ready_snake` retrieves/spawns a `Venomous.SnakeWorker` with :retrieved status.\nWorkers with status :ready and :retrieved are considered inactive and will be cleared up by main process loop running `:clean_inactive_workers` if they exceed their given TTL\nWorkers with :retrieved retrieved again until they are used.","ref":"Venomous.SnakeManager.html","title":"Venomous.SnakeManager","type":"module"},{"doc":"The following configurations are retrieved from :venomous :snake_manager Application env:\n\n- `erlport_encoder: %{module: atom(), func: atom(), args: list(any())}`: Optional :erlport encoder/decoder python function for converting types. The function can also provide any callbacks from :erlport documentation like .cast() message handler\n- `snake_ttl_minutes: non_neg_integer()`: Time-to-live for a Snake in minutes. Default is 15 min.\n- `perpetual_workers: non_neg_integer()`: Number of Snakes to keep alive perpetually. Default is 10.\n- `cleaner_interval: non_neg_integer()`: Interval in milliseconds for cleaning up inactive Snakes. Default is 60_000 ms.","ref":"Venomous.SnakeManager.html#module-configuration","title":"Configuration - Venomous.SnakeManager","type":"module"},{"doc":"Returns a specification to start this module under a supervisor.\n\nSee `Supervisor`.","ref":"Venomous.SnakeManager.html#child_spec/1","title":"Venomous.SnakeManager.child_spec/1","type":"function"},{"doc":"","ref":"Venomous.SnakeManager.html#get_snake_worker_status/2","title":"Venomous.SnakeManager.get_snake_worker_status/2","type":"function"},{"doc":"","ref":"Venomous.SnakeManager.html#handle_continue/2","title":"Venomous.SnakeManager.handle_continue/2","type":"function"},{"doc":"","ref":"Venomous.SnakeManager.html#init/1","title":"Venomous.SnakeManager.init/1","type":"function"},{"doc":"","ref":"Venomous.SnakeManager.html#start_link/1","title":"Venomous.SnakeManager.start_link/1","type":"function"},{"doc":"Module for converting Venomous python config keywords to erlport ones","ref":"Venomous.SnakeOpts.html","title":"Venomous.SnakeOpts","type":"module"},{"doc":"","ref":"Venomous.SnakeOpts.html#to_erlport_opts/1","title":"Venomous.SnakeOpts.to_erlport_opts/1","type":"function"},{"doc":"DynamicSupervisor for Snakes\nThe maximum cap of `Venomous.SnakeWorker` is defined with :max_children option\n> #### Warning {: .warning}\n>\n> The maximum amount of python processes is capped at your systems maximum number of open file-descriptors\n> `ulimit -n` to check your limit","ref":"Venomous.SnakeSupervisor.html","title":"Venomous.SnakeSupervisor","type":"module"},{"doc":"Returns a specification to start this module under a supervisor.\n\nSee `Supervisor`.","ref":"Venomous.SnakeSupervisor.html#child_spec/1","title":"Venomous.SnakeSupervisor.child_spec/1","type":"function"},{"doc":"Deploys snake with given opts Map containing :erlport encoder/decoder module, func and args","ref":"Venomous.SnakeSupervisor.html#deploy_snake_worker/1","title":"Venomous.SnakeSupervisor.deploy_snake_worker/1","type":"function"},{"doc":"","ref":"Venomous.SnakeSupervisor.html#init/1","title":"Venomous.SnakeSupervisor.init/1","type":"function"},{"doc":"","ref":"Venomous.SnakeSupervisor.html#start_link/1","title":"Venomous.SnakeSupervisor.start_link/1","type":"function"},{"doc":"🔨🐍\nA brave snake worker slithering across...\n\nThis module defines a GenServer that manages a snake worker, which interacts with a Python process to execute specified functions asynchronously.\nThe main :run_snake call, creates a `Task.async/1` which calls python and handles exceptions returning python result or an Error struct which gets sent with signal to the caller process. This `Task` gets awaited inside the :run cast(). The original call() returns :ok","ref":"Venomous.SnakeWorker.html","title":"Venomous.SnakeWorker","type":"module"},{"doc":"Python options can be configured inside :venomous :python_opts config key\n\n All of these are optional. However you will most likely want to set module_paths\n ```elixir\n @available_opts [\n :module_paths, # List of paths to your python modules\n :cd, # Change python's directory on spawn. Default is $PWD\n :compressed, # Can be set from 0-9. May affect performance. Read more on [Erlport documentation](http://erlport.org/docs/python.html#erlang-api)\n :envvars, # additional python process envvars\n :packet_bytes, # Size of erlport python packet. Default: 4 = max 4GB of data. Can be set to 1 = 256 bytes or 2 = ? bytes if you are sure you won't be transfering a lot of data.\n :python_executable # path to python executable to use.\n]\n```","ref":"Venomous.SnakeWorker.html#module-configuration","title":"Configuration - Venomous.SnakeWorker","type":"module"},{"doc":"Returns a specification to start this module under a supervisor.\n\nSee `Supervisor`.","ref":"Venomous.SnakeWorker.html#child_spec/1","title":"Venomous.SnakeWorker.child_spec/1","type":"function"},{"doc":"","ref":"Venomous.SnakeWorker.html#handle_continue/2","title":"Venomous.SnakeWorker.handle_continue/2","type":"function"},{"doc":"","ref":"Venomous.SnakeWorker.html#init/1","title":"Venomous.SnakeWorker.init/1","type":"function"},{"doc":"","ref":"Venomous.SnakeWorker.html#start_link/1","title":"Venomous.SnakeWorker.start_link/1","type":"function"},{"doc":"","ref":"Venomous.SnakeWorker.html#t:t/0","title":"Venomous.SnakeWorker.t/0","type":"type"},{"doc":"![Venomous](https://github.com/RustySnek/Venomous/blob/master/assets/venomous_logo.png)\n\n> A wrapper for managing concurrent [Erlport](http://erlport.org/) Python processes with ease.\n\n[![CI](https://github.com/rustysnek/venomous/actions/workflows/elixir.yml/badge.svg)](https://github.com/rustysnek/venomous/actions/workflows/elixir.yml)\n[![Hex.pm](https://img.shields.io/hexpm/v/venomous)](https://hex.pm/packages/venomous)\n[![Hex.pm](http://img.shields.io/hexpm/dt/venomous.svg)](https://hex.pm/packages/venomous)\n\nVenomous is a wrapper around erlport python Ports, designed to simplify concurrent use. It focuses on dynamic extensibility, like spawning, reusing and killing processes on demand. Furthermore, unused processes get automatically killed by scheduled process which can be configured inside config.exs. Venomous core functions capture and handle :EXIT calls ensuring that all python process die with it and do not continue their execution.","ref":"readme.html","title":"README","type":"extras"},{"doc":"Add `:venomous` to your list of dependencies in `mix.exs`:\n```elixir\ndef deps do\n [\n {:venomous, \"~> 0.6.1\"}\n ]\nend\n```","ref":"readme.html#installation","title":"Installation - README","type":"extras"},{"doc":"Check the [documentation](https://hexdocs.pm/venomous) for more in-depth information.\n \n For custom type conversion see the [Handling Erlport API](https://github.com/RustySnek/Venomous/blob/master/PYTHON.md)\n\n > By default the python modules to load are kept inside PYTHONPATH envvar.\n > but I highly recommend setting them inside python_opts[:module_paths] for hot reloading comp.\n\n You can checkout examples [here](https://github.com/RustySnek/venomous-examples)","ref":"readme.html#getting-started","title":"Getting Started - README","type":"extras"},{"doc":"```elixir\n config :venomous, :snake_manager, %{\n # Optional :erlport encoder/decoder for type conversion between elixir/python applied to all workers. The function may also include any :erlport callbacks from python api\n erlport_encoder: %{\n module: :my_encoder_module,\n func: :encode_my_snakes_please,\n args: []\n },\n # TTL whenever python process is inactive. Default: 15\n snake_ttl_minutes: 10,\n # Number of python workers that don't get cleared by SnakeManager when their TTL while inactive ends. Default: 10\n perpetual_workers: 1,\n # Interval for killing python processes past their ttl while inactive. Default: 60_000ms (1 min)\n cleaner_interval: 5_000,\n # reload module for hot reloading.\n # default is already provided inside venomous python/ directory\n reload_module: :reload,\n\n # Erlport python options\n python_opts: [\n module_paths: [\"/path/to/my/modules\", \"/path/to/other/modules\"], # List of paths to your python modules.\n cd: \"/\", # Change python's directory on spawn. Default is $PWD\n compressed: 0, # Can be set from 0-9. May affect performance. Read more on [Erlport documentation](http://erlport.org/docs/python.html#erlang-api)\n envvars: [SNAKE_VAR_ONE: \"I'm a snake\", SNAKE_VAR_TWO: \"No, you are not\"], # additional python process envvars\n packet_bytes: 4, # Size of erlport python packet. Default: 4 = max 4GB of data. Can also be set to 1 = 256 bytes or 2 = ? bytes if you are sure you won't be transfering a lot of data.\n python_executable: \"/bin/python\" # Change the path to python executable to use.\n ]\n }\n ```","ref":"readme.html#configure-the-snakemanager-options","title":"Configure the SnakeManager options - README","type":"extras"},{"doc":"Requires watchdog python module, which can be installed with `mix venomous.watchdog install`.\n Currently only supports the SnakeManager's processes. Watches only directories specified in `module_paths`\n ```elixir\n config :venomous, :serpent_watcher, [\n enable: true, # Defaults to false\n logging: true, # log every hot reload. Default: true\n module: :serpent_watcher, # Provided by default\n func: :watch_directories, # Provided by default\n manager_pid: Venomous.SnakeManager, # Provided by default\n ]\n ```","ref":"readme.html#enable-the-hot-reloading","title":"Enable the Hot reloading - README","type":"extras"},{"doc":"```elixir\n defmodule YourApp.Application do\n @moduledoc false\n\n use Application\n\n @doc false\n def start(_type, _args) do\n children = [\n {Venomous.SnakeSupervisor, [strategy: :one_for_one, max_restarts: 0, max_children: 50]},\n {Venomous.PetSnakeSupervisor, [strategy: :one_for_one, max_children: 10]} # not necessary\n ]\n opts = [strategy: :one_for_one, name: YourApp.Supervisor]\n Supervisor.start_link(children, opts)\n end\n end\n ```","ref":"readme.html#configure-the-snakesupervisor-and-petsnakesupervisor-if-needed-to-start-on-application-boot","title":"Configure the SnakeSupervisor and PetSnakeSupervisor (if needed) to start on application boot. - README","type":"extras"},{"doc":"","ref":"readme.html#quickstart","title":"Quickstart - README","type":"extras"},{"doc":"```elixir\nalias Venomous.SnakeArgs\nimport Venomous\n\ntimeout = 1_000\nargs = SnakeArgs.from_params(:builtins, :sum, [[0,1,2,3,4,5]])\n\ncase python(args, python_timeout: timeout) do\n {:retrieve_error, msg} -> \"No Snakes? #{inspect(msg)}\"\n %{error: :timeout} -> \"We timed out...\"\n sum -> assert sum == 15\nend\n\n# or just use python!/3 which waits for the available snake.\ntimeout = :infinity\nassert python!(args, python_timeout: timeout) == 15\n```","ref":"readme.html#basic-way-to-call-python-process","title":"Basic way to call python process - README","type":"extras"},{"doc":"Venomous is designed with concurrency, as well as proper exits in mind.\n```elixir\nalias Venomous.SnakeArgs\nimport Venomous\n\n# Venomous can handle as much concurrent python as you've setup\n# in your snake_manager configuration. However the python! will\n# wait for any process to free up in case none are available.\nargs = SnakeArgs.from_params(:time, :sleep, [0.5])\nEnum.map(1..100, fn _ -> \n Task.async(fn ->\n python!(args)\n end)\nend) |> Task.await_many(5_000)\n\n# You can view the spawned and ready snakes using the list_alive_snakes() \nlist_alive_snakes() |> dbg\n```\n```elixir\nalias Venomous.SnakeArgs\nimport Venomous\n\n# Venomous kills the OS pid of the python process on :EXIT\n# ensuring the process will not proceed with the execution further\nEnum.map(1..200, fn _ ->\n {:ok, pid} =\n Task.start(fn ->\n SnakeArgs.from_params(:time, :sleep, [1000]) |> python!()\n end)\n\n pid\nend)\n|> Enum.each(fn pid ->\n Process.send_after(pid, {:EXIT, :snake_slithered_away}, 100)\nend)\n\n# We'll sleep to make sure all exits got sent.\nProcess.sleep(1_000)\nassert list_alive_snakes() == []\n```","ref":"readme.html#concurrency-and-exit-signals","title":"Concurrency and :EXIT signals - README","type":"extras"},{"doc":"Venomous provides an easy way to convert structs into classes and back with VenomousTrait class and `mix venomous.structs ...` task.\n```\n$ mix venomous.structs\nSimple utility to create python elixir compatible classes.\n\n VenomousTrait class provides 2 functions: \n - def from_dict(cls, erl_map: Map | Dict, structs: Dict = {}) -> cls\n # converts Erlport Map or a Dict into the object class\n - def into_erl(self) -> Map\n # returns erlang compatible struct from self\n\n \n To create basic python classes and encode/decode functions based on structs: \n - mix venomous.structs MyModule.MyStruct MyModule.MoreStructs ...\n\n To create extended classes depending on existing python class: \n - mix venomous.structs MyModule.MyStruct:PythonClassName ...\n\n To create for all available structs inside an application\n - mix venomous.structs all my_application\n```\n\nYou can see this used in the [struct_test.exs](https://github.com/RustySnek/Venomous/blob/struct_class_handling/test/struct_test.exs) and [test_venomous.py](https://github.com/RustySnek/Venomous/blob/struct_class_handling/python/test_venomous.py)","ref":"readme.html#struct-class-comp","title":"Struct/Class comp - README","type":"extras"},{"doc":"# Quick guide on erlport Python API\nYou can read more about this in the [erlport documentation](http://erlport.org/docs/python.html)\n\nYou can find the default data types mapping [here](http://erlport.org/docs/python.html#data-types-mapping)","ref":"python.html","title":"Quick guide on erlport Python API","type":"extras"},{"doc":"The function passed to the snake_manager's erlport_encoder should be a main function containing everything you will setup further.\n```python\nfrom erlport.erlang import set_decoder, set_encoder, set_message_handler\nfrom erlport.erlterms import Atom\n\ndef main_encoder():\n set_decoder(decoder_func)\n set_encoder(encoder_func)\n set_message_handler(cast_handler_func)\n return Atom(\"ok\".encode(\"utf-8\"))\n```","ref":"python.html#creating-an-encoder-decoder","title":"Creating an encoder/decoder - Quick guide on erlport Python API","type":"extras"},{"doc":"Here is an example of encoding a simple class\n> While this is possible, a better way would be to handle them in a function that returns this type directly.\n```python\nfrom dataclasses import dataclass\nfrom erlport.erlterms import Atom\n\n@dataclass\nclass Cat:\n name: str\n color: str\n favorite_snacks: list[str]\n\n# By default erlport converts regular strings into charlists.\n# We can handle most of the cases by encoding strings into utf-8 with a simple function like this.\ndef encode_basic_type_strings(data):\n if isinstance(data, str):\n return data.encode(\"utf-8\")\n elif isinstance(data, list):\n return [encode_basic_type_strings(item) for item in data]\n elif isinstance(data, tuple):\n return tuple(encode_basic_type_strings(item) for item in data)\n elif isinstance(data, dict):\n return {key: encode_basic_type_strings(value) for key, value in data.items()}\n else:\n return data\n\ndef encoder(value: any):\n if isinstance(value, Cat):\n # We .__dict__ the class and normalize it's key,values.\n # Erlport will convert this dict into a Map\n return {\n Atom(encode_basic_type_strings(key)): # Convert the keys to atoms\n encode_basic_type_strings(val) # utf-8 Encode strings inside\n for key, val in value.__dict__.items()\n }\n # If none matches we encode strings, and return\n return encode_basic_type_strings(value)\n```","ref":"python.html#an-encoder-is-a-function-that-handles-conversion-python-elixir","title":"An Encoder is a function that handles conversion PYTHON -> ELIXIR - Quick guide on erlport Python API","type":"extras"},{"doc":"Here is an example of decoding elixir's parameters\n```python\nfrom erlport.erlterms import Atom, Map\n\ndef decoder(value: any):\n # Elixir strings convert to bytes, we can decode them into utf-8 strings.\n if isinstance(value, bytes):\n return value.decode('utf-8')\n if isinstance(value, Map):\n # If its a Map custom type we decode bytes into utf-8 strings\n return {\n key.decode(\"utf-8\"): [v.decode(\"utf-8\") for v in val]\n for key, val in value.items()\n }\n # if none get caught we just return the raw inputs\n return value\n\n```","ref":"python.html#a-decoder-is-a-function-that-handles-conversion-elixir-python","title":"A decoder is a function that handles conversion ELIXIR -> PYTHON - Quick guide on erlport Python API","type":"extras"}],"producer":{"name":"ex_doc","version":[48,46,51,52,46,48]}} \ No newline at end of file diff --git a/docs/index.html b/docs/index.html index e8b925f..2bf5ef1 100644 --- a/docs/index.html +++ b/docs/index.html @@ -2,7 +2,7 @@
-- Hex Package + Hex Package - Hex Preview + Hex Preview - (current file) + (current file) diff --git a/docs/readme.html b/docs/readme.html index 0497689..407adb5 100644 --- a/docs/readme.html +++ b/docs/readme.html @@ -5,10 +5,10 @@ - + -
Add :venomous
to your list of dependencies in mix.exs
:
def deps do
- [
- {:venomous, "~> 0.6.0"}
- ]
-end
Add :venomous
to your list of dependencies in mix.exs
:
def deps do
+ [
+ {:venomous, "~> 0.6.1"}
+ ]
+end
config :venomous, :snake_manager, %{
+ config :venomous, :snake_manager, %{
# Optional :erlport encoder/decoder for type conversion between elixir/python applied to all workers. The function may also include any :erlport callbacks from python api
- erlport_encoder: %{
+ erlport_encoder: %{
module: :my_encoder_module,
func: :encode_my_snakes_please,
- args: []
- },
+ args: []
+ },
# TTL whenever python process is inactive. Default: 15
snake_ttl_minutes: 10,
# Number of python workers that don't get cleared by SnakeManager when their TTL while inactive ends. Default: 10
@@ -178,48 +178,48 @@
reload_module: :reload,
# Erlport python options
- python_opts: [
- module_paths: ["/path/to/my/modules", "/path/to/other/modules"], # List of paths to your python modules.
+ python_opts: [
+ module_paths: ["/path/to/my/modules", "/path/to/other/modules"], # List of paths to your python modules.
cd: "/", # Change python's directory on spawn. Default is $PWD
compressed: 0, # Can be set from 0-9. May affect performance. Read more on [Erlport documentation](http://erlport.org/docs/python.html#erlang-api)
- envvars: [SNAKE_VAR_ONE: "I'm a snake", SNAKE_VAR_TWO: "No, you are not"], # additional python process envvars
+ envvars: [SNAKE_VAR_ONE: "I'm a snake", SNAKE_VAR_TWO: "No, you are not"], # additional python process envvars
packet_bytes: 4, # Size of erlport python packet. Default: 4 = max 4GB of data. Can also be set to 1 = 256 bytes or 2 = ? bytes if you are sure you won't be transfering a lot of data.
python_executable: "/bin/python" # Change the path to python executable to use.
- ]
- }
+
]
+ }
Requires watchdog python module, which can be installed with mix venomous.watchdog install
.
- Currently only supports the SnakeManager's processes. Watches only directories specified in module_paths
config :venomous, :serpent_watcher, [
+ Currently only supports the SnakeManager's processes. Watches only directories specified in module_paths
config :venomous, :serpent_watcher, [
enable: true, # Defaults to false
logging: true, # log every hot reload. Default: true
module: :serpent_watcher, # Provided by default
func: :watch_directories, # Provided by default
manager_pid: Venomous.SnakeManager, # Provided by default
- ]
+
]
defmodule YourApp.Application do
+ defmodule YourApp.Application do
@moduledoc false
use Application
@doc false
- def start(_type, _args) do
- children = [
- {Venomous.SnakeSupervisor, [strategy: :one_for_one, max_restarts: 0, max_children: 50]},
- {Venomous.PetSnakeSupervisor, [strategy: :one_for_one, max_children: 10]} # not necessary
- ]
- opts = [strategy: :one_for_one, name: YourApp.Supervisor]
- Supervisor.start_link(children, opts)
- end
- end
+
def start(_type, _args) do
+ children = [
+ {Venomous.SnakeSupervisor, [strategy: :one_for_one, max_restarts: 0, max_children: 50]},
+ {Venomous.PetSnakeSupervisor, [strategy: :one_for_one, max_children: 10]} # not necessary
+ ]
+ opts = [strategy: :one_for_one, name: YourApp.Supervisor]
+ Supervisor.start_link(children, opts)
+ end
+ end
alias Venomous.SnakeArgs
+list_alive_snakes() |> dbg
alias Venomous.SnakeArgs
import Venomous
# Venomous kills the OS pid of the python process on :EXIT
# ensuring the process will not proceed with the execution further
-Enum.map(1..200, fn _ ->
- {:ok, pid} =
- Task.start(fn ->
- SnakeArgs.from_params(:time, :sleep, [1000]) |> python!()
- end)
+Enum.map(1..200, fn _ ->
+ {:ok, pid} =
+ Task.start(fn ->
+ SnakeArgs.from_params(:time, :sleep, [1000]) |> python!()
+ end)
pid
-end)
-|> Enum.each(fn pid ->
- Process.send_after(pid, {:EXIT, :snake_slithered_away}, 100)
-end)
+end)
+|> Enum.each(fn pid ->
+ Process.send_after(pid, {:EXIT, :snake_slithered_away}, 100)
+end)
# We'll sleep to make sure all exits got sent.
-Process.sleep(1_000)
-assert list_alive_snakes() == []
- Hex Package + Hex Package - Hex Preview + Hex Preview - (current file) + (current file) diff --git a/docs/search.html b/docs/search.html index a0a9b0a..bd943b5 100644 --- a/docs/search.html +++ b/docs/search.html @@ -5,12 +5,12 @@ - + -