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
26 changes: 13 additions & 13 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "loro_py"
version = "1.10.3"
version = "1.13.1"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
Expand All @@ -9,7 +9,7 @@ name = "loro"
crate-type = ["cdylib"]

[dependencies]
loro = { version = "1.10.3", features = ["counter", "jsonpath"] }
loro = { version = "1.13.1", features = ["counter", "jsonpath"] }
rustc-hash = "2.1.1"
pyo3 = { version = "0.26.0" }
serde_json = "1"
62 changes: 62 additions & 0 deletions loro.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,16 @@ class LoroDoc:
"""
...

def try_get_movable_list(
self, obj: ContainerId
) -> typing.Optional[LoroMovableList]:
r"""
Try to get a [LoroMovableList] by container id.

Returns `None` if the container does not exist.
"""
...

def get_list(self, obj: ContainerId) -> LoroList:
r"""
Get a [LoroList] by container id.
Expand All @@ -433,6 +443,14 @@ class LoroDoc:
"""
...

def try_get_list(self, obj: ContainerId) -> typing.Optional[LoroList]:
r"""
Try to get a [LoroList] by container id.

Returns `None` if the container does not exist.
"""
...

def get_map(self, obj: ContainerId) -> LoroMap:
r"""
Get a [LoroMap] by container id.
Expand All @@ -441,6 +459,14 @@ class LoroDoc:
"""
...

def try_get_map(self, obj: ContainerId) -> typing.Optional[LoroMap]:
r"""
Try to get a [LoroMap] by container id.

Returns `None` if the container does not exist.
"""
...

def get_text(self, obj: ContainerId) -> LoroText:
r"""
Get a [LoroText] by container id.
Expand All @@ -449,6 +475,14 @@ class LoroDoc:
"""
...

def try_get_text(self, obj: ContainerId) -> typing.Optional[LoroText]:
r"""
Try to get a [LoroText] by container id.

Returns `None` if the container does not exist.
"""
...

def get_tree(self, obj: ContainerId) -> LoroTree:
r"""
Get a [LoroTree] by container id.
Expand All @@ -457,6 +491,14 @@ class LoroDoc:
"""
...

def try_get_tree(self, obj: ContainerId) -> typing.Optional[LoroTree]:
r"""
Try to get a [LoroTree] by container id.

Returns `None` if the container does not exist.
"""
...

def get_counter(self, obj: typing.Any) -> LoroCounter:
r"""
Get a [LoroCounter] by container id.
Expand All @@ -465,6 +507,14 @@ class LoroDoc:
"""
...

def try_get_counter(self, obj: typing.Any) -> typing.Optional[LoroCounter]:
r"""
Try to get a [LoroCounter] by container id.

Returns `None` if the container does not exist.
"""
...

def commit(self) -> None:
r"""
Commit the cumulative auto commit transaction.
Expand Down Expand Up @@ -1306,6 +1356,18 @@ class LoroMap:
"""
...

def ensure_mergeable_list(self, key: str) -> LoroList: ...

def ensure_mergeable_map(self, key: str) -> LoroMap: ...

def ensure_mergeable_tree(self, key: str) -> LoroTree: ...

def ensure_mergeable_movable_list(self, key: str) -> LoroMovableList: ...

def ensure_mergeable_text(self, key: str) -> LoroText: ...

def ensure_mergeable_counter(self, key: str) -> LoroCounter: ...

def clear(self) -> None:
r"""
Delete all key-value pairs in the map.
Expand Down
26 changes: 25 additions & 1 deletion src/container/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use crate::{
value::{ContainerID, LoroValue, ValueOrContainer},
};

use super::Container;
use super::{Container, LoroCounter, LoroList, LoroMovableList, LoroText, LoroTree};

pub fn register_class(m: &Bound<'_, PyModule>) -> PyResult<()> {
m.add_class::<LoroMap>()?;
Expand Down Expand Up @@ -150,6 +150,30 @@ impl LoroMap {
Ok(container.into())
}

pub fn ensure_mergeable_list(&self, key: &str) -> PyLoroResult<LoroList> {
Ok(LoroList(self.0.ensure_mergeable_list(key)?))
}

pub fn ensure_mergeable_map(&self, key: &str) -> PyLoroResult<LoroMap> {
Ok(LoroMap(self.0.ensure_mergeable_map(key)?))
}

pub fn ensure_mergeable_tree(&self, key: &str) -> PyLoroResult<LoroTree> {
Ok(LoroTree(self.0.ensure_mergeable_tree(key)?))
}

pub fn ensure_mergeable_movable_list(&self, key: &str) -> PyLoroResult<LoroMovableList> {
Ok(LoroMovableList(self.0.ensure_mergeable_movable_list(key)?))
}

pub fn ensure_mergeable_text(&self, key: &str) -> PyLoroResult<LoroText> {
Ok(LoroText(self.0.ensure_mergeable_text(key)?))
}

pub fn ensure_mergeable_counter(&self, key: &str) -> PyLoroResult<LoroCounter> {
Ok(LoroCounter(self.0.ensure_mergeable_counter(key)?))
}

/// Delete all key-value pairs in the map.
pub fn clear(&self) -> PyLoroResult<()> {
self.0.clear()?;
Expand Down
83 changes: 74 additions & 9 deletions src/doc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,9 @@ impl LoroDoc {
/// Fork the document at the given frontiers.
///
/// The created doc will only contain the history before the specified frontiers.
pub fn fork_at(&self, frontiers: &Frontiers) -> Self {
let new_doc = self.doc.fork_at(&frontiers.into());
Self { doc: new_doc }
pub fn fork_at(&self, frontiers: &Frontiers) -> PyLoroResult<Self> {
let new_doc = self.doc.fork_at(&frontiers.into())?;
Ok(Self { doc: new_doc })
}

/// Get the configurations of the document.
Expand Down Expand Up @@ -287,6 +287,21 @@ impl LoroDoc {
Ok(LoroMovableList(self.doc.get_movable_list(container_id)))
}

/// Try to get a [LoroMovableList] by container id.
///
/// Returns `None` if the container does not exist.
#[inline]
pub fn try_get_movable_list(
&self,
obj: &Bound<'_, PyAny>,
) -> PyResult<Option<LoroMovableList>> {
let container_id = pyobject_to_container_id(obj, ContainerType::MovableList {})?;
Ok(self
.doc
.try_get_movable_list(container_id)
.map(LoroMovableList))
}

/// Get a [LoroList] by container id.
///
/// If the provided id is string, it will be converted into a root container id with the name of the string.
Expand All @@ -296,6 +311,15 @@ impl LoroDoc {
Ok(LoroList(self.doc.get_list(container_id)))
}

/// Try to get a [LoroList] by container id.
///
/// Returns `None` if the container does not exist.
#[inline]
pub fn try_get_list(&self, obj: &Bound<'_, PyAny>) -> PyResult<Option<LoroList>> {
let container_id = pyobject_to_container_id(obj, ContainerType::List {})?;
Ok(self.doc.try_get_list(container_id).map(LoroList))
}

/// Get a [LoroMap] by container id.
///
/// If the provided id is string, it will be converted into a root container id with the name of the string.
Expand All @@ -305,6 +329,15 @@ impl LoroDoc {
Ok(LoroMap(self.doc.get_map(container_id)))
}

/// Try to get a [LoroMap] by container id.
///
/// Returns `None` if the container does not exist.
#[inline]
pub fn try_get_map(&self, obj: &Bound<'_, PyAny>) -> PyResult<Option<LoroMap>> {
let container_id = pyobject_to_container_id(obj, ContainerType::Map {})?;
Ok(self.doc.try_get_map(container_id).map(LoroMap))
}

/// Get a [LoroText] by container id.
///
/// If the provided id is string, it will be converted into a root container id with the name of the string.
Expand All @@ -314,6 +347,15 @@ impl LoroDoc {
Ok(LoroText(self.doc.get_text(container_id)))
}

/// Try to get a [LoroText] by container id.
///
/// Returns `None` if the container does not exist.
#[inline]
pub fn try_get_text(&self, obj: &Bound<'_, PyAny>) -> PyResult<Option<LoroText>> {
let container_id = pyobject_to_container_id(obj, ContainerType::Text {})?;
Ok(self.doc.try_get_text(container_id).map(LoroText))
}

/// Get a [LoroTree] by container id.
///
/// If the provided id is string, it will be converted into a root container id with the name of the string.
Expand All @@ -323,6 +365,15 @@ impl LoroDoc {
Ok(LoroTree(self.doc.get_tree(container_id)))
}

/// Try to get a [LoroTree] by container id.
///
/// Returns `None` if the container does not exist.
#[inline]
pub fn try_get_tree(&self, obj: &Bound<'_, PyAny>) -> PyResult<Option<LoroTree>> {
let container_id = pyobject_to_container_id(obj, ContainerType::Tree {})?;
Ok(self.doc.try_get_tree(container_id).map(LoroTree))
}

/// Get a [LoroCounter] by container id.
///
/// If the provided id is string, it will be converted into a root container id with the name of the string.
Expand All @@ -332,6 +383,15 @@ impl LoroDoc {
Ok(LoroCounter(self.doc.get_counter(container_id)))
}

/// Try to get a [LoroCounter] by container id.
///
/// Returns `None` if the container does not exist.
#[inline]
pub fn try_get_counter(&self, obj: &Bound<'_, PyAny>) -> PyResult<Option<LoroCounter>> {
let container_id = pyobject_to_container_id(obj, ContainerType::Counter {})?;
Ok(self.doc.try_get_counter(container_id).map(LoroCounter))
}

/// Commit the cumulative auto commit transaction.
///
/// There is a transaction behind every operation.
Expand Down Expand Up @@ -872,14 +932,19 @@ impl LoroDoc {
///
/// The callback may fire false positives; it is intended as a lightweight notification so
/// callers can debounce or throttle before running an expensive JSONPath query themselves.
pub fn subscribe_jsonpath(&self, path: &str, callback: Py<PyAny>) -> PyLoroResult<Subscription> {
let subscription = self
.doc
.subscribe_jsonpath(path, Arc::new(move || {
pub fn subscribe_jsonpath(
&self,
path: &str,
callback: Py<PyAny>,
) -> PyLoroResult<Subscription> {
let subscription = self.doc.subscribe_jsonpath(
path,
Arc::new(move || {
Python::attach(|py| {
callback.call0(py).unwrap();
});
}))?;
}),
)?;
Ok(subscription.into())
}

Expand Down Expand Up @@ -1124,7 +1189,7 @@ impl Configure {
}

pub fn text_style_config(&self) -> StyleConfigMap {
StyleConfigMap(self.0.text_style_config().read().unwrap().clone())
StyleConfigMap(self.0.text_style_config().read().clone())
}

pub fn record_timestamp(&self) -> bool {
Expand Down
Loading
Loading