Metadata-Version: 2.4
Name: ravendb-embedded
Version: 7.2.7
Summary: RavenDB Embedded library to run RavenDB in an embedded way
Home-page: https://github.com/ravendb/ravendb-python-embedded
Author: RavenDB
Author-email: support@ravendb.net
License: Custom EULA
Keywords: ravendb embedded database nosql doc db
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: ravendb~=7.2.7
Requires-Dist: cryptography>=42.0.0
Dynamic: author
Dynamic: author-email
Dynamic: description
Dynamic: description-content-type
Dynamic: home-page
Dynamic: keywords
Dynamic: license
Dynamic: license-file
Dynamic: requires-dist
Dynamic: requires-python
Dynamic: summary

# ravendb-embedded

`ravendb-embedded` starts a real RavenDB server as a child process of your Python application.
The server starts with your code, stops with it, and is accessed through the standard `ravendb`
client.

Use it for local development, integration tests, or applications that should manage their own
RavenDB process.

## Install

```bash
pip install ravendb-embedded
```

Python 3.10+ is required.

## Quick start

The default mode uses the RavenDB binaries included in the wheel and a compatible system .NET
runtime:

```python
from ravendb_embedded import EmbeddedServer, ServerOptions

options = ServerOptions()

with EmbeddedServer() as server:
    server.start_server(options)
    with server.get_document_store("MyDatabase") as store:
        with store.open_session() as session:
            session.store({"name": "Ayende"}, "people/1")
            session.save_changes()
```

## Choose how RavenDB runs

| Mode | System .NET required? | Server lifecycle | Best for |
|------|-----------------------|------------------|----------|
| [Bundled server](#bundled-server-default) | Yes | Managed by the package | The simplest local setup |
| [On-demand self-contained server](#on-demand-self-contained-server) | No | Downloaded, cached, and managed by the package | Portable developer and CI environments |
| [Self-contained server you provide](#self-contained-server-you-provide) | No | Managed by the package | Offline or centrally controlled server artifacts |

Only the bundled-server mode requires .NET to be installed on the machine running Python.

### Bundled server (default)

The wheel includes a framework-dependent RavenDB server. Its runtime requirement follows the
RavenDB version:

| `ravendb-embedded` version | Required runtime |
|----------------------------|------------------|
| 7.2.x                      | .NET 10          |
| 7.1.x                      | .NET 8           |

Run `dotnet --list-runtimes` and look for `Microsoft.NETCore.App`. Re-check this requirement when
upgrading to a new RavenDB minor version.

Runnable walkthrough: [Lab 01 â€” embedded zero-config](labs/01-embedded-zero-config.md).

### On-demand self-contained server

For the same managed experience without installing .NET, let the package download a
self-contained RavenDB build:

```python
from ravendb_embedded import EmbeddedServer, ServerOptions

options = ServerOptions()
options.with_auto_downloaded_server()
options.data_directory = "./data/RavenDB"
options.logs_path = "./logs/RavenDB"

with EmbeddedServer() as server:
    server.start_server(options)
    with server.get_document_store("MyDatabase") as store:
        ...
```

The operating system and architecture are detected at runtime, so the same Python configuration
is portable across:

- Windows x64 and x86
- Linux x64 and ARM64
- macOS x64 and ARM64

Unsupported targets, including Windows ARM64, fail with an explicit error instead of downloading
an incompatible build.

The first run downloads a self-contained server (100 MB+) and caches it under
`~/.cache/ravendb-embedded`. Later runs reuse that cache. Pass `cache_root` to
`with_auto_downloaded_server()` when you want a different location:

```python
options.with_auto_downloaded_server(cache_root="./.ravendb-cache")
```

By default, the download follows the installed package's RavenDB version line. The cache is not
refreshed automatically; remove that version's cache directory when you intentionally want to
resolve a newer server build from the same line.

The wheel does not contain a self-contained build for every platform; it downloads only the build
needed by the current machine. Self-contained mode removes the system .NET requirement, but normal
RavenDB operating-system dependencies still apply. Minimal Linux images may need their
distribution's ICU package.

Runnable walkthrough: [Lab 03 â€” on-demand server](labs/03-on-demand-server.md).

### Self-contained server you provide

Download and extract the Server package for the target platform, then point the package at its
`Server` directory:

```python
from ravendb_embedded import EmbeddedServer, ServerOptions

options = ServerOptions()
options.with_external_server("/path/to/extracted/Server")

with EmbeddedServer() as server:
    server.start_server(options)
    with server.get_document_store("MyDatabase") as store:
        ...
```

The native apphost is run directly, so `dotnet` is not called. Server packages are available on
the [RavenDB downloads page](https://ravendb.net/downloads).

Runnable walkthrough: [Lab 02 â€” external self-contained server](labs/02-embedded-external-server.md).

### Advanced server sources

`with_external_server()` also accepts a ZIP archive containing RavenDB server files. Applications
that ship the archive as a Python package resource can use
`ExtractFromPkgResourceServerProvider(package, resource_name)`. For other sources, implement
`ProvideRavenDBServer.provide(target_directory)` and assign the provider to `options.provider`.

## Configuration

Create a `ServerOptions` instance before starting the server:

Construct options with `ServerOptions()`. The misleading `ServerOptions.INSTANCE()` constructor
alias is deprecated and will be removed in a future release.

- `data_directory`: where database data is stored; retains the existing
  `<package-directory>/RavenDB` default. Set it explicitly for applications that need a writable
  or application-owned location.
- `logs_path`: where RavenDB writes its logs; defaults to `<data_directory>/Logs` and follows a
  changed `data_directory` until you set `logs_path` explicitly.
- `accept_eula`: controls the RavenDB EULA command-line setting and defaults to `True`.
- `server_url`: address to bind; the default uses localhost and a free port.
- `dot_net_path`: path to `dotnet` for bundled mode when it is not on `PATH`.
- `command_line_args`: additional
  [RavenDB server arguments](https://ravendb.net/docs/article-page/latest/csharp/server/configuration/command-line-arguments).
- `framework_version`: defaults to `""`, preserving the dotnet host's normal runtime selection and
  roll-forward behavior. Set it to `auto` to read the server runtime configuration and select a
  compatible installed patch, or set an exact version for advanced setups.
- `graceful_shutdown_timeout`: how long to wait before terminating the child process.
- `process_kill_timeout`: how long to wait for the process after terminating or killing it.
- `max_server_startup_time_duration`: maximum server startup time.

Startup failures raise `ServerStartupError`. When the configured startup duration expires, the
more specific `ServerStartupTimeoutError` is raised. A failed start does not dispose the
`EmbeddedServer`; correct the configuration and call `start_server()` on the same instance again.

```python
from datetime import timedelta

from ravendb_embedded import EmbeddedServer, ServerOptions, ServerStartupTimeoutError

options = ServerOptions()
options.max_server_startup_time_duration = timedelta(seconds=15)

with EmbeddedServer() as server:
    try:
        server.start_server(options)
    except ServerStartupTimeoutError:
        options.max_server_startup_time_duration = timedelta(minutes=1)
        server.start_server(options)
```

### License and EULA

`accept_eula` remains enabled by default. Applications can configure it through
`options.accept_eula`. See the
[RavenDB EULA](https://ravendb.net/legal/ravendb/commercial-license-eula) for the applicable terms.

Configure a license through `options.licensing`:

```python
options.licensing.license = '{"Id": "..."}'  # Inline license JSON
# Or:
options.licensing.license_path = "/path/to/license.json"

options.licensing.disable_auto_update = True
options.licensing.disable_auto_update_from_api = True
options.licensing.disable_license_support_check = True
options.licensing.throw_on_invalid_or_missing_license = True
```

The fail-fast option is useful in CI and production environments where falling back to an
unlicensed server would hide a configuration problem.

### HTTPS and client certificates

Use `ServerOptions.secured()` with a server PFX to start RavenDB over HTTPS:

```python
options = ServerOptions()
options.secured("server.pfx")
```

This configures the embedded server only. External clients must authenticate with a certificate
trusted by RavenDB. To let `EmbeddedServer` create authenticated `DocumentStore` instances, supply
a client PEM as well:

```python
options = ServerOptions()
options.secured(
    "server.pfx",
    "client.pem",
    server_pfx_certificate_password="",
    ca_certificate_path="ca.crt",
)
```

The returned `DocumentStore` receives the client certificate and custom CA automatically.
The client PEM must contain both its certificate and matching unencrypted private key. If the
certificate declares Extended Key Usage, it must include TLS Client Authentication.

The server PFX is not reused as a client certificate: a server-only certificate may
not have Client Authentication EKU, and its PFX may not contain a suitable client identity.
`ca_certificate_path` is optional for certificates trusted by the operating system; provide a CA
bundle for private or self-signed server certificates. A supplied client PEM and CA bundle are
validated before the RavenDB process starts.

When another process supplies the server certificate, use `secured_with_certificate_exec()`:

```python
options.secured_with_certificate_exec(
    certificate_exec="python",
    certificate_arguments='"load_certificate.py" "server.pfx"',
    client_pem_certificate_path="client.pem",
    ca_certificate_path="ca.crt",
)
```

The certificate command must write the PFX bytes to standard output.

Runnable walkthrough: [Lab 04 â€” secured embedded server](labs/04-embedded-secured.md).

### Server lifecycle

Use `get_server_process_id()` to inspect the child process. `stop_server()` stops RavenDB without
disposing the `EmbeddedServer`, and `restart_server()` starts it again with the same options.
Calling `close()` stops the process and disposes all document stores.

The public API is synchronous, matching the RavenDB Python client's execution model. Server start,
shutdown, and restart calls block until the requested lifecycle transition completes. Async
applications can run these blocking lifecycle calls with `asyncio.to_thread()` instead of
maintaining a second embedded API with different behavior.

`EmbeddedServer` is intentionally not a singleton. An application may run independent server
instances in the same Python process; give each instance a different `data_directory` and
`logs_path`. Prefer `with EmbeddedServer() as server:` so the context manager always closes that
instance's process and document stores.

```python
first_options = ServerOptions()
first_options.data_directory = "./servers/first"

second_options = ServerOptions()
second_options.data_directory = "./servers/second"

with EmbeddedServer() as first, EmbeddedServer() as second:
    first.start_server(first_options)
    second.start_server(second_options)
    assert first.get_server_process_id() != second.get_server_process_id()
```

Register a process-exit callback when the application needs to observe server failures:

```python
server.add_server_process_exited(
    lambda event: print(event.process_id, event.exit_code, event.expected)
)
```

Callbacks run on a background thread. `event.expected` is `True` for exits caused by
`stop_server()`, `restart_server()`, or `close()`, and `False` when the child exits unexpectedly.

Runnable walkthrough: [Lab 06 â€” lifecycle and process monitoring](labs/06-embedded-lifecycle.md).

### Persistent data

The default data directory remains `RavenDB` inside the installed package directory. Set
`data_directory` explicitly when the package directory may be read-only, the application owns its
storage layout, or several embedded servers run in one process. Use a temporary directory for
disposable tests.

Runnable walkthrough: [Lab 05 â€” persistent data](labs/05-embedded-persistent.md).

### Document stores

`get_document_store(database_name)` returns a standard RavenDB `DocumentStore` and creates the
database when needed. For finer control, create `DatabaseOptions` with
`DatabaseOptions.from_database_name()` and call `get_document_store_from_options()`.

Set `skip_creating_database=True` on `DatabaseOptions` when the database is managed elsewhere.
Call `open_studio_in_browser()` to open RavenDB Studio.

## Labs

The repository contains runnable, self-checking examples:

| Lab | Scenario | Needs system .NET? |
|-----|----------|--------------------|
| [01](labs/01-embedded-zero-config.md) | Bundled zero-config server | Yes |
| [02](labs/02-embedded-external-server.md) | Self-contained server you provide | No |
| [03](labs/03-on-demand-server.md) | Automatic platform detection, download, and cache | No |
| [04](labs/04-embedded-secured.md) | HTTPS and client-certificate authentication | Yes |
| [05](labs/05-embedded-persistent.md) | Data that survives server restarts | Yes |
| [06](labs/06-embedded-lifecycle.md) | Stop, restart, PID, and process-exit monitoring | Yes |

The scripts live in the repository rather than the installed wheel. Clone or download the
repository, install the package, and run them from the repository root. See the
[complete labs guide](labs/README.md).

## Links

- [PyPI](https://pypi.org/project/ravendb-embedded/)
- [Source](https://github.com/ravendb/ravendb-python-embedded)
- [RavenDB Python client documentation](https://ravendb.net/docs/article-page/latest/python)
