sdlib


Namesdlib JSON
Version 0.0.1 PyPI version JSON
download
home_page
SummaryStable Diffusion Library
upload_time2023-11-20 01:43:42
maintainer
docs_urlNone
authorljleb
requires_python>=3.8
license
keywords
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # sdlib: Stable Diffusion Library

*Example plugin that appends `", gloomy atmosphere"` to any positive prompt.*

```python
import sdlib
plugin = sdlib.register_plugin("my-plugin")

@plugin.wrapper
def encode_prompt_schedule(params: sdlib.EncodePromptScheduleParams, original_function):
    if params.is_positive:
        if params.prompt.strip():
            params.prompt += ", "
        params.prompt += "gloomy atmosphere"
    return original_function(params)
```

sdlib is a library that exposes many different components of the [Stable Diffusion Webui](https://github.com/AUTOMATIC1111/stable-diffusion-webui) through a stable programming interface.
It takes care of much of the boilerplate so that extension developers can focus on writing useful code.

## Motivation

Developing extensions for the webui is currently very error-prone.
Monkey patching is commonplace, extensions break all the time shortly after a release.
There are many extension repositories that are stale because they are updated less often than the webui.

sdlib intends to help stabilize the interface extension developers program against so that things stop breaking all the time.

## Documentation

This guide provides basic documentation for plugins intercommunication.

### TL;DR:

1. Create a plugin using `plugin = sdlib.create_plugin("plugin_name", "0.0.1")`
2. Define a function and register it to a plugin using the `@plugin.function` decorator.
3. Use the `@plugin.wrapper` decorator to register a function wrapper. You can use the optional `after=` parameter to specify execution order.

### Create a plugin

Any change in the plugin system (registering a new function, wrapping a function, etc.) must be done through a plugin.

Here's how to declare a plugin:

```python
import sdlib
plugin = sdlib.register_plugin("my_awesome_plugin", api_version="0.0.1")
```

A plugin identifier is a series of underscores or lowercase letters (`[a-z_]+`).
The identifier of a plugin must be unique; two plugins cannot have the same identifier at the same time.

The version of a plugin is used to make sure the programming interface the code is written against stays consistent over time.

### Defining a Function

A function in sdlib is a regular Python function that can be registered to a plugin.
It performs a specific task and can be extended using wrappers.

#### Example:

```python
@plugin.function
def eat(food):
    return f"I eat {food}!"
```

### Using the `wrapper` Decorator

The `wrapper` decorator is used to extend or modify the behavior of a registered function.
The wrapper function must have the same name as the target function, unless the `name` parameter is used.

#### Without Parameters:

```python
@plugin.wrapper
def eat(food, original_function):
    return original_function(food).upper()
```

In this example, `eat` is a wrapper that converts the eating message to uppercase, extending the original `eat` function defined earlier.

#### With Parameters:

```python
@plugin.wrapper(name="eat", after="another_plugin")
def custom_eating(food, original_function):
    return f"{original_function(food)} You should as well!"
```

In this example, `custom_eating` adds an additional message to the original one.
The parameters of the annotation tells the plugin system to:

- wrap the `eat` function defined earlier instead of targeting an unknown entity named `"custom_eating"`
- only wrap after any wraps provided by `another_plugin`

### Applying Wrappers

Wrappers are applied in the order they are defined, unless specified otherwise using the `after` parameter.

### Using Generator Functions as Wrappers

Generator functions can also be used for wrappers.
In a generator wrapper, each `yield` statement calls the original function and receives its result.

Here’s how you can convert a regular function wrapper to a generator wrapper:

#### Regular Function Wrapper:

```python
@plugin.wrapper
def eat(food, original_function):
    return original_function(food).upper()
```

#### Generator Function Wrapper:

```python
@plugin.wrapper
def eat(food):
    result = yield food
    return result.upper()
```

In this generator wrapper example, the `eat` function yields the `food` to the original function and then receives the original function’s result.
The wrapper then proceeds to modify the result by converting it to uppercase before returning it.

You can also use multiple `yield` statements in a generator wrapper, which allows for more intricate interactions with the original function.
Each `yield` results in a call to the original function, and the generator receives the result of that call.

#### Example with Multiple Yields:
```python
@plugin.wrapper
def eat(food):
    result1 = yield food
    result2 = yield f"{result1} and it's delicious"
    return result2
```

In this example, the `eat` function calls the original function twice, first with the original `food` argument, and then with an additional question.
The final result is derived from the second call to the original function.

### Best Practices

- Make sure the parameter types of your wrappers match the original function definition.
- Use descriptive names for your functions and wrappers.
- When applicable, ensure that your wrapper does not accidentally override or disrupt the behavior of the original function.

## Contributing

Contributions are welcome.

            

Raw data

            {
    "_id": null,
    "home_page": "",
    "name": "sdlib",
    "maintainer": "",
    "docs_url": null,
    "requires_python": ">=3.8",
    "maintainer_email": "",
    "keywords": "",
    "author": "ljleb",
    "author_email": "",
    "download_url": "https://files.pythonhosted.org/packages/15/e5/881569ba007314967f1a06945b61fac024876956809f495c374b4576eb62/sdlib-0.0.1.tar.gz",
    "platform": null,
    "description": "# sdlib: Stable Diffusion Library\r\n\r\n*Example plugin that appends `\", gloomy atmosphere\"` to any positive prompt.*\r\n\r\n```python\r\nimport sdlib\r\nplugin = sdlib.register_plugin(\"my-plugin\")\r\n\r\n@plugin.wrapper\r\ndef encode_prompt_schedule(params: sdlib.EncodePromptScheduleParams, original_function):\r\n    if params.is_positive:\r\n        if params.prompt.strip():\r\n            params.prompt += \", \"\r\n        params.prompt += \"gloomy atmosphere\"\r\n    return original_function(params)\r\n```\r\n\r\nsdlib is a library that exposes many different components of the [Stable Diffusion Webui](https://github.com/AUTOMATIC1111/stable-diffusion-webui) through a stable programming interface.\r\nIt takes care of much of the boilerplate so that extension developers can focus on writing useful code.\r\n\r\n## Motivation\r\n\r\nDeveloping extensions for the webui is currently very error-prone.\r\nMonkey patching is commonplace, extensions break all the time shortly after a release.\r\nThere are many extension repositories that are stale because they are updated less often than the webui.\r\n\r\nsdlib intends to help stabilize the interface extension developers program against so that things stop breaking all the time.\r\n\r\n## Documentation\r\n\r\nThis guide provides basic documentation for plugins intercommunication.\r\n\r\n### TL;DR:\r\n\r\n1. Create a plugin using `plugin = sdlib.create_plugin(\"plugin_name\", \"0.0.1\")`\r\n2. Define a function and register it to a plugin using the `@plugin.function` decorator.\r\n3. Use the `@plugin.wrapper` decorator to register a function wrapper. You can use the optional `after=` parameter to specify execution order.\r\n\r\n### Create a plugin\r\n\r\nAny change in the plugin system (registering a new function, wrapping a function, etc.) must be done through a plugin.\r\n\r\nHere's how to declare a plugin:\r\n\r\n```python\r\nimport sdlib\r\nplugin = sdlib.register_plugin(\"my_awesome_plugin\", api_version=\"0.0.1\")\r\n```\r\n\r\nA plugin identifier is a series of underscores or lowercase letters (`[a-z_]+`).\r\nThe identifier of a plugin must be unique; two plugins cannot have the same identifier at the same time.\r\n\r\nThe version of a plugin is used to make sure the programming interface the code is written against stays consistent over time.\r\n\r\n### Defining a Function\r\n\r\nA function in sdlib is a regular Python function that can be registered to a plugin.\r\nIt performs a specific task and can be extended using wrappers.\r\n\r\n#### Example:\r\n\r\n```python\r\n@plugin.function\r\ndef eat(food):\r\n    return f\"I eat {food}!\"\r\n```\r\n\r\n### Using the `wrapper` Decorator\r\n\r\nThe `wrapper` decorator is used to extend or modify the behavior of a registered function.\r\nThe wrapper function must have the same name as the target function, unless the `name` parameter is used.\r\n\r\n#### Without Parameters:\r\n\r\n```python\r\n@plugin.wrapper\r\ndef eat(food, original_function):\r\n    return original_function(food).upper()\r\n```\r\n\r\nIn this example, `eat` is a wrapper that converts the eating message to uppercase, extending the original `eat` function defined earlier.\r\n\r\n#### With Parameters:\r\n\r\n```python\r\n@plugin.wrapper(name=\"eat\", after=\"another_plugin\")\r\ndef custom_eating(food, original_function):\r\n    return f\"{original_function(food)} You should as well!\"\r\n```\r\n\r\nIn this example, `custom_eating` adds an additional message to the original one.\r\nThe parameters of the annotation tells the plugin system to:\r\n\r\n- wrap the `eat` function defined earlier instead of targeting an unknown entity named `\"custom_eating\"`\r\n- only wrap after any wraps provided by `another_plugin`\r\n\r\n### Applying Wrappers\r\n\r\nWrappers are applied in the order they are defined, unless specified otherwise using the `after` parameter.\r\n\r\n### Using Generator Functions as Wrappers\r\n\r\nGenerator functions can also be used for wrappers.\r\nIn a generator wrapper, each `yield` statement calls the original function and receives its result.\r\n\r\nHere\u2019s how you can convert a regular function wrapper to a generator wrapper:\r\n\r\n#### Regular Function Wrapper:\r\n\r\n```python\r\n@plugin.wrapper\r\ndef eat(food, original_function):\r\n    return original_function(food).upper()\r\n```\r\n\r\n#### Generator Function Wrapper:\r\n\r\n```python\r\n@plugin.wrapper\r\ndef eat(food):\r\n    result = yield food\r\n    return result.upper()\r\n```\r\n\r\nIn this generator wrapper example, the `eat` function yields the `food` to the original function and then receives the original function\u2019s result.\r\nThe wrapper then proceeds to modify the result by converting it to uppercase before returning it.\r\n\r\nYou can also use multiple `yield` statements in a generator wrapper, which allows for more intricate interactions with the original function.\r\nEach `yield` results in a call to the original function, and the generator receives the result of that call.\r\n\r\n#### Example with Multiple Yields:\r\n```python\r\n@plugin.wrapper\r\ndef eat(food):\r\n    result1 = yield food\r\n    result2 = yield f\"{result1} and it's delicious\"\r\n    return result2\r\n```\r\n\r\nIn this example, the `eat` function calls the original function twice, first with the original `food` argument, and then with an additional question.\r\nThe final result is derived from the second call to the original function.\r\n\r\n### Best Practices\r\n\r\n- Make sure the parameter types of your wrappers match the original function definition.\r\n- Use descriptive names for your functions and wrappers.\r\n- When applicable, ensure that your wrapper does not accidentally override or disrupt the behavior of the original function.\r\n\r\n## Contributing\r\n\r\nContributions are welcome.\r\n",
    "bugtrack_url": null,
    "license": "",
    "summary": "Stable Diffusion Library",
    "version": "0.0.1",
    "project_urls": null,
    "split_keywords": [],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "ebf80659c22018d73e70fecdb1eae0aca11361bec1170a520eb1673f496745ba",
                "md5": "7ca2e60260a33efeb941745623c52256",
                "sha256": "a3df7760b03f11e63f3f7bd23fa45acc1a00b21b81ff39965f29edf86128b314"
            },
            "downloads": -1,
            "filename": "sdlib-0.0.1-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "7ca2e60260a33efeb941745623c52256",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.8",
            "size": 11368,
            "upload_time": "2023-11-20T01:43:40",
            "upload_time_iso_8601": "2023-11-20T01:43:40.902671Z",
            "url": "https://files.pythonhosted.org/packages/eb/f8/0659c22018d73e70fecdb1eae0aca11361bec1170a520eb1673f496745ba/sdlib-0.0.1-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "15e5881569ba007314967f1a06945b61fac024876956809f495c374b4576eb62",
                "md5": "ec50627ea70dd40367762120bbb1d14c",
                "sha256": "9aab0d31716e9975cc8b9446780e2cc34c86c557d4175962da4c5514cb321be4"
            },
            "downloads": -1,
            "filename": "sdlib-0.0.1.tar.gz",
            "has_sig": false,
            "md5_digest": "ec50627ea70dd40367762120bbb1d14c",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.8",
            "size": 11160,
            "upload_time": "2023-11-20T01:43:42",
            "upload_time_iso_8601": "2023-11-20T01:43:42.295175Z",
            "url": "https://files.pythonhosted.org/packages/15/e5/881569ba007314967f1a06945b61fac024876956809f495c374b4576eb62/sdlib-0.0.1.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-11-20 01:43:42",
    "github": false,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "lcname": "sdlib"
}
        
Elapsed time: 0.15286s