Skip to content
This repository was archived by the owner on Mar 29, 2025. It is now read-only.

Adding support for RDB version <= 12 and refactoring #19

Merged
merged 35 commits into from
Mar 29, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
4d52810
Add new rdb version and datatypes
bimtauer Dec 19, 2024
865bea2
Begin port to clap and revised structure
bimtauer Dec 19, 2024
677b503
Refactor, fix previous test, add rust integration test
bimtauer Dec 19, 2024
40bea25
Introduce file output and simplify integration test
bimtauer Dec 19, 2024
a28198f
Change encoding of non ascii chars
bimtauer Dec 22, 2024
7b06391
Implement hash list pack
bimtauer Dec 22, 2024
4decc7b
Begin factoring out formatter from parser
bimtauer Dec 23, 2024
3e25fe5
Further refactor formatter
bimtauer Dec 23, 2024
2d11517
Fix tests for refactored json formatter, cleanup pending
bimtauer Dec 25, 2024
0633c9e
Refactor formatter, generic format method
bimtauer Dec 27, 2024
7aaf4ea
Implement skip for hash list pack
bimtauer Dec 27, 2024
8083786
Add integration tests for plain and protocol format
bimtauer Dec 27, 2024
f5c159b
Improve error handling
bimtauer Dec 27, 2024
036be25
Create protocol based integration test across versions
bimtauer Dec 29, 2024
e4bf3c2
Implement listpack handling, better errors, ensure that all previousl…
bimtauer Dec 29, 2024
0439a7b
Implement sorted set v2 and listpack encodings
bimtauer Dec 30, 2024
3115477
Add logging
bimtauer Dec 30, 2024
c0424ae
Small cleanup
bimtauer Dec 30, 2024
b16a169
Restructure code and public lib interface
bimtauer Jan 1, 2025
ca0cd68
Add python bindings
bimtauer Jan 2, 2025
bac656d
Update readme
bimtauer Jan 2, 2025
419a88c
Update changelog
bimtauer Jan 2, 2025
ead9e1a
Link changelog
bimtauer Jan 2, 2025
b7bcbb5
Fix start and end formatting
bimtauer Jan 2, 2025
fcdf100
Integrate shell script tests fully into rust integration tests
bimtauer Jan 2, 2025
8152adf
Remove makefile
bimtauer Jan 2, 2025
74b5836
Update ignore and rm python version
bimtauer Jan 2, 2025
361a432
Heed clippy's call
bimtauer Jan 2, 2025
279fce9
Add Rust CI workflow
bimtauer Jan 2, 2025
7a5bfac
Clean
bimtauer Jan 13, 2025
cd8a83a
Fix Redis Container Integration Test
bimtauer Jan 14, 2025
817f9b4
Adapt python CI
bimtauer Jan 14, 2025
ef4608a
Prep release
bimtauer Jan 14, 2025
2ce44ab
Removing token should use trusted publisher
bimtauer Jan 14, 2025
2a87c62
Rename python project
bimtauer Jan 15, 2025
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
1 change: 1 addition & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* @bimtauer
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added this in my fork as a precaution against hijacking since I did test-publish the python package rdb-py from there. I used a trusted publisher configured for my fork for this. Publishing the python bindings wont work from here. Let me know if you also want to publish 0.3 of the python lib from here first.
Sorry for not mentioning this ealier.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All good! Once I publish the latest version on crates.io, I will hand it over to you and your repo becomes the main one. So we can keep it as that and you can do the rdb-py release afterwards.

149 changes: 149 additions & 0 deletions .github/workflows/Python-CI.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
# This file is autogenerated by maturin v1.8.1
# To update, run
#
# maturin generate-ci github --platform linux --platform windows --platform macos
#
name: Python-CI

on:
push:
branches:
- master
tags:
- '*'
pull_request:
workflow_dispatch:

permissions:
contents: read

jobs:
linux:
runs-on: ${{ matrix.platform.runner }}
strategy:
matrix:
platform:
- runner: ubuntu-22.04
target: x86_64
- runner: ubuntu-22.04
target: x86
- runner: ubuntu-22.04
target: aarch64
- runner: ubuntu-22.04
target: armv7
- runner: ubuntu-22.04
target: s390x
- runner: ubuntu-22.04
target: ppc64le
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: 3.x
- name: Build wheels
uses: PyO3/maturin-action@v1
with:
target: ${{ matrix.platform.target }}
args: --release --out dist --find-interpreter
sccache: 'true'
manylinux: auto
- name: Upload wheels
uses: actions/upload-artifact@v4
with:
name: wheels-linux-${{ matrix.platform.target }}
path: dist

windows:
runs-on: ${{ matrix.platform.runner }}
strategy:
matrix:
platform:
- runner: windows-latest
target: x64
- runner: windows-latest
target: x86
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: 3.x
architecture: ${{ matrix.platform.target }}
- name: Build wheels
uses: PyO3/maturin-action@v1
with:
target: ${{ matrix.platform.target }}
args: --release --out dist --find-interpreter
sccache: 'true'
- name: Upload wheels
uses: actions/upload-artifact@v4
with:
name: wheels-windows-${{ matrix.platform.target }}
path: dist

macos:
runs-on: ${{ matrix.platform.runner }}
strategy:
matrix:
platform:
- runner: macos-13
target: x86_64
- runner: macos-14
target: aarch64
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: 3.x
- name: Build wheels
uses: PyO3/maturin-action@v1
with:
target: ${{ matrix.platform.target }}
args: --release --out dist --find-interpreter
sccache: 'true'
- name: Upload wheels
uses: actions/upload-artifact@v4
with:
name: wheels-macos-${{ matrix.platform.target }}
path: dist

sdist:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build sdist
uses: PyO3/maturin-action@v1
with:
command: sdist
args: --out dist
- name: Upload sdist
uses: actions/upload-artifact@v4
with:
name: wheels-sdist
path: dist

release:
name: Release
runs-on: ubuntu-latest
if: ${{ startsWith(github.ref, 'refs/tags/') || github.event_name == 'workflow_dispatch' }}
needs: [linux, windows, macos, sdist]
permissions:
# Use to sign the release artifacts
id-token: write
# Used to upload release artifacts
contents: write
# Used to generate artifact attestation
attestations: write
steps:
- uses: actions/download-artifact@v4
- name: Generate artifact attestation
uses: actions/attest-build-provenance@v1
with:
subject-path: 'wheels-*/*'
- name: Publish to PyPI
if: ${{ startsWith(github.ref, 'refs/tags/') }}
uses: PyO3/maturin-action@v1
env:
MATURIN_PYPI_TOKEN: ${{ secrets.PYPI_API_TOKEN }}
with:
command: upload
args: --non-interactive --skip-existing wheels-*/*
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will fail in this repository

1 change: 1 addition & 0 deletions .python-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3.10
9 changes: 9 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,18 @@ name = "rdb"
path = "src/main.rs"
doc = false

[lib]
name = "rdb"
crate-type = ["cdylib", "rlib"]

[dependencies]
lzf = "0.3"
getopts = "0.2"
rustc-serialize = "0.3"
regex = "0.1"
byteorder = "0.5"
thiserror = "1.0"
pyo3 = { version = "0.23.3", features = ["extension-module"], optional = true }
clap = { version = "4.4", features = ["derive"] }
indexmap = "2.7.0"
log = "0.4.22"
Expand All @@ -45,3 +50,7 @@ rstest = "0.23.0"
testcontainers = "0.23.1"
testcontainers-modules = { version = "0.11.4", features = ["redis"] }
tempfile = "3.14.0"

[features]
default = []
python = ["pyo3"]
23 changes: 23 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
[project]
name = "rdb"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.10"
dependencies = [
"maturin>=1.8.0",
"cffi==1.17.1"
]
classifiers = [
"Programming Language :: Rust",
"Programming Language :: Python :: Implementation :: CPython",
"Programming Language :: Python :: Implementation :: PyPy",
]


[build-system]
requires = ["maturin>=1,<2"]
build-backend = "maturin"

[tool.maturin]
features = ["python"]
1 change: 0 additions & 1 deletion src/formatter/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,6 @@ pub trait Formatter {
self.checksum(checksum);
Ok(())
}
_ => Ok(()),
}
}
}
Expand Down
74 changes: 67 additions & 7 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
//! # use std::path::Path;
//! let file = File::open(&Path::new("dump.rdb")).unwrap();
//! let reader = BufReader::new(file);
//! rdb::parse(reader, rdb::formatter::JSON::new(None), rdb::filter::Simple::new());
//! rdb::parse_with_formatter(reader, rdb::formatter::JSON::new(None), rdb::filter::Simple::new());
//! ```
//!
//! # Formatter
Expand Down Expand Up @@ -72,12 +72,11 @@
//! value
//! ```

extern crate byteorder;
extern crate lzf;
extern crate regex;
extern crate rustc_serialize as serialize;
#[cfg(feature = "python")]
use pyo3::exceptions::PyValueError;
#[cfg(feature = "python")]
use pyo3::prelude::*;

//use pyo3::prelude::*;
use std::io::Read;

#[doc(hidden)]
Expand Down Expand Up @@ -107,6 +106,10 @@ impl<R: Read, L: Filter, F: Formatter> RdbParser<R, L, F> {
formatter: None,
}
}

pub fn into_iter(self) -> RdbDecoder<R, L> {
self.decoder
}
}

#[derive(Default)]
Expand Down Expand Up @@ -156,7 +159,7 @@ impl<R: Read, L: Filter, F: Formatter> RdbParser<R, L, F> {
}
}

pub fn parse<R: Read, L: Filter + Default, F: Formatter>(
pub fn parse_with_formatter<R: Read, L: Filter + Default, F: Formatter>(
reader: R,
formatter: F,
filter: L,
Expand All @@ -168,3 +171,60 @@ pub fn parse<R: Read, L: Filter + Default, F: Formatter>(
.build();
parser.parse()
}

#[cfg(feature = "python")]
#[pyclass(name = "RdbDecoder")]
pub struct PyRdbDecoder {
decoder: RdbDecoder<std::fs::File, Simple>,
}

#[cfg(feature = "python")]
#[pymethods]
impl PyRdbDecoder {
#[new]
pub fn new(path: &str) -> PyResult<Self> {
let file = std::fs::File::open(path)
.map_err(|e| PyValueError::new_err(format!("Failed to open file: {}", e)))?;

let mut filter = Simple::new();

for t in [
Type::Hash,
Type::String,
Type::List,
Type::Set,
Type::SortedSet,
] {
filter.add_type(t);
}

let decoder = RdbDecoder::new(file, filter)
.map_err(|e| PyValueError::new_err(format!("Failed to create decoder: {}", e)))?;

Ok(PyRdbDecoder { decoder })
}

fn __iter__(slf: PyRef<'_, Self>) -> PyRef<'_, Self> {
slf
}

fn __next__(mut slf: PyRefMut<'_, Self>) -> PyResult<Option<PyObject>> {
match slf.decoder.next() {
Some(Ok(value)) => Python::with_gil(|py| {
value
.into_pyobject(py)
.map(|obj| Some(obj.into()))
.map_err(|e| PyValueError::new_err(format!("Conversion error: {}", e)))
}),
Some(Err(e)) => Err(PyValueError::new_err(format!("Parsing error: {}", e))),
None => Ok(None),
}
}
}

#[cfg(feature = "python")]
#[pymodule(name = "rdb")]
fn rdb_py(m: &Bound<'_, PyModule>) -> PyResult<()> {
m.add_class::<PyRdbDecoder>()?;
Ok(())
}
2 changes: 1 addition & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,5 +96,5 @@ pub fn main() {
}
};

rdb::parse(reader, formatter, filter).expect("Failed to parse RDB file");
rdb::parse_with_formatter(reader, formatter, filter).expect("Failed to parse RDB file");
}
1 change: 0 additions & 1 deletion src/parser/mod.rs

This file was deleted.

1 change: 0 additions & 1 deletion src/parser/rdb.rs

This file was deleted.

Loading