Skip to content

Commit

Permalink
Store YBlob as bytes, not base64-encoded string (#209)
Browse files Browse the repository at this point in the history
* Store YBlob as bytes, not base64-encoded string

* Add test

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Automatic application of license header

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
  • Loading branch information
3 people authored Jan 5, 2024
1 parent 947c46e commit fc99cca
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 14 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -147,3 +147,5 @@ jupyter_ydoc/_version.py
!.yarn/versions
docs/source/api
docs/source/changelog.md
# pixi environments
.pixi
20 changes: 7 additions & 13 deletions jupyter_ydoc/yblob.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
# Copyright (c) Jupyter Development Team.
# Distributed under the terms of the Modified BSD License.

import base64
from functools import partial
from typing import Any, Callable, Optional, Union
from typing import Any, Callable, Optional

from pycrdt import Doc, Map

Expand All @@ -13,10 +12,7 @@
class YBlob(YBaseDoc):
"""
Extends :class:`YBaseDoc`, and represents a blob document.
It is currently encoded as base64 because of:
https://github.com/y-crdt/ypy/issues/108#issuecomment-1377055465
The Y document can be set from bytes or from str, in which case it is assumed to be encoded as
base64.
The Y document is set from bytes.
Schema:
Expand Down Expand Up @@ -46,7 +42,7 @@ def version(self) -> str:
:return: Document's version.
:rtype: str
"""
return "1.0.0"
return "2.0.0"

def get(self) -> bytes:
"""
Expand All @@ -55,18 +51,16 @@ def get(self) -> bytes:
:return: Document's content.
:rtype: bytes
"""
return base64.b64decode(self._ysource.get("base64", "").encode())
return self._ysource.get("bytes", b"")

def set(self, value: Union[bytes, str]) -> None:
def set(self, value: bytes) -> None:
"""
Sets the content of the document.
:param value: The content of the document.
:type value: Union[bytes, str]
:type value: bytes
"""
if isinstance(value, bytes):
value = base64.b64encode(value).decode()
self._ysource["base64"] = value
self._ysource["bytes"] = value

def observe(self, callback: Callable[[str, Any], None]) -> None:
"""
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ requires-python = ">=3.7"
keywords = ["jupyter", "ypy"]
dependencies = [
"importlib_metadata >=3.6; python_version<'3.10'",
"pycrdt >=0.8.1,<0.9.0",
"pycrdt >=0.8.3,<0.9.0",
]

[[project.authors]]
Expand Down
24 changes: 24 additions & 0 deletions tests/test_ydocs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Copyright (c) Jupyter Development Team.
# Distributed under the terms of the Modified BSD License.

from jupyter_ydoc import YBlob


def test_yblob():
yblob = YBlob()
assert yblob.get() == b""
yblob.set(b"012")
assert yblob.get() == b"012"
changes = []

def callback(topic, event):
print(topic, event)
changes.append((topic, event))

yblob.observe(callback)
yblob.set(b"345")
assert len(changes) == 1
topic, event = changes[0]
assert topic == "source"
assert event.keys["bytes"]["oldValue"] == b"012"
assert event.keys["bytes"]["newValue"] == b"345"

0 comments on commit fc99cca

Please sign in to comment.