Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/docs/src/content/docs/packages/graphql/context.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ What Strawberry is handed as `context_value`, and what a resolver gets by
annotating `GraphContext`.

```python
from sillo.graphql import GraphContext
from sillo_graphql import GraphContext


@field
Expand Down
6 changes: 3 additions & 3 deletions docs/docs/src/content/docs/packages/graphql/errors.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ description: Free builders with stable codes, masking of anything unexpected, an
`redirect()`. Errors here follow the same shape.

```python
from sillo.graphql import forbidden, not_found
from sillo_graphql import forbidden, not_found


@field
Expand Down Expand Up @@ -87,7 +87,7 @@ unusable; masking a `RuntimeError` is the whole point.
### Configuring it

```python
from sillo.graphql import ErrorPolicy
from sillo_graphql import ErrorPolicy

Graph(schema, errors=ErrorPolicy(
mask=True, # the default
Expand Down Expand Up @@ -120,7 +120,7 @@ An application raises its own exceptions, and masking them is the right default
and a poor experience.

```python
from sillo.graphql import bad_input, conflict, not_found
from sillo_graphql import bad_input, conflict, not_found


@graph.on_error(RecordNotFound)
Expand Down
19 changes: 7 additions & 12 deletions docs/docs/src/content/docs/packages/graphql/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ A production GraphQL endpoint over a Strawberry schema.
pip install sillo-graphql
```

Installs as `sillo-graphql`, imports as `sillo.graphql`. Strawberry keeps the
Installs as `sillo-graphql`, imports as `sillo_graphql`. Strawberry keeps the
schema; this package owns everything around it — the transports, the safety,
and the observability.

```python
import strawberry
from sillo import Depend, HttpContext, SilloApp
from sillo.graphql import Graph, Limits, field
from sillo_graphql import Graph, Limits, field


@strawberry.type
Expand Down Expand Up @@ -101,17 +101,12 @@ If you are moving from the framework's module, the shortest path is
`Mapping`, so the old subscript keeps working and a schema can migrate one
resolver at a time.

## The two import paths
## Not the framework's `sillo.graphql`

`sillo.graphql` and `sillo_graphql` are the same module object. The code lives
in the top-level `sillo_graphql` package; a `.pth` registers a meta-path finder
at interpreter startup, and PEP 561 partial stubs serve type checkers, which
never run import hooks. Nothing is written into the framework's `sillo/`
directory.

Because the framework shipped its own `sillo.graphql` before 1.0, the alias
**refuses to load** against an older framework rather than silently shadowing
it, and says which two things disagree.
Versions of `sillo-framework` before 1.0 shipped a GraphQL module of their own
at `sillo.graphql`. This package is its replacement, not an upgrade of it: it
installs separately, imports as `sillo_graphql`, and requires framework 1.0 or
newer. The table above is the migration.

## Requirements

Expand Down
4 changes: 2 additions & 2 deletions docs/docs/src/content/docs/packages/graphql/limits.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ So the document is measured **before** execution and refused if it is too
large. Refusing afterwards would mean having already done the work.

```python
from sillo.graphql import Graph, Limits
from sillo_graphql import Graph, Limits

Graph(schema, limits=Limits(depth=10, cost=1_000, aliases=15)).mount(app)
```
Expand Down Expand Up @@ -153,7 +153,7 @@ are refused.

```python
from graphql import parse
from sillo.graphql import Limits, analyze
from sillo_graphql import Limits, analyze

result = analyze(parse(document), limits=Limits(), schema=graph.schema._schema)
result.depth, result.cost, result.aliases, result.breadth, result.fields
Expand Down
2 changes: 1 addition & 1 deletion docs/docs/src/content/docs/packages/graphql/loaders.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ Prefer a tuple over a dict — a tuple hashes, so it caches.
Background jobs and tests can open a scope of their own:

```python
from sillo.graphql import LoaderRegistry
from sillo_graphql import LoaderRegistry


async def nightly_digest():
Expand Down
4 changes: 2 additions & 2 deletions docs/docs/src/content/docs/packages/graphql/observability.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ year of rows are the same endpoint.
What is worth measuring is per **operation**.

```python
from sillo.graphql import Metrics, OperationLog
from sillo_graphql import Metrics, OperationLog

graph.on_operation(OperationLog(slower_than=0.5))

Expand Down Expand Up @@ -108,7 +108,7 @@ Pass a logger of your own as the first argument; it defaults to

```python
from opentelemetry import trace
from sillo.graphql import opentelemetry
from sillo_graphql import opentelemetry

graph.on_operation(opentelemetry(trace.get_tracer("graphql")))
```
Expand Down
6 changes: 3 additions & 3 deletions docs/docs/src/content/docs/packages/graphql/persisted.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ your application actually sends is generated at build time, and the server
executes nothing else.

```python
from sillo.graphql import Persisted
from sillo_graphql import Persisted

Graph(schema, persisted=Persisted(apq=True)) # bandwidth
Graph(schema, persisted=Persisted(trusted="operations.json")) # safety
Expand Down Expand Up @@ -47,7 +47,7 @@ separately, which is correct and merely wasteful, so a shared store is worth
configuring once there is more than one.

```python
from sillo.graphql import MemoryStore
from sillo_graphql import MemoryStore

Graph(schema, store=MemoryStore(max_entries=5_000))
```
Expand Down Expand Up @@ -88,7 +88,7 @@ Generate it from your client's operations at build time and ship it with the
server. It can also be passed inline, which is what a test wants:

```python
from sillo.graphql import hash_document
from sillo_graphql import hash_document

document = "{ hello }"
Graph(schema, persisted=Persisted(trusted={hash_document(document): document}))
Expand Down
2 changes: 1 addition & 1 deletion docs/docs/src/content/docs/packages/graphql/resolvers.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ it needs. A resolver here is the same thing.
```python
import strawberry
from sillo import Depend, HttpContext
from sillo.graphql import field, mutation, subscription
from sillo_graphql import field, mutation, subscription


@strawberry.type
Expand Down
6 changes: 3 additions & 3 deletions docs/docs/src/content/docs/packages/graphql/subscriptions.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ from typing import AsyncGenerator

import strawberry
from sillo import WebSocketContext
from sillo.graphql import subscription
from sillo_graphql import subscription


@strawberry.type
Expand Down Expand Up @@ -72,7 +72,7 @@ the `connection_init` payload instead. `@graph.on_connect` is given it before
any operation runs.

```python
from sillo.graphql import unauthenticated
from sillo_graphql import unauthenticated


@graph.on_connect
Expand Down Expand Up @@ -111,7 +111,7 @@ and counted.
## Tuning

```python
from sillo.graphql.transport.ws import WebSocketTransport
from sillo_graphql.transport.ws import WebSocketTransport

graph.ws = WebSocketTransport(graph, init_timeout=5.0, keepalive=20.0)
```
Expand Down
6 changes: 3 additions & 3 deletions docs/docs/src/content/docs/packages/graphql/testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ A GraphQL test written through a plain HTTP client is four lines of JSON
assembly and a dictionary walk before it reaches the thing under test.

```python
from sillo.graphql.testing import GraphClient
from sillo_graphql.testing import GraphClient


def test_me():
Expand Down Expand Up @@ -155,7 +155,7 @@ slow afternoon.
Outside a request, open a scope:

```python
from sillo.graphql import LoaderRegistry
from sillo_graphql import LoaderRegistry


async def test_the_batch_function_aligns_its_results():
Expand Down Expand Up @@ -183,7 +183,7 @@ test cannot leak:
```python
import pytest
from sillo import SilloApp
from sillo.graphql import Graph, Limits
from sillo_graphql import Graph, Limits


@pytest.fixture
Expand Down
6 changes: 3 additions & 3 deletions docs/docs/src/content/docs/packages/graphql/transport.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ a client parse a body to discover.
## Requests

```python
from sillo.graphql import Transport
from sillo_graphql import Transport

Graph(schema, transport=Transport(
get_queries=True,
Expand Down Expand Up @@ -101,7 +101,7 @@ that accepts files has a materially larger attack surface than one that does
not, and that should be a decision.

```python
from sillo.graphql import Uploads
from sillo_graphql import Uploads

Graph(schema, uploads=Uploads(
enabled=True,
Expand Down Expand Up @@ -138,7 +138,7 @@ than a 500 on the first large request.
## The explorer

```python
from sillo.graphql import IDE
from sillo_graphql import IDE

Graph(schema, ide=True) # bundled, offline
Graph(schema, ide=IDE(enabled=True, assets="cdn")) # GraphiQL from unpkg
Expand Down
50 changes: 24 additions & 26 deletions docs/docs/src/content/docs/packages/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,49 +10,47 @@ cadence, or a scope that the core should not carry on everybody's behalf.

| Package | Install | Import | What it is |
|---|---|---|---|
| [Wire](/packages/wire/) | `sillo-wire` | `sillo.wire` | Rooms, presence and fan-out for WebSockets |
| [GraphQL](/packages/graphql/) | `sillo-graphql` | `sillo.graphql` | A production GraphQL endpoint over a Strawberry schema |
| [Wire](/packages/wire/) | `sillo-wire` | `sillo_wire` | Rooms, presence and fan-out for WebSockets |
| [GraphQL](/packages/graphql/) | `sillo-graphql` | `sillo_graphql` | A production GraphQL endpoint over a Strawberry schema |
| [Warder](/packages/warder/) | `warder` | `warder` | A declarative admin over your models |

Each has a manual of its own — pick one above and the sidebar becomes its
table of contents.

## How they attach

Wire and GraphQL extend the framework's own surface, so they take a name inside
it. The code lives in a top-level package — `sillo_wire`, `sillo_graphql` — and
the framework name is an alias for it. Both bind the same objects:
Every package is a plain top-level distribution with a plain top-level import
name. Install `sillo-wire`, import `sillo_wire`:

```python
from sillo.wire import Hub # both of these
from sillo_wire import Hub # name the same class
from sillo_wire import Hub, Peer
from sillo_graphql import Graph, field
```

Warder does not, and the difference is deliberate. It is not an extension of
`sillo` — it is an application you mount on yours, the way you would mount any
other. So it keeps its own name:
Warder is the exception to the naming rule, and the difference is deliberate.
It is not an extension of `sillo` — it is an application you mount on yours,
the way you would mount any other — so it keeps its own name:

```python
from warder import Admin
admin.mount(app)
```

The alias is a meta-path finder the package registers through a `.pth` at
interpreter startup, plus PEP 561 partial stubs so type checkers resolve it
too. Nothing is written into the `sillo` package directory.

That last part is the point. Shipping `sillo/wire/` into the framework's own
directory is simpler, and it is what Wire did first — but two distributions
sharing one directory goes wrong in both directions. Installing the framework
from a checkout moves where `sillo` resolves and orphans the copy in
site-packages; removing or replacing the framework leaves that directory
standing with no `__init__.py` in it, which is an override rather than an
addition. Uninstalling either package now leaves the other untouched.

One consequence is worth stating plainly: a package cannot claim a name the
framework still uses. `sillo-graphql` claims `sillo.graphql`, which the
framework shipped until 1.0 — so against an older framework the alias
refuses to load and says why, rather than quietly shadowing it.
Nothing is ever written into the framework's own `sillo` package directory.
Shipping `sillo/wire/` in there is simpler, and it is what Wire did first — but
two distributions sharing one directory goes wrong in both directions.
Installing the framework from a checkout moves where `sillo` resolves and
orphans the copy in site-packages; removing or replacing the framework leaves
that directory standing with no `__init__.py` in it, which is an override
rather than an addition. Uninstalling either package leaves the other
untouched.

Wire and GraphQL previously also answered to `sillo.wire` and `sillo.graphql`,
through a meta-path finder registered by a `.pth` at interpreter startup and a
second set of PEP 561 stubs to serve type checkers. It read as part of the
framework, at the cost of a `.pth` running on every interpreter start and type
declarations kept in two places. Those aliases are gone; the `sillo_` names
above are the only ones.

## What stays in core

Expand Down
4 changes: 2 additions & 2 deletions docs/docs/src/content/docs/packages/wire/backlog.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Mobile clients disconnect. Laptops sleep. A backlog is what turns that from
data loss into a gap the client can ask about.

```python
from sillo.wire import Hub, MemoryBacklog
from sillo_wire import Hub, MemoryBacklog

hub = Hub(backlog=MemoryBacklog(capacity_bytes=4 * 1024 * 1024))
```
Expand Down Expand Up @@ -122,7 +122,7 @@ backlog at all.
## No backlog

```python
from sillo.wire import Hub, NullBacklog
from sillo_wire import Hub, NullBacklog

hub = Hub(backlog=NullBacklog()) # the same as Hub()
```
Expand Down
2 changes: 1 addition & 1 deletion docs/docs/src/content/docs/packages/wire/consumers.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ of application code, and the ceremony is where the leaks are. `RoomConsumer`
writes it once.

```python
from sillo.wire import Hub, RoomConsumer
from sillo_wire import Hub, RoomConsumer

hub = Hub()

Expand Down
2 changes: 1 addition & 1 deletion docs/docs/src/content/docs/packages/wire/hub.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ A `Hub` is a set of rooms, and a room is a set of peers. Everything that
reaches more than one connection goes through it.

```python
from sillo.wire import Hub
from sillo_wire import Hub

hub = Hub()
```
Expand Down
17 changes: 2 additions & 15 deletions docs/docs/src/content/docs/packages/wire/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ Rooms, presence and fan-out for WebSockets.
pip install sillo-wire
```

Installs as `sillo-wire`, imports as `sillo.wire`. The core keeps the socket
Installs as `sillo-wire`, imports as `sillo_wire`. The core keeps the socket
itself — [`WebSocketContext`](/v1.0/guides/websockets/) — and this adds
everything about talking to more than one of them at a time.

```python
from sillo import SilloApp
from sillo.wire import Hub, Peer
from sillo_wire import Hub, Peer

app = SilloApp()
hub = Hub()
Expand Down Expand Up @@ -105,19 +105,6 @@ counted in payload bytes and evicts oldest-first.
The status enums are gone. `join` and `leave` return a plain `bool`, and
`broadcast` returns a [`DeliveryReport`](/packages/wire/reference/).

## The two import paths

`sillo.wire` and `sillo_wire` are the same module object, not two copies. The
code lives in the top-level `sillo_wire` package; a `.pth` shipped with the
distribution registers a meta-path finder at interpreter startup, and PEP 561
partial stubs serve type checkers, which never run import hooks.

Nothing is written into the framework's own `sillo/` directory. Two
distributions sharing one package directory goes wrong in both directions —
installing the framework from a checkout orphans whatever the other package
left in site-packages, and removing the framework leaves a directory standing
with no `__init__.py` in it.

## Requirements

Python 3.10 through 3.14, and `sillo-framework`. Nothing else.
Expand Down
Loading
Loading