Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
48caa69
RavenDB-27069 Add Lab 01: embedded zero-config (guide + runnable scri…
poissoncorp Jul 22, 2026
5f6d379
RavenDB-27069 Detect self-contained servers in ExternalServerProvider…
poissoncorp Jul 22, 2026
0479d2d
RavenDB-27069 Add Lab 02: external self-contained server (no system .…
poissoncorp Jul 22, 2026
62bdcae
RavenDB-27069 CI: net10-only matrix, enforce required .NET, run labs …
poissoncorp Jul 22, 2026
7d58db1
RavenDB-27069 Cleanup: drop dead pin_framework_version helper; requir…
poissoncorp Jul 22, 2026
5515182
RavenDB-27069 Remove no-op CommandLineArgumentEscaper (Popen gets an …
poissoncorp Jul 22, 2026
acac43d
RavenDB-27069 Document the .NET runtime requirement and Python 3.10+ …
poissoncorp Jul 22, 2026
b09b24e
RavenDB-27069 Add Lab 04: on-demand cached self-contained server (exp…
poissoncorp Jul 23, 2026
5b9b519
RavenDB-27069 Trim comments to critical one-liners; drop dead noise
poissoncorp Jul 23, 2026
f66cc31
RavenDB-27069 Rewrite README around usage cases (why/how + link labs)
poissoncorp Jul 23, 2026
499fc95
RavenDB-27069 Bump to 7.2.5 (bundled server + package); pin client to…
poissoncorp Jul 23, 2026
0476851
RavenDB-27069 Pin GitHub Actions to commit SHA; add Dependabot (actio…
poissoncorp Jul 23, 2026
ca363bb
RavenDB-27069 Renumber on-demand to Lab 03; document pulling latest s…
poissoncorp Jul 23, 2026
a7c6068
RavenDB-27069 Add Lab 04 (secured) and Lab 05 (persistent data dir); …
poissoncorp Jul 23, 2026
0c1a1ab
RavenDB-27069 Implement on-demand self-contained server as a real fea…
poissoncorp Jul 23, 2026
035c7bd
RavenDB-27069 Consolidate to a single markdown README (stale README.m…
poissoncorp Jul 23, 2026
19ca7bb
RavenDB-27069 Docs: point users to the official downloads page instea…
poissoncorp Jul 28, 2026
af43ee4
RavenDB-27069 Rename with_on_demand_server -> with_auto_downloaded_se…
poissoncorp Jul 28, 2026
3d0c7aa
RavenDB-27069 Trim remaining redundant inline comments to critical on…
poissoncorp Jul 28, 2026
53c4995
RavenDB-27069 Run a ready external/self-contained server in place; fi…
poissoncorp Jul 28, 2026
0126076
RavenDB-27069 Harden on-demand download: reject archive path-traversa…
poissoncorp Jul 28, 2026
585ac50
RavenDB-27069 check_dotnet_requirement: clean message + int exit when…
poissoncorp Jul 28, 2026
0e43533
RavenDB-27069 Run a ready server in place explicitly; never clear the…
poissoncorp Jul 28, 2026
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
15 changes: 15 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
groups:
github-actions:
patterns:
- "*"

- package-ecosystem: "pip"
directory: "/"
schedule:
interval: "weekly"
68 changes: 55 additions & 13 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,30 +9,27 @@ on:

jobs:
test:
# Path A: embedded framework-dependent server -> needs a system .NET. The 7.2 server
# targets net10.0 (7.1 was net8.0), so we install .NET 10 explicitly and assert the
# bundled server really needs it (no more green-by-luck on a preinstalled runtime).
runs-on: ${{ matrix.os }}
env:
# .NET 8 (the server's target) is exercised by default resolution; .NET 10 must be
# forced since runners preinstall .NET 8 and would otherwise win. tests/pin_framework_version.
RAVENDB_TEST_FRAMEWORK_VERSION: ${{ matrix.dotnet == '10.0' && '10.0.x' || '' }}
strategy:
fail-fast: false
# Latest Python only (the ravendb client requires 3.10+); full OS x .NET matrix.
matrix:
os: [ubuntu-latest, windows-latest]
dotnet: ["8.0", "10.0"]

steps:
- uses: actions/checkout@v4
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0

- name: Set up Python 3.13
uses: actions/setup-python@v5
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: "3.13"

- name: Set up .NET ${{ matrix.dotnet }}
uses: actions/setup-dotnet@v4
- name: Set up .NET 10
uses: actions/setup-dotnet@67a3573c9a986a3f9c594539f4ab511d57bb3ce9 # v4.3.1
with:
dotnet-version: ${{ matrix.dotnet }}
dotnet-version: "10.0"

- name: Install package
run: |
Expand All @@ -44,12 +41,57 @@ jobs:
pip install black
black --check .

# Populates ravendb_embedded/target/nuget via the project's sdist hook (the server the
# tests copy from). setuptools is installed explicitly; modern virtualenvs omit it.
# Downloads + unpacks the bundled (framework-dependent) server into
# ravendb_embedded/target/nuget. setuptools is installed explicitly; modern venvs omit it.
- name: Fetch bundled RavenDB server
run: |
pip install setuptools wheel
python setup.py sdist

- name: Assert CI .NET matches the server's required runtime
run: python scripts/check_dotnet_requirement.py

- name: Run tests
run: python -m unittest discover -s tests

- name: Run Lab 01 (embedded zero-config)
run: python labs/01_embedded_zero_config.py

- name: Run Lab 04 (secured embedded)
run: python labs/04_embedded_secured.py

- name: Run Lab 05 (persistent data directory)
run: python labs/05_embedded_persistent.py

self-contained:
# Path B: external self-contained server -> runs the native apphost, no system .NET.
# We do not set up .NET; the lab uses a bogus dot_net_path so a successful run proves the
# apphost path is genuinely dotnet-free even though the runner happens to ship a .NET.
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0

- name: Set up Python 3.13
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: "3.13"

- name: Install package
run: |
python -m pip install --upgrade pip
pip install -e .

- name: Download a self-contained RavenDB server
run: |
curl -fsSL -o ravendb.tar.bz2 "https://hibernatingrhinos.com/downloads/RavenDB%20for%20Linux%20x64/latest?version=7.2"
mkdir server
tar xjf ravendb.tar.bz2 -C server

- name: Run Lab 02 (self-contained, no system .NET)
run: |
SERVER="$(find server -type d -name Server | head -1)"
RAVENDB_SELF_CONTAINED_SERVER="$SERVER" python labs/02_embedded_external_server.py

- name: Run Lab 03 (on-demand cached self-contained, no system .NET)
run: python labs/03_on_demand_server.py
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
/dist
/ravendb_embedded.egg-info
/ravendb_embedded/target
/ravendb_embedded/RavenDB
*.pyc
*.log
*.raven-topology
Expand Down
2 changes: 1 addition & 1 deletion MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
graft ravendb_embedded/target/nuget
include README.rst
include README.md
recursive-exclude tests *
195 changes: 123 additions & 72 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,106 +1,157 @@
# ravendb-embedded

## Overview
ravendb-embedded is a RavenDB package for running RavenDB in embedded mode.
`ravendb-embedded` runs a real RavenDB server from inside your Python program. You `pip install`
it, start the server in-process, and talk to it with the normal `ravendb` client. There is no
separate server to install, configure, or keep running: the server's lifetime follows your
process.

Reach for it when you want:

- **Local development** without setting up a standalone RavenDB.
- **Integration tests** against a real server instead of a mock (see also `ravendb-test-driver`).
- **Small or self-contained apps** that ship the database alongside the code.

```python
from ravendb_embedded import EmbeddedServer

EmbeddedServer().start_server()
with EmbeddedServer().get_document_store("Embedded") as store:
with store.open_session() as session:
session.store(User(name="Ilay", age=4))
session.save_changes()
```
with EmbeddedServer() as server:
server.start_server()
with server.get_document_store("Embedded") as store:
with store.open_session() as session:
session.store({"name": "Ayende"}, "people/1")
session.save_changes()
```

## Installation
Install from [PyPi](https://pypi.python.org/pypi), as [ravendb-embedded](https://pypi.python.org/project/ravendb-embedded).

```bash
pip install ravendb-embedded
```
Install ravendb-embedded from pip will provide you with a copy of RavenDB server binaries files as well.

The install includes a copy of the RavenDB server binaries. Python 3.10+ is required.

## The .NET requirement (read this)

The bundled server is a .NET application, so a matching **.NET runtime** must be on the machine.
The required version tracks the bundled server:

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

Check what is installed with `dotnet --list-runtimes` (look for `Microsoft.NETCore.App`). Because
the requirement follows the bundled server, it can change on a minor upgrade, so re-check it when
you bump versions.

If the machine cannot or should not have .NET, use the self-contained path under
[Run without installing .NET](#run-without-installing-net) below.

## Usage
#### Start a server
To start RavenDB server, call `start_server()` method from `EmbeddedServer` instance.
```python
from ravendb_embedded import EmbeddedServer

ravendb_server = EmbeddedServer()
ravendb_server.start_server()
```
To be more in control about your server `start_server` method can take `server_options`.
The three sections below are the ways people actually use this package. Pick the one that matches
your environment; each links to a runnable walkthrough in `labs/`.

### Run it (the default, needs .NET)

Start the server and get a document store. This is the zero-config path and uses the system .NET
described above. Pass a `ServerOptions` when you want to control where data lives, the bind URL,
and so on.

#### ServerOptions
* **framework_version** - The framework version to run the server with.
* **data_directory** - Where to save the database data (if None the files will be saved in RavenDB folder in the base folder).
* **server_url** - The url the server will be opened if None the server will open on local host.
* **dotnet_path** - Where dotnet.exe is located if dotnet in the PATH nothing needed here (If .net core is not installed in your machine
you can download [dotnet binaries](https://www.microsoft.com/net/download/windows) and just put the path to it)
* **command_line_args** - A list of all [server command args](https://ravendb.net/docs/article-page/6.0/csharp/server/configuration/command-line-arguments).
```python
from ravendb_embedded import EmbeddedServer, ServerOptions

server_options = ServerOptions(data_directory="MYPATH/RavenDBDataDir")
EmbeddedServer().start_server(server_options)
options = ServerOptions()
options.data_directory = "MYPATH/RavenDBDataDir" # optional; defaults to a local RavenDB folder

with EmbeddedServer() as server:
server.start_server(options)
with server.get_document_store("MyDb") as store:
... # ordinary ravendb client code
```
---
##### Security
There are options to make ravendb secured in ravendb-embedded:<br />

`secured(server_pfx_certificate_path, client_pem_certificate_path, server_pfx_certificate_password=None, ca_certificate_path = None)`
- For this option you will put path to a .pfx and .pem files and a password/ca cert if you have one.
- Server certificate password and CA cert file are optional arguments. Minimal setup requires both .pfx server and .pem client certificates.
```python
from ravendb_embedded import EmbeddedServer, ServerOptions

server_options = ServerOptions()
server_options.secured("PATH_TO_SERVER_PFX_CERT_FILE", "PATH_TO_CLIENT_PEM_CERT")
EmbeddedServer.start_server(server_options)
```
---
#### Get Document Store
After initialize and start the server we can use `get_document_store` method to be able to get a DocumentStore
and start work with RavenDB as normal.

Runnable walkthrough: [`labs/01-embedded-zero-config.md`](labs/01-embedded-zero-config.md).

### Run without installing .NET

On locked-down hosts or minimal CI images where you do not want a system .NET, bring a
**self-contained** RavenDB build (it bundles its own runtime). Point the server at the extracted
`Server` folder: the driver detects the bundled runtime and launches the server's native apphost
directly, never calling `dotnet`.

```python
from ravendb_embedded import EmbeddedServer
from ravendb_embedded import EmbeddedServer, ServerOptions

ravendb_server = EmbeddedServer()
ravendb_server.start_server()
options = ServerOptions()
options.with_external_server("/path/to/extracted/Server") # a self-contained build

with ravendb_server.get_document_store("Test") as store:
# Your code here
with EmbeddedServer() as server:
server.start_server(options)
with server.get_document_store("MyDb") as store:
...
```
---

##### DatabaseOptions
* **database_name** - The name of the database
* **skip_creating_database** - `get_document_store` will create a new database if the database is not exists,
if this option if True we won't create the database (Default False).
Download the Server package for your platform from the [RavenDB downloads page](https://ravendb.net/downloads);
the server files live in the archive's `Server/` folder. Runnable walkthrough:
[`labs/02-embedded-external-server.md`](labs/02-embedded-external-server.md).

Or skip the manual download and let the driver fetch and cache one for you on first use:

```python
# In this example we won't create the Test database if not exists will raise an exception
from ravendb_embedded import EmbeddedServer, DatabaseOptions
options = ServerOptions()
options.with_auto_downloaded_server() # downloads + caches a self-contained server, no .NET needed
```

ravendb_server = EmbeddedServer()
ravendb_server.start_server()
Walkthrough: [`labs/03-on-demand-server.md`](labs/03-on-demand-server.md).

database_options = DatabaseOptions.from_database_name("Test")
database_options.skip_creating_database = True
### Don't manage a server at all (tests)

with ravendb_server.get_document_store_from_options(database_options) as store:
# Your code here
```
For test suites that should not touch .NET or embedded startup, `ravendb-test-driver` can attach
to a RavenDB you run yourself (Docker, testcontainers, a shared CI service) while still giving
each test its own database. See the
[`ravendb-python-testdriver`](https://github.com/ravendb/ravendb-python-testdriver) repository.

#### Open RavenDB studio in the browser
To open RavenDB studio from ravendb-embedded you can use `open_studio_in_browser` method and the studio will open automatically
one your default browser.
## Configuration

```python
from ravendb_embedded import EmbeddedServer
ravendb_server = EmbeddedServer()
ravendb_server.start_server()
### `ServerOptions`

Create `ServerOptions()` and set attributes:

- `data_directory`: where database data is stored (defaults to a local `RavenDB` folder). Set a
stable path for data that outlives the process, see
[`labs/05-embedded-persistent.md`](labs/05-embedded-persistent.md).
- `server_url`: the URL to bind (defaults to localhost on a free port).
- `dot_net_path`: path to `dotnet` when it is not on `PATH` (ignored on the self-contained path).
- `command_line_args`: extra [server command-line arguments](https://ravendb.net/docs/article-page/latest/csharp/server/configuration/command-line-arguments).
- `framework_version`: pin an exact .NET version (advanced; leave empty to autodetect the installed runtime).

ravendb_server.open_studio_in_browser()
### Security

Secure the server with `ServerOptions.secured()`:

```python
options = ServerOptions()
options.secured(
server_pfx_certificate_path, # server certificate (.pfx), required
client_pem_certificate_path, # client certificate (.pem)
server_pfx_certificate_password=None,
ca_certificate_path=None,
)
```

Runnable example (HTTPS + client-certificate auth):
[`labs/04-embedded-secured.md`](labs/04-embedded-secured.md).

### Working with data

`get_document_store(database_name)` returns a `DocumentStore` you use like any RavenDB client. For
finer control, build a `DatabaseOptions` (via `DatabaseOptions.from_database_name`) and call
`get_document_store_from_options`; set `skip_creating_database=True` to not auto-create the
database.

Call `open_studio_in_browser()` to open RavenDB Studio in your default browser.

## Labs

The `labs/` folder holds runnable, self-checking guides, one per usage case above. Start at
[`labs/README.md`](labs/README.md).
Loading
Loading