# Extending the rules

:::{important}
**This is public, but volatile, functionality.**

Extending and customizing the rules is supported functionality, but with weaker
backwards compatibility guarantees, and is not fully subject to the normal
backwards compatibility procedures and policies. It's simply not feasible to
support every possible customization with strong backwards compatibility
guarantees.
:::

Because of the rich ecosystem of tools and variety of use cases, APIs are
provided to make it easy to create custom rules using the existing rules as a
basis. This allows implementing behaviors that aren't possible using
wrapper macros around the core rules, and can make certain types of changes
much easier and transparent to implement.

:::{note}
It is not required to extend a core rule. The minimum requirement for a custom
rule is to return the appropriate provider (e.g. {bzl:obj}`PyInfo` etc).
Extending the core rules is most useful when you want all or most of the
behavior of a core rule.
:::

Follow or comment on https://github.com/bazel-contrib/rules_python/issues/1647
for the development of APIs to support custom derived rules.

## Creating custom rules

Custom rules can be created using the core rules as a basis by using their rule
builder APIs.

* [`//python/apis:executables.bzl`](#python-apis-executables-bzl): builders for
  executables.
* [`//python/apis:libraries.bzl`](#python-apis-libraries-bzl): builders for
  libraries.

These builders create {bzl:obj}`ruleb.Rule` objects, which are thin
wrappers around the keyword arguments eventually passed to the `rule()`
function. These builder APIs give access to the _entire_ rule definition and
allow arbitrary modifications.

This is level of control is powerful, but also volatile. A rule definition
contains many details that _must_ change as the implementation changes. What
is more or less likely to change isn't known in advance, but some general
rules are:

* Additive behavior to public attributes will be less prone to breaking.
* Internal attributes that directly support a public attribute are likely
  reliable.
* Internal attributes that support an action are more likely to change.
* Rule toolchains are moderately stable (toolchains are mostly internal to
  how a rule works, but custom toolchains are supported).

## Example: validating a source file

In this example, we derive from `py_library` a custom rule that verifies source
code contains the word "snakes". It does this by:

* Adding an implicit dependency on a checker program
* Calling the base implementation function
* Running the checker on the srcs files
* Adding the result to the `_validation` output group (a special output
  group for validation behaviors).

To users, they can use `has_snakes_library` the same as `py_library`. The same
is true for other targets that might consume the rule.

```
load("@rules_python//python/api:libraries.bzl", "libraries")
load("@rules_python//python/api:attr_builders.bzl", "attrb")

def _has_snakes_impl(ctx, base):
    providers = base(ctx)

    out = ctx.actions.declare_file(ctx.label.name + "_snakes.check")
    ctx.actions.run(
        inputs = ctx.files.srcs,
        outputs = [out],
        executable = ctx.attr._checker[DefaultInfo].files_to_run,
        args = [out.path] + [f.path for f in ctx.files.srcs],
    )
    prior_ogi = None
    for i, p in enumerate(providers):
        if type(p) == "OutputGroupInfo":
            prior_ogi = (i, p)
            break
    if prior_ogi:
        groups = {k: getattr(prior_ogi[1], k) for k in dir(prior_ogi)}
        if "_validation" in groups:
            groups["_validation"] = depset([out], transitive=groups["_validation"])
        else:
            groups["_validation"] = depset([out])
        providers[prior_ogi[0]] = OutputGroupInfo(**groups)
    else:
        providers.append(OutputGroupInfo(_validation=depset([out])))
    return providers

def create_has_snakes_rule():
    r = libraries.py_library_builder()
    base_impl = r.implementation()
    r.set_implementation(lambda ctx: _has_snakes_impl(ctx, base_impl))
    r.attrs["_checker"] = attrb.Label(
        default="//:checker",
        executable = True,
    )
    return r.build()
has_snakes_library = create_has_snakes_rule()
```

## Example: adding transitions

In this example, we derive from `py_binary` to force building for a particular
platform. We do this by:

* Adding an additional output to the rule's cfg
* Calling the base transition function
* Returning the new transition outputs

```starlark

load("@rules_python//python/api:executables.bzl", "executables")

def _force_linux_impl(settings, attr, base_impl):
    settings = base_impl(settings, attr)
    settings["//command_line_option:platforms"] = ["//my/platforms:linux"]
    return settings

def create_rule():
    r = executables.py_binary_rule_builder()
    base_impl = r.cfg.implementation()
    r.cfg.set_implementation(
        lambda settings, attr: _force_linux_impl(settings, attr, base_impl)
    )
    r.cfg.add_output("//command_line_option:platforms")
    return r.build()

py_linux_binary = create_linux_binary_rule()
```

Users can then use `py_linux_binary` the same as a regular py_binary. It will
act as if `--platforms=//my/platforms:linux` was specified when building it.
