Metadata-Version: 2.4
Name: muscles-wsgi
Version: 1.0.1
Summary: Muscles WSGI runtime adapter for Web/API applications
License: MIT
Author: Denis B.
Author-email: denis@butko.info
Requires-Python: >=3.10,<4.0
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Provides-Extra: mime
Provides-Extra: server
Requires-Dist: dnspython (==2.6.1)
Requires-Dist: jinja2 (==3.1.2)
Requires-Dist: jsonschema (==4.16.0)
Requires-Dist: muscles (>=1.0.0rc1,<2.0.0)
Requires-Dist: python-magic (==0.4.27) ; extra == "mime"
Requires-Dist: requests (>=2.31.0,<3.0.0)
Requires-Dist: requests-toolbelt (>=1.0.0,<2.0.0)
Requires-Dist: uwsgi (==2.0.20) ; extra == "server"
Requires-Dist: watchdog (>=4.0.0,<5.0.0)
Project-URL: Documentation, https://github.com/butkoden/muscles-wsgi#readme
Project-URL: Homepage, https://github.com/butkoden/muscles-wsgi
Project-URL: PyPI, https://pypi.org/project/muscles-wsgi/
Project-URL: Repository, https://github.com/butkoden/muscles-wsgi
Project-URL: Releases, https://github.com/butkoden/muscles-wsgi/releases
Project-URL: muscles, https://pypi.org/project/muscles/
Project-URL: muscles-asgi, https://pypi.org/project/muscles-asgi/
Project-URL: muscles-cli, https://pypi.org/project/muscles-cli/
Project-URL: muscles-mcp, https://pypi.org/project/muscles-mcp/
Project-URL: muscles-benchmarks, https://pypi.org/project/muscles-benchmarks/
Description-Content-Type: text/markdown

# Muscles WSGI

`muscles-wsgi` is the WSGI runtime for Muscles. It provides page routing,
request/response handling, templates, static files, REST controllers and Swagger
UI on top of the shared `muscles` core.

## Installation

```bash
pip install muscles-wsgi
```

Canonical ecosystem install matrix is documented in core:
[Muscles installation matrix](https://github.com/butkoden/muscles/blob/master/docs/installation.md).

## Related Repositories

- [`muscles`](https://github.com/butkoden/muscles) - core contracts, routing, actions and canonical documentation.
- [`muscles-asgi`](https://github.com/butkoden/muscles-asgi) - ASGI runtime with the same application model.
- [`muscles-cli`](https://github.com/butkoden/muscles-cli) - CLI projection and developer commands.
- [`muscles-mcp`](https://github.com/butkoden/muscles-mcp) - MCP projection that can also expose WSGI/CLI adapters.
- [`muscles-benchmarks`](https://github.com/butkoden/muscles-benchmarks) - WSGI regression and architecture checks.

## Runtime

An app binds `Context` to `WsgiStrategy`:

```python
from muscles import ApplicationMeta, Configurator, Context
from muscles.wsgi import WsgiStrategy


class App(metaclass=ApplicationMeta):
    config = Configurator(obj={"main": {"HOST": "0.0.0.0", "PORT": "8080"}})
    context = Context(WsgiStrategy, params={})

    def run(self, *args):
        return self.context.execute(*args, shutup=True)
```

`WsgiStrategy` now accepts explicit `host` and `port` keyword arguments and uses
standard WSGI environment keys such as `PATH_INFO`, `QUERY_STRING` and
`wsgi.url_scheme`.

## Schema Ownership

WSGI does not ship its own `muscles.wsgi.schema_` package. Framework schemas,
columns, fields, request/response bodies, security objects and value objects
belong to `muscles.core.schema` and should be imported from `muscles`:

```python
from muscles import Column, JsonRequestBody, Model, String
```

## ASGI/WSGI Parity

WSGI mirrors the ASGI developer-facing API. An application should be able to
switch from `AsgiStrategy` to `WsgiStrategy` without changing route groups,
OpenAPI metadata, guards, auth overrides, response helpers, file upload
handlers or typed handler arguments.

The WSGI package also exposes the same convenience layers:

```python
from muscles.wsgi import MuscularWsgiApp, TestClient, wsgi_app

application = wsgi_app(MuscularWsgiApp())
client = TestClient(application).with_bearer("token")
response = client.post("/api/documents", json={"title": "Spec"})
```

Use `auth=False` on a route when a public endpoint such as `/api/login` lives
inside a protected API group.

## REST API And Swagger

`RestApi` registers controllers and actions into the shared route structure.
Swagger is generated from those controller schemas, request bodies, parameters
and response bodies.

The generated OpenAPI paths include the mounted API prefix. If a controller
action is registered as `/bookings` under prefix `/api/v1`, the schema exposes
`/api/v1/bookings`.

More detail: [docs/openapi-and-routing.md](docs/openapi-and-routing.md).
Backend pipeline features are documented in
[docs/backend-pipeline.md](docs/backend-pipeline.md).
Russian documentation:
[docs/openapi-and-routing.ru.md](docs/openapi-and-routing.ru.md) and
[docs/backend-pipeline.ru.md](docs/backend-pipeline.ru.md).

## Request Handling

The request parser supports standard WSGI input and does not require optional
system libraries to import. Multipart parsing uses the Python standard library;
`python-magic` is treated as optional.

WSGI strategy uses a persistent server lifecycle on strategy/app level, so
route cache is reused across requests while `environ`/`start_response` remain
strictly per-request state.

## Development

Run tests with sibling packages on `PYTHONPATH` when working from source:

```bash
PYTHONPATH=../muscles/src:src python -m pytest -q
```

Production notes: [docs/production.md](docs/production.md).

