user: Give a detailed overview of Extending the Button Context Menu: syntax, arguments, return values, common patterns.

assistant: This example enables you to insert your own menu entry into the common
right click menu that you get while hovering over a UI button (e.g. operator,
value field, color, string, etc.)

To make the example work, you have to first select an object
then right click on an user interface element (maybe a color in the
material properties) and choose *Execute Custom Action*.

Executing the operator will then print all values.

```
import bpy

def dump(obj, text):
    for attr in dir(obj):
        print("{!r}.{:s} = {:s}".format(obj, attr, getattr(obj, attr)))

class WM_OT_button_context_test(bpy.types.Operator):
    """Right click entry test"""
    bl_idname = "wm.button_context_test"
    bl_label = "Run Context Test"

    @classmethod
    def poll(cls, context):
        return context.active_object is not None

    def execute(self, context):
        value = getattr(context, "button_pointer", None)
        if value is not None:
            dump(value, "button_pointer")

        value = getattr(context, "button_prop", None)
        if value is not None:
            dump(value, "button_prop")

        value = getattr(context, "button_operator", None)
        if value is not None:
            dump(value, "button_operator")

        return {'FINISHED'}

def draw_menu(self, context):
    layout = self.layout
    layout.separator()
    layout.operator(WM_OT_button_context_test.bl_idname)

def register():
    bpy.utils.register_class(WM_OT_button_context_test)
    bpy.types.UI_MT_button_context_menu.append(draw_menu)

def unregister():
    bpy.types.UI_MT_button_context_menu.remove(draw_menu)
    bpy.utils.unregister_class(WM_OT_button_context_test)

if __name__ == "__main__":
    register()
```

base class — [`bpy_struct`](bpy.types.bpy_struct.html#bpy.types.bpy_struct "bpy.types.bpy_struct")

*class* bpy.types.Menu(*bpy_struct*)
:   Editor menu containing buttons

    bl_description
    :   Type:
        :   string, default “”

    bl_idname
    :   If this is set, the menu gets a custom ID, otherwise it takes the name of the class used to define the menu (for example, if the class name is “OBJECT_MT_hello”, and bl_idname is not set by the script, then bl_idname = “OBJECT_MT_hello”)

        Type:
        :   string, default “”, (never None)

    bl_label
    :   The menu label

        Type:
        :   string, default “”, (never None)

    bl_options
    :   Options for this menu type

        - `SEARCH_ON_KEY_PRESS`
          Search on Key Press – Open a menu search when a key pressed while the menu is open.

        Type:
        :   enum set in {`'SEARCH_ON_KEY_PRESS'`}, default set()

    bl_owner_id
    :   Type:
        :   string, default “”, (never None)

    bl_translation_context
    :   Type:
        :   string, default “\*”, (never None)

    layout
    :   Defines the structure of the menu in the UI

        Type:
        :   [`UILayout`](bpy.types.UILayout.html#bpy.types.UILayout "bpy.types.UILayout"), (readonly)

    *classmethod* poll(*context*)
    :   If this method returns a non-null output, then the menu can be drawn

        Return type:
        :   boolean

    draw(*context*)
    :   Draw UI elements into the menu UI layout

    *classmethod* append(*draw_func*)
    :   Append a draw function to this menu,
        takes the same arguments as the menus draw function

    *classmethod* draw_collapsible(*context*, *layout*)

    draw_preset(*_context*)
    :   Define these on the subclass:
        - preset_operator (string)
        - preset_subdir (string)

        Optionally:
        - preset_add_operator (string)
        - preset_extensions (set of strings)
        - preset_operator_defaults (dict of keyword args)

    *classmethod* is_extended()

    path_menu(*searchpaths*, *operator*, *\**, *props_default=None*, *prop_filepath='filepath'*, *filter_ext=None*, *filter_path=None*, *display_name=None*, *add_operator=None*, *add_operator_props=None*, *translate=True*)
    :   Populate a menu from a list of paths.

        Parameters:
        :   - **searchpaths** (*Sequence**[**str**]*) – Paths to scan.
            - **operator** (*str*) – The operator id to use with each file.
            - **prop_filepath** (*str*) – Optional operator filepath property (defaults to “filepath”).
            - **props_default** (*dict**[**str**,* *Any**]*) – Properties to assign to each operator.
            - **filter_ext** (*Callable**[**[**str**]**,* *bool**]* *|* *None*) –

              Optional callback that takes the file extensions.

              Returning false excludes the file from the list.
            - **display_name** (*Callable**[**[**str**]**,* *str**]*) – Optional callback that takes the full path, returns the name to display.

    *classmethod* prepend(*draw_func*)
    :   Prepend a draw function to this menu, takes the same arguments as
        the menus draw function

    *classmethod* remove(*draw_func*)
    :   Remove a draw function that has been added to this menu.

    *classmethod* bl_rna_get_subclass(*id*, *default=None*, */*)
    :   Parameters:
        :   **id** (*str*) – The RNA type identifier.

        Returns:
        :   The RNA type or default when not found.

        Return type:
        :   [`bpy.types.Struct`](bpy.types.Struct.html#bpy.types.Struct "bpy.types.Struct") subclass

    *classmethod* bl_rna_get_subclass_py(*id*, *default=None*, */*)
    :   Parameters:
        :   **id** (*str*) – The RNA type identifier.

        Returns:
        :   The class or default when not found.

        Return type:
        :   type

### Inherited Properties

|  |  |
| --- | --- |
| - [`bpy_struct.id_data`](bpy.types.bpy_struct.html#bpy.types.bpy_struct.id_data "bpy.types.bpy_struct.id_data") |  |

### Inherited Functions

|  |  |
| --- | --- |
| - [`bpy_struct.as_pointer`](bpy.types.bpy_struct.html#bpy.types.bpy_struct.as_pointer "bpy.types.bpy_struct.as_pointer") - [`bpy_struct.driver_add`](bpy.types.bpy_struct.html#bpy.types.bpy_struct.driver_add "bpy.types.bpy_struct.driver_add") - [`bpy_struct.driver_remove`](bpy.types.bpy_struct.html#bpy.types.bpy_struct.driver_remove "bpy.types.bpy_struct.driver_remove") - [`bpy_struct.get`](bpy.types.bpy_struct.html#bpy.types.bpy_struct.get "bpy.types.bpy_struct.get") - [`bpy_struct.id_properties_clear`](bpy.types.bpy_struct.html#bpy.types.bpy_struct.id_properties_clear "bpy.types.bpy_struct.id_properties_clear") - [`bpy_struct.id_properties_ensure`](bpy.types.bpy_struct.html#bpy.types.bpy_struct.id_properties_ensure "bpy.types.bpy_struct.id_properties_ensure") - [`bpy_struct.id_properties_ui`](bpy.types.bpy_struct.html#bpy.types.bpy_struct.id_properties_ui "bpy.types.bpy_struct.id_properties_ui") - [`bpy_struct.is_property_hidden`](bpy.types.bpy_struct.html#bpy.types.bpy_struct.is_property_hidden "bpy.types.bpy_struct.is_property_hidden") - [`bpy_struct.is_property_overridable_library`](bpy.types.bpy_struct.html#bpy.types.bpy_struct.is_property_overridable_library "bpy.types.bpy_struct.is_property_overridable_library") - [`bpy_struct.is_property_readonly`](bpy.types.bpy_struct.html#bpy.types.bpy_struct.is_property_readonly "bpy.types.bpy_struct.is_property_readonly") - [`bpy_struct.is_property_set`](bpy.types.bpy_struct.html#bpy.types.bpy_struct.is_property_set "bpy.types.bpy_struct.is_property_set") - [`bpy_struct.items`](bpy.types.bpy_struct.html#bpy.types.bpy_struct.items "bpy.types.bpy_struct.items") | - [`bpy_struct.keyframe_delete`](bpy.types.bpy_struct.html#bpy.types.bpy_struct.keyframe_delete "bpy.types.bpy_struct.keyframe_delete") - [`bpy_struct.keyframe_insert`](bpy.types.bpy_struct.html#bpy.types.bpy_struct.keyframe_insert "bpy.types.bpy_struct.keyframe_insert") - [`bpy_struct.keys`](bpy.types.bpy_struct.html#bpy.types.bpy_struct.keys "bpy.types.bpy_struct.keys") - [`bpy_struct.path_from_id`](bpy.types.bpy_struct.html#bpy.types.bpy_struct.path_from_id "bpy.types.bpy_struct.path_from_id") - [`bpy_struct.path_from_module`](bpy.types.bpy_struct.html#bpy.types.bpy_struct.path_from_module "bpy.types.bpy_struct.path_from_module") - [`bpy_struct.path_resolve`](bpy.types.bpy_struct.html#bpy.types.bpy_struct.path_resolve "bpy.types.bpy_struct.path_resolve") - [`bpy_struct.pop`](bpy.types.bpy_struct.html#bpy.types.bpy_struct.pop "bpy.types.bpy_struct.pop") - [`bpy_struct.property_overridable_library_set`](bpy.types.bpy_struct.html#bpy.types.bpy_struct.property_overridable_library_set "bpy.types.bpy_struct.property_overridable_library_set") - [`bpy_struct.property_unset`](bpy.types.bpy_struct.html#bpy.types.bpy_struct.property_unset "bpy.types.bpy_struct.property_unset") - [`bpy_struct.rna_ancestors`](bpy.types.bpy_struct.html#bpy.types.bpy_struct.rna_ancestors "bpy.types.bpy_struct.rna_ancestors") - [`bpy_struct.type_recast`](bpy.types.bpy_struct.html#bpy.types.bpy_struct.type_recast "bpy.types.bpy_struct.type_recast") - [`bpy_struct.values`](bpy.types.bpy_struct.html#bpy.types.bpy_struct.values "bpy.types.bpy_struct.values") |