diff --git a/docs/conf.py b/docs/conf.py index 5f7bed142..d69dc2b84 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -38,7 +38,6 @@ extensions = [ 'sphinx.ext.autodoc', 'sphinx.ext.viewcode', - 'sphinx_autodoc_annotation', ] # Add any paths that contain templates here, relative to this directory. diff --git a/docs/requirements.txt b/docs/requirements.txt index 6ba2c7197..c63762b6f 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,6 +1,4 @@ -sphinx>=1.2 - -sphinx-autodoc-annotation +sphinx>=8.2.3 -e . hypchat diff --git a/docs/user_guide/plugin_development/command_parameters.rst b/docs/user_guide/plugin_development/command_parameters.rst new file mode 100644 index 000000000..d2fe56334 --- /dev/null +++ b/docs/user_guide/plugin_development/command_parameters.rst @@ -0,0 +1,130 @@ +Command Parameters +================== + +This page explains how to handle command parameters in Errbot plugins, including default values, argument parsing, and best practices. + +Basic Command Parameters +------------------------ + +The most basic form of a bot command takes a message object and arguments: + +.. code-block:: python + + @botcmd + def hello(self, msg, args): + return f"Hello! You said: {args}" + +In this case, ``msg`` is the message object containing information about who sent the command and where, and ``args`` is a string containing everything after the command. + +Default Values +-------------- + +You can provide default values for command parameters. This is useful when you want to make certain arguments optional: + +.. code-block:: python + + @botcmd + def echo(self, msg, args="default message"): + return f"You said: {args}" + +In this example, if someone calls the command without arguments, ``args`` will be set to "default message". + +.. note:: + Default values work for both the ``msg`` and ``args`` parameters. However, it's recommended to only use default values for ``args`` as the ``msg`` parameter is typically required for proper command handling. + +Argument Splitting +------------------ + +You can automatically split arguments into a list using the ``split_args_with`` parameter: + +.. code-block:: python + + @botcmd(split_args_with=None) # Split on any whitespace + def count(self, msg, args): + # If user types: !count one two three + # args will be ['one', 'two', 'three'] + return f"You provided {len(args)} arguments" + +The ``split_args_with`` parameter works exactly like Python's ``str.split()``. Common values are: + +- ``None``: Split on any whitespace (recommended for most cases) +- ``' '``: Split on single spaces only +- ``','``: Split on commas +- ``'|'``: Split on pipe characters + +Advanced Argument Parsing +------------------------- + +For more complex argument parsing, you can use the ``arg_botcmd`` decorator which provides argparse-style argument handling: + +.. code-block:: python + + @arg_botcmd('name', type=str) + @arg_botcmd('--count', dest='repeat', type=int, default=1) + def repeat(self, msg, name=None, repeat=None): + return name * repeat + +This allows for: +- Type checking and conversion +- Optional arguments with defaults +- Named arguments +- Help text generation + +Best Practices +-------------- + +1. **Parameter Order**: Always keep parameters in the order ``(self, msg, args)`` for consistency. + +2. **Default Values**: Use default values for optional parameters, but be careful with the ``msg`` parameter as it's usually required. + +3. **Argument Splitting**: Use ``split_args_with=None`` when you need to handle multiple space-separated arguments. + +4. **Type Safety**: Use ``arg_botcmd`` when you need type checking or complex argument parsing. + +5. **Documentation**: Always document your command's parameters and expected usage in the function's docstring. + +Example with All Features +------------------------- + +Here's a complete example showing various parameter handling techniques: + +.. code-block:: python + + @arg_botcmd('name', type=str, help='The name to greet') + @arg_botcmd('--count', dest='repeat', type=int, default=1, help='Number of times to repeat') + @arg_botcmd('--shout', dest='shout', action='store_true', help='Convert to uppercase') + def greet(self, msg, name=None, repeat=None, shout=False): + """Greet someone with a customizable message. + + Example: + !greet Alice --count 3 --shout + """ + if not name: + return "Please provide a name to greet" + + message = f"Hello, {name}!" + if shout: + message = message.upper() + + return message * repeat + +This command demonstrates: +- Required and optional arguments +- Type conversion +- Default values +- Boolean flags +- Help text +- Proper documentation + +Common Pitfalls +--------------- + +1. **Default Values for msg**: While possible, it's generally not recommended to provide default values for the ``msg`` parameter as it's essential for command context. + +2. **Argument Splitting**: Remember that ``split_args_with=None`` splits on any whitespace, which might not be what you want if you need to preserve spaces in arguments. + +3. **Type Conversion**: When using ``arg_botcmd``, always specify the correct type for arguments to ensure proper conversion and validation. + +4. **Parameter Names**: Keep parameter names consistent with the decorator's expectations (``msg`` and ``args`` for basic commands, or the names specified in ``arg_botcmd``). + +5. **Documentation**: Always include examples in your docstrings to help users understand how to use your commands correctly. \ No newline at end of file diff --git a/docs/user_guide/plugin_development/index.rst b/docs/user_guide/plugin_development/index.rst index 086a4d9cc..bfc8059c8 100644 --- a/docs/user_guide/plugin_development/index.rst +++ b/docs/user_guide/plugin_development/index.rst @@ -14,12 +14,14 @@ with sets of recipes on a range of topics describing how to handle more advanced development_environment basics botcommands + command_parameters messaging threaded_replies presence mentions persistence configuration + provisioning streams dependencies dynaplugs diff --git a/docs/user_guide/provisioning.rst b/docs/user_guide/plugin_development/provisioning.rst similarity index 83% rename from docs/user_guide/provisioning.rst rename to docs/user_guide/plugin_development/provisioning.rst index 188b89406..cf029317c 100644 --- a/docs/user_guide/provisioning.rst +++ b/docs/user_guide/plugin_development/provisioning.rst @@ -33,13 +33,13 @@ It will give you on stdout a python dictionary of the core namespace like:: {'configs': {'Webserver': {'PORT': 8888}}} -To read the values from a plugin storage, for example here from alimac/err-factoid you can do:: +To read the values from a plugin storage, for example here from the ChatRoom plugin you can do:: - errbot --storage-get Factoid + errbot --storage-get ChatRoom It will give you on stdout a similar output:: - {'FACTOID': {'fire': 'burns', 'water': 'wet'}} + {'rooms': ['#general', '#support']} Writing values @@ -54,11 +54,8 @@ Checking back:: errbot --storage-get core {'configs': {'Webserver': {'PORT': 9999}}} -Changing facts in Factoid (note the merge is only on the first level so we change all FACTOID here):: +Changing plugin storage values (note the merge is only on the first level):: - echo "{'FACTOID': {'errbot': 'awesome'}}" | errbot --storage-merge Factoid - - >>> !errbot? - errbot is awesome + echo "{'rooms': ['#general', '#support', '#dev']}" | errbot --storage-merge ChatRoom You can use --storage-set in the same fashion but it will erase first the namespace before writing your values. diff --git a/docs/user_guide/plugin_development/testing_plugins_fullstack.rst b/docs/user_guide/plugin_development/testing_plugins_fullstack.rst index 3e74989ef..11304611e 100644 --- a/docs/user_guide/plugin_development/testing_plugins_fullstack.rst +++ b/docs/user_guide/plugin_development/testing_plugins_fullstack.rst @@ -4,7 +4,7 @@ Testing your plugins with unittest This guide explains how to test your Errbot plugins using the built-in testing framework. Errbot provides a powerful testing backend called ``FullStackTest`` that allows you to write unit tests for your plugins in a familiar unittest style. Basic Test Setup --------------- +---------------- To test your plugin, create a test file (e.g., `test_myplugin.py`) in your plugin's directory. Here's a basic example: @@ -29,7 +29,7 @@ To test your plugin, create a test file (e.g., `test_myplugin.py`) in your plugi self.assertIn('Hello!', self.pop_message()) Running Tests ------------- +------------- You can run your tests using Python's unittest framework: @@ -38,7 +38,7 @@ You can run your tests using Python's unittest framework: python -m unittest test_myplugin.py Test Methods ------------ +------------ FullStackTest provides several methods to help test your plugin's behavior: @@ -59,7 +59,7 @@ FullStackTest provides several methods to help test your plugin's behavior: - Test plugin dependencies Example Test Cases ----------------- +------------------ Here are some example test cases showing different testing scenarios: @@ -105,7 +105,7 @@ Here are some example test cases showing different testing scenarios: self.assertIn('Mock response', self.pop_message()) Best Practices -------------- +-------------- 1. **Test Isolation**: Each test should be independent and not rely on the state from other tests. @@ -118,7 +118,7 @@ Best Practices 5. **Documentation**: Document your test cases to explain what they're testing and why. Complete Example --------------- +---------------- Here's a complete example of a test suite for a plugin: diff --git a/docs/user_guide/plugin_development/threaded_replies.rst b/docs/user_guide/plugin_development/threaded_replies.rst index 0794c10aa..e9c06edc6 100644 --- a/docs/user_guide/plugin_development/threaded_replies.rst +++ b/docs/user_guide/plugin_development/threaded_replies.rst @@ -1,10 +1,10 @@ Threaded Replies -=============== +================ Errbot supports threaded replies, which allows bot responses to be organized in conversation threads when the backend supports this feature. This is particularly useful for maintaining context in group chats and keeping related messages together. Enabling Threaded Replies ------------------------- +------------------------- There are two ways to enable threaded replies in Errbot: @@ -12,7 +12,7 @@ There are two ways to enable threaded replies in Errbot: 2. Globally for specific commands using the `DIVERT_TO_THREAD` configuration Per-command Threaded Replies ---------------------------- +---------------------------- You can send a threaded reply to any message using the `in_reply_to` parameter in `send`: @@ -27,7 +27,7 @@ You can send a threaded reply to any message using the `in_reply_to` parameter i self.send(msg.frm, "This is a threaded response", in_reply_to=msg) Global Thread Configuration -------------------------- +--------------------------- You can configure Errbot to automatically send responses in threads for specific commands by adding them to the `DIVERT_TO_THREAD` configuration in your config.py: @@ -40,7 +40,7 @@ You can configure Errbot to automatically send responses in threads for specific DIVERT_TO_THREAD = ("ALL_COMMANDS",) Backend Support --------------- +--------------- Threaded replies are supported by the following backends: @@ -52,7 +52,7 @@ Threaded replies are supported by the following backends: Note that not all backends support threaded replies. If a backend doesn't support threading, the message will be sent as a regular message. Best Practices -------------- +-------------- 1. Use threaded replies for: - Long conversations that need to maintain context @@ -66,7 +66,7 @@ Best Practices - Debug information Example Plugin -------------- +-------------- Here's a complete example of a plugin that demonstrates threaded replies: @@ -96,7 +96,7 @@ Here's a complete example of a plugin that demonstrates threaded replies: self.send(msg.frm, help_text, in_reply_to=msg) Configuration ------------- +------------- To enable threaded replies globally for specific commands, add them to your config.py: @@ -114,7 +114,7 @@ To enable threaded replies globally for specific commands, add them to your conf DIVERT_TO_THREAD = ("ALL_COMMANDS",) Limitations ----------- +----------- 1. Not all backends support threaded replies 2. Threaded replies may not be visible in all chat clients diff --git a/docs/user_guide/setup.rst b/docs/user_guide/setup.rst index b806f5f42..a336ca9d1 100644 --- a/docs/user_guide/setup.rst +++ b/docs/user_guide/setup.rst @@ -197,7 +197,7 @@ on `PyPI `_. Provisioning (advanced) ----------------------- -See the :doc:`provisioning documentation ` +See the :doc:`provisioning documentation ` .. _virtualenv: https://virtualenv.pypa.io/en/latest/ .. _pip: https://pip.pypa.io/en/stable/ diff --git a/setup.py b/setup.py index ba8568af5..40b627e30 100755 --- a/setup.py +++ b/setup.py @@ -36,7 +36,7 @@ "colorlog==6.7.0", "markdown==3.4.4", "ansi==0.3.6", - "Pygments==2.16.1", + "Pygments>=2.17", "pygments-markdown-lexer==0.1.0.dev39", # sytax coloring to debug md "dulwich==0.21.5", # python implementation of git "deepmerge==1.1.0",