Skip to content

Commit 9b6c73e

Browse files
committed
Apply all changes from y-crdt#156
1 parent b9241a9 commit 9b6c73e

18 files changed

+385
-414
lines changed

.gitignore

+2-1
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,5 @@ Cargo.lock
99
docs/_*
1010
.DS_Store
1111
*.pyc
12-
dist
12+
dist
13+
.idea

Cargo.toml

+4-2
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,17 @@ version = "0.7.0-alpha.1"
44
rust-version = "1.72"
55
edition = "2021"
66

7+
[features]
8+
sync = []
9+
710
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
811

912
[lib]
1013
name = "y_py"
1114
crate-type = ["cdylib"]
1215

1316
[dependencies]
14-
lib0 = "0.16.10"
15-
yrs = "0.16.10"
17+
yrs = "0.21.3"
1618

1719
[dependencies.pyo3]
1820
version = "0.19.2"

pyproject.toml

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ build-backend = "maturin"
55
[project]
66
name = "y-py"
77
description = "Python bindings for the Y-CRDT built from yrs (Rust)"
8+
dynamic = ["version"]
89
license = { file = "LICENSE" }
910
authors = [
1011
{ name = "John Waidhofer", email = "[email protected]" },

src/json_builder.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::{collections::HashMap, convert::TryFrom};
22

3-
use lib0::any::Any;
43
use pyo3::{exceptions::PyTypeError, PyErr, PyObject, PyResult, Python};
4+
use yrs::Any;
55

66
use crate::shared_types::{CompatiblePyType, YPyType};
77

src/shared_types.rs

+8-11
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use std::{
1616
rc::Rc,
1717
};
1818
use yrs::types::TypeRef;
19-
use yrs::SubscriptionId;
19+
use yrs::Subscription;
2020

2121
// Common errors
2222
create_exception!(y_py, PreliminaryObservationException, PyException, "Occurs when an observer is attached to a Y type that is not integrated into a YDoc. Y types can only be observed once they have been added to a YDoc.");
@@ -45,17 +45,14 @@ impl DefaultPyErr for IntegratedOperationException {
4545
}
4646

4747
#[pyclass]
48-
#[derive(Clone, Copy)]
49-
pub struct ShallowSubscription(pub SubscriptionId);
50-
#[pyclass]
51-
#[derive(Clone, Copy)]
52-
pub struct DeepSubscription(pub SubscriptionId);
48+
#[cfg(feature = "sync")]
49+
#[derive(Clone)]
50+
pub struct ObservationId(pub Subscription);
5351

54-
#[derive(FromPyObject)]
55-
pub enum SubId {
56-
Shallow(ShallowSubscription),
57-
Deep(DeepSubscription),
58-
}
52+
#[pyclass(unsendable)]
53+
#[cfg(not(feature = "sync"))]
54+
#[derive(Clone)]
55+
pub struct ObservationId(pub Subscription);
5956

6057
#[derive(Clone)]
6158
pub enum CompatiblePyType<'a> {

src/type_conversions.rs

+17-16
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
use lib0::any::Any;
21
use pyo3::create_exception;
32
use pyo3::exceptions::PyException;
43
use pyo3::exceptions::PyTypeError;
@@ -13,13 +12,15 @@ use std::ops::Deref;
1312
use std::rc::Rc;
1413
use yrs::block::Unused;
1514
use yrs::block::{ItemContent, Prelim};
15+
use yrs::branch::{Branch, BranchPtr};
1616
use yrs::types::Events;
17-
use yrs::types::{Attrs, Branch, BranchPtr, Change, Delta, Value};
17+
use yrs::types::{Attrs, Change, Delta};
18+
use yrs::Any;
1819
use yrs::ArrayRef;
1920
use yrs::MapRef;
2021
use yrs::TextRef;
2122
use yrs::TransactionMut;
22-
use yrs::{Array, Map, Text};
23+
use yrs::{Array, Map, Out, Text};
2324

2425
use crate::shared_types::CompatiblePyType;
2526
use crate::shared_types::TypeWithDoc;
@@ -131,7 +132,7 @@ impl WithDocToPython for &Attrs {
131132
let o = pytypes::PyDict::new(py);
132133
for (key, value) in self.iter() {
133134
let key = key.as_ref();
134-
let value = Value::Any(value.clone()).with_doc_into_py(doc.clone(), py);
135+
let value = Out::Any(value.clone()).with_doc_into_py(doc.clone(), py);
135136
o.set_item(key, value).unwrap();
136137
}
137138
o.into()
@@ -311,7 +312,7 @@ impl<'a> TryFrom<CompatiblePyType<'a>> for Any {
311312
const MAX_JS_NUMBER: i64 = 2_i64.pow(53) - 1;
312313
match py_type {
313314
CompatiblePyType::Bool(b) => Ok(Any::Bool(b.extract()?)),
314-
CompatiblePyType::String(s) => Ok(Any::String(s.extract::<String>()?.into_boxed_str())),
315+
CompatiblePyType::String(s) => Ok(Any::String(s.extract::<String>()?.into())),
315316
CompatiblePyType::Int(i) => {
316317
let num: i64 = i.extract()?;
317318
if num > MAX_JS_NUMBER {
@@ -326,7 +327,7 @@ impl<'a> TryFrom<CompatiblePyType<'a>> for Any {
326327
.into_iter()
327328
.map(|py_any|CompatiblePyType::try_from(py_any)?.try_into())
328329
.collect();
329-
result.map(|res| Any::Array(res.into_boxed_slice()))
330+
result.map(|res| Any::Array(res.into()))
330331
},
331332
CompatiblePyType::Dict(d) => {
332333
let result: PyResult<HashMap<String, Any>> = d
@@ -337,7 +338,7 @@ impl<'a> TryFrom<CompatiblePyType<'a>> for Any {
337338
Ok((key, value))
338339
})
339340
.collect();
340-
result.map(|res| Any::Map(Box::new(res)))
341+
result.map(|res| Any::Map(Box::new(res).into()))
341342
},
342343
CompatiblePyType::None => Ok(Any::Null),
343344
CompatiblePyType::YType(v) => Err(MultipleIntegrationError::new_err(format!(
@@ -416,17 +417,17 @@ impl ToPython for Any {
416417
}
417418
}
418419

419-
impl WithDocToPython for Value {
420+
impl WithDocToPython for Out {
420421
fn with_doc_into_py(self, doc: Rc<RefCell<YDocInner>>, py: Python) -> PyObject {
421422
match self {
422-
Value::Any(v) => v.into_py(py),
423-
Value::YText(v) => v.with_doc(doc).into_py(py),
424-
Value::YArray(v) => v.with_doc(doc).into_py(py),
425-
Value::YMap(v) => v.with_doc(doc).into_py(py),
426-
Value::YXmlElement(v) => v.with_doc(doc).into_py(py),
427-
Value::YXmlText(v) => v.with_doc(doc).into_py(py),
428-
Value::YXmlFragment(v) => v.with_doc(doc).into_py(py),
429-
Value::YDoc(_) => py.None(),
423+
Out::Any(v) => v.into_py(py),
424+
Out::YText(v) => v.with_doc(doc).into_py(py),
425+
Out::YArray(v) => v.with_doc(doc).into_py(py),
426+
Out::YMap(v) => v.with_doc(doc).into_py(py),
427+
Out::YXmlElement(v) => v.with_doc(doc).into_py(py),
428+
Out::YXmlText(v) => v.with_doc(doc).into_py(py),
429+
Out::YXmlFragment(v) => v.with_doc(doc).into_py(py),
430+
_ => py.None(),
430431
}
431432
}
432433
}

src/y_array.rs

+37-42
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,26 @@
1-
use std::cell::RefCell;
2-
use std::convert::{TryFrom, TryInto};
3-
use std::rc::Rc;
4-
51
use crate::json_builder::JsonBuilder;
62
use crate::shared_types::{
7-
CompatiblePyType, DeepSubscription, DefaultPyErr, PreliminaryObservationException,
8-
ShallowSubscription, SubId, TypeWithDoc,
3+
CompatiblePyType, DefaultPyErr, ObservationId, PreliminaryObservationException, TypeWithDoc,
94
};
105
use crate::type_conversions::{events_into_py, WithDocToPython};
116
use crate::y_doc::{WithDoc, YDocInner};
127
use crate::y_transaction::{YTransaction, YTransactionInner};
8+
use std::cell::RefCell;
9+
use std::clone::Clone;
10+
use std::convert::{TryFrom, TryInto};
11+
use std::rc::Rc;
12+
use std::string::ToString;
1313

1414
use super::shared_types::SharedType;
1515
use crate::type_conversions::ToPython;
16-
use lib0::any::Any;
1716
use pyo3::exceptions::PyIndexError;
1817

1918
use crate::type_conversions::PyObjectWrapper;
2019
use pyo3::prelude::*;
2120
use pyo3::types::{PyList, PySlice, PySliceIndices};
2221
use yrs::types::array::ArrayEvent;
2322
use yrs::types::{DeepObservable, ToJson};
24-
use yrs::{Array, ArrayRef, Assoc, Observable, SubscriptionId, TransactionMut};
23+
use yrs::{Any, Array, ArrayRef, Assoc, Observable, TransactionMut};
2524

2625
/// A collection used to store data in an indexed sequence structure. This type is internally
2726
/// implemented as a double linked list, which may squash values inserted directly one after another
@@ -365,59 +364,55 @@ impl YArray {
365364

366365
/// Subscribes to all operations happening over this instance of `YArray`. All changes are
367366
/// batched and eventually triggered during transaction commit phase.
368-
/// Returns a `SubscriptionId` which can be used to cancel the callback with `unobserve`.
369-
pub fn observe(&mut self, f: PyObject) -> PyResult<ShallowSubscription> {
367+
/// Returns a `ObservationId` which can be used to cancel the callback with `unobserve`.
368+
pub fn observe(&mut self, f: PyObject) -> PyResult<ObservationId> {
370369
match &mut self.0 {
371370
SharedType::Integrated(array) => {
372371
let doc = array.doc.clone();
373-
let sub: SubscriptionId = array
374-
.inner
375-
.observe(move |txn, e| {
376-
Python::with_gil(|py| {
377-
let event = YArrayEvent::new(e, txn, doc.clone());
378-
if let Err(err) = f.call1(py, (event,)) {
379-
err.restore(py)
380-
}
381-
})
372+
let subscription = array.inner.observe(move |txn, e| {
373+
Python::with_gil(|py| {
374+
let event = YArrayEvent::new(e, txn, doc.clone());
375+
if let Err(err) = f.call1(py, (event,)) {
376+
err.restore(py)
377+
}
382378
})
383-
.into();
384-
Ok(ShallowSubscription(sub))
379+
});
380+
Ok(ObservationId(subscription))
385381
}
386382
SharedType::Prelim(_) => Err(PreliminaryObservationException::default_message()),
387383
}
388384
}
389385
/// Observes YArray events and events of all child elements.
390-
pub fn observe_deep(&mut self, f: PyObject) -> PyResult<DeepSubscription> {
386+
pub fn observe_deep(&mut self, f: PyObject) -> PyResult<ObservationId> {
391387
match &mut self.0 {
392388
SharedType::Integrated(array) => {
393389
let doc = array.doc.clone();
394-
let sub: SubscriptionId = array
395-
.inner
396-
.observe_deep(move |txn, events| {
397-
Python::with_gil(|py| {
398-
let events = events_into_py(txn, events, doc.clone());
399-
if let Err(err) = f.call1(py, (events,)) {
400-
err.restore(py)
401-
}
402-
})
390+
let subscription = array.inner.observe_deep(move |txn, events| {
391+
Python::with_gil(|py| {
392+
let events = events_into_py(txn, events, doc.clone());
393+
if let Err(err) = f.call1(py, (events,)) {
394+
err.restore(py)
395+
}
403396
})
404-
.into();
405-
Ok(DeepSubscription(sub))
397+
});
398+
Ok(ObservationId(subscription))
406399
}
407400
SharedType::Prelim(_) => Err(PreliminaryObservationException::default_message()),
408401
}
409402
}
410403

411-
/// Cancels the callback of an observer using the Subscription ID returned from the `observe` method.
412-
pub fn unobserve(&mut self, subscription_id: SubId) -> PyResult<()> {
404+
/// Cancels the callback of an observer using the `observation_d` returned from the `observe` method.
405+
pub fn unobserve(&mut self, observation_d: ObservationId) -> PyResult<()> {
413406
match &mut self.0 {
414-
SharedType::Integrated(arr) => {
415-
match subscription_id {
416-
SubId::Shallow(ShallowSubscription(id)) => arr.unobserve(id),
417-
SubId::Deep(DeepSubscription(id)) => arr.unobserve_deep(id),
418-
}
419-
Ok(())
420-
}
407+
SharedType::Integrated(_) => Ok(drop(observation_d.0)),
408+
SharedType::Prelim(_) => Err(PreliminaryObservationException::default_message()),
409+
}
410+
}
411+
412+
/// Cancels the callback of an observer using the `observation_d` returned from the `observe_deep` method.
413+
pub fn unobserve_deep(&mut self, observation_d: ObservationId) -> PyResult<()> {
414+
match &mut self.0 {
415+
SharedType::Integrated(_) => Ok(drop(observation_d.0)),
421416
SharedType::Prelim(_) => Err(PreliminaryObservationException::default_message()),
422417
}
423418
}

0 commit comments

Comments
 (0)