Metadata-Version: 2.3
Name: mflux-web
Version: 0.0.1a2
Summary: Extensible web UI namespace for mflux
Author: Anthony Wu
Author-email: Anthony Wu <462072+anthonywu@users.noreply.github.com>
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Programming Language :: Python :: 3.15
Requires-Python: >=3.11
Description-Content-Type: text/markdown

# mflux-web

Install from PyPI:

```sh
pip install mflux-web
```

Import the web namespace:

```python
import mflux.web
```

`mflux.web` owns the implementation. Importing it produces no output.
Third-party plugins live under `mflux.web.<plugin>`. The inference distribution
`mflux` is optional: without it, Python creates an implicit `mflux` namespace;
with it installed, the packages share that parent namespace.

## Demo web UI

Install from PyPI and launch the demo, powered by Python's standard-library
HTTP server:

```sh
pip install mflux-web
mflux-web
# Or, from this checkout:
just demo
```

Open <http://127.0.0.1:8000> to see:

> Hello from mflux - this is a stub package that provides a parent namespace for web uis

Use `mflux-web --port 8080`
to choose another port; the default host is `127.0.0.1`. Stop with Ctrl+C.
Importing the library does not launch a server. Plugins remain independent;
this demo does not automatically mount plugin routes.

The demo requires no extras or third-party runtime dependencies.

## Namespace ownership

This distribution owns `mflux/web/__init__.py` and the demo module `mflux/web/demo.py`. It deliberately
does **not** ship `mflux/__init__.py` or require the inference distribution.
`mflux.web` uses `pkgutil.extend_path` to discover plugin directories contributed
by other distributions, including separate editable checkouts. The child name
`demo` is reserved for the included demo server.

## Create a separately installable plugin

Each plugin is its own PyPI distribution. Installing its wheel into the same
virtual environment makes its Python package available under `mflux.web`.
No registration file or entry point is required for imports. Installation alone
does not run the plugin or register routes; applications explicitly import and
call it.

For example, use `mflux-web-image-tools` as the PyPI distribution name and
`image_tools` as the unique Python child package:

```sh
mkdir -p mflux-web-image-tools/src/mflux/web/image_tools
cd mflux-web-image-tools
```

Distribution names may contain hyphens; Python import names must be valid
identifiers, so use underscores. Choose a child name that no other plugin owns.
PyPI name availability does not reserve a Python namespace name.

Create `pyproject.toml`:

```toml
[project]
name = "mflux-web-image-tools"
version = "0.1.0"
description = "Image tools plugin for mflux.web"
requires-python = ">=3.11"
dependencies = ["mflux-web>=0.0.1a2"]

[build-system]
requires = ["uv_build>=0.12.15,<0.13.0"]
build-backend = "uv_build"

[tool.uv.build-backend]
module-name = "mflux.web.image_tools"
```

The explicit alpha minimum allows this example to depend on the current
prerelease of `mflux-web`. Update the minimum when your plugin requires a newer
API. If your plugin calls inference APIs from `mflux`, also declare `mflux` as a
dependency with the minimum version you have tested. Depending on `mflux-web`
alone does not install the inference library.

Create `src/mflux/web/image_tools/__init__.py`:

```python
def hello() -> str:
    return "Hello from the image_tools plugin"
```

The finished source tree is:

```text
mflux-web-image-tools/
├── pyproject.toml
└── src/
    └── mflux/
        └── web/
            └── image_tools/
                └── __init__.py
```

**Do not add `src/mflux/__init__.py` or `src/mflux/web/__init__.py`.** The parent
distributions own those files. Your distribution
owns only `mflux/web/image_tools/`; another plugin can independently own
`mflux/web/another_plugin/`.

### Build and install into a virtual environment

From the plugin project directory:

```sh
uv build
uv venv --python 3.14 .venv
# mflux-web is installed automatically from PyPI as a plugin dependency.
uv pip install --python .venv/bin/python mflux dist/mflux_web_image_tools-0.1.0-py3-none-any.whl
```

All three distributions now coexist in one environment. Verify from the plugin
project directory, using that environment without syncing the plugin project:

```sh
uv run --no-project --python .venv/bin/python python - <<'PYTHON'
import mflux
import mflux.web
from mflux.web import image_tools

print(image_tools.hello())
PYTHON
```

Expected output in a fresh process:

```text
Hello from the image_tools plugin
```

After publishing your plugin to PyPI, users can install it by distribution name
into their activated environment:

```sh
pip install mflux mflux-web-image-tools
```

Its dependency installs `mflux-web` automatically. Import the plugin using
`mflux.web.image_tools`.

### Editable plugin development

With `mflux` and `mflux-web` already installed in the target environment, replace
the plugin wheel with an editable installation:

```sh
uv pip install --python .venv/bin/python --editable .
```

Separate source trees require the parent `mflux` initializer to extend its
package path as described below. This applies even if only the plugin is
editable. Restart Python after installing a plugin so package discovery runs
again. Installing every package as a wheel into the same site-packages directory
does not require this split-path setup.

## Integration with the mflux parent

The existing mflux project has a regular `mflux/__init__.py`. Normal wheel
installations into the same site-packages directory coexist with this package.
For separate editable installs or other split-path layouts, add this to the
**mflux project's** existing `src/mflux/__init__.py`, retaining its current setup:

```python
from pkgutil import extend_path

__path__ = extend_path(__path__, __name__)
```

Without that parent change, an installed regular mflux package can hide an
editable mflux-web checkout. Setting `namespace = true` in build configuration
does not change Python's runtime import behavior. This repository does not
modify or replace the parent initializer.

## Development

Use uv-managed Python 3.14 for development; the library supports Python 3.11–3.15.

```sh
uv sync
uv build
just test
just lint
```

The tests build the distributions in a temporary directory and check their
contents and imports in isolated subprocesses, including third-party namespace
contributions and regular-parent coexistence.
