Skip to content

Commit

Permalink
add python wrapper
Browse files Browse the repository at this point in the history
  • Loading branch information
carderne committed Apr 15, 2024
1 parent ab0ed05 commit 9cb47be
Show file tree
Hide file tree
Showing 11 changed files with 126 additions and 7 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@ cov:

.PHONY: py
py:
maturin develop
rye run maturin develop --pip-path ~/.rye/self/bin/pip
53 changes: 52 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
[tool.rye.scripts]
check = "pyright"
test = "pytest"

[build-system]
requires = ["maturin>=1.5,<2.0"]
build-backend = "maturin"

[project]
name = "bean-rs"
requires-python = ">= 3.9"
classifiers = [
"Environment :: Console",
"License :: OSI Approved :: MIT License",
Expand All @@ -15,5 +18,53 @@ classifiers = [
]
dynamic = ["version"]

requires-python = ">= 3.9"

dependencies = [
]

[project.urls]
homepage = "https://github.com/carderne/signal-export"
repository = "https://github.com/carderne/signal-export"

[tool.rye]
managed = true
dev-dependencies = [
"maturin>=1.5,<2.0",
"pyright",
"pytest",
]

[tool.maturin]
python-source = "python"
module-name = "bean_rs._bean_rs"
features = ["pyo3/extension-module"]

[tool.ruff]
target-version = "py39"

[tool.ruff.lint]
select = [
"F",
"E",
"I",
"U",
"N",
"E",
"T100",
"A",
"Q",
"ANN",
]

[tool.pyright]
venvPath = "."
venv = ".venv"
extraPaths = ["./python/bean_rs"]
include = ["python"]
reportMissingImports = true
reportMissingParameterType = true
reportUnnecessaryTypeIgnoreComment = true
reportDeprecated = true
pythonVersion = "3.12"
pythonPlatform = "Linux"
7 changes: 7 additions & 0 deletions python/bean_rs/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
"""Python binds to a beancount clone in Rust."""

# The Rust bindings are in `_bean_rs` and we try to mediate all access
# through this file to make typing a bit easier
from bean_rs._bean_rs import load

__all__ = ["load"]
19 changes: 19 additions & 0 deletions python/bean_rs/bean_rs.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import datetime

class Options:
title: str
operating_currency: str

class BeanError(Exception):
pass

class Directive:
date: datetime.date

class Ledger:
dirs: list[Directive]
errs: list[BeanError]
opts: Options

def load(path: str) -> Ledger:
pass
Empty file added python/bean_rs/py.typed
Empty file.
6 changes: 6 additions & 0 deletions python/tests/test_load.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from bean_rs import load


def test_load() -> None:
ledger = load("example.bean")
assert ledger.opts.operating_currency == "GBP"
23 changes: 23 additions & 0 deletions requirements-dev.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# generated by rye
# use `rye lock` or `rye sync` to update this lockfile
#
# last locked with the following flags:
# pre: false
# features: []
# all-features: false
# with-sources: false

-e file:.
iniconfig==2.0.0
# via pytest
maturin==1.5.1
nodeenv==1.8.0
# via pyright
packaging==24.0
# via pytest
pluggy==1.4.0
# via pytest
pyright==1.1.358
pytest==8.1.1
setuptools==69.5.1
# via nodeenv
10 changes: 10 additions & 0 deletions requirements.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# generated by rye
# use `rye lock` or `rye sync` to update this lockfile
#
# last locked with the following flags:
# pre: false
# features: []
# all-features: false
# with-sources: false

-e file:.
7 changes: 4 additions & 3 deletions src/error.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use pyo3::pyclass;
use std::fmt;

use crate::data::{DebugLine, Directive};
Expand All @@ -16,10 +17,10 @@ pub enum ErrorType {
InvalidCcy,
}

#[allow(dead_code)]
#[derive(Debug)]
#[pyclass]
#[derive(Clone, Debug)]
pub struct BeanError {
pub ty: ErrorType, // not yet used anywhere
pub ty: ErrorType,
pub debug: DebugLine,
pub msg: String,
}
Expand Down
1 change: 1 addition & 0 deletions src/ledger.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use crate::error::BeanError;
#[pyclass]
pub struct Ledger {
pub dirs: Vec<Directive>,
#[pyo3(get)]
pub errs: Vec<BeanError>,
#[pyo3(get)]
pub opts: Options,
Expand Down
5 changes: 3 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,15 @@ pub fn balance(path: &str) -> (AccBal, Vec<BeanError>) {

/// Load the ledger from Python
#[pyfunction]
#[pyo3(name = "load")]
fn py_load(path: &str) -> Ledger {
let text = std::fs::read_to_string(path).expect("cannot read file");
load(text)
}

/// `bean_rs` importable from Python
/// `_bean_rs` importable from Python
#[pymodule]
fn bean_rs(m: &Bound<'_, PyModule>) -> PyResult<()> {
fn _bean_rs(m: &Bound<'_, PyModule>) -> PyResult<()> {
m.add_function(wrap_pyfunction!(py_load, m)?)?;
Ok(())
}

0 comments on commit 9cb47be

Please sign in to comment.