Python-OTType
A python library for Operational Transformation (OT). Basic idea follows the spec at https://github.com/ottypes/docs.
Supported Python versions : CPython 3.9 - 3.13, PyPy 3.10 - 3.11
Installation
pip install python-ottype
Basic usage:
import ottype
assert ottype.apply('asdf', [3, '123', {'d':'f'}]) == 'asd123'
OT Operations
Skip
Object type : int
Skip n characters from the current position is represented as n
assert apply('asdf', [3]) == 'asdf'
Insert
Object type : str
Insert a string s at the current position is represented as s
assert apply('asdf', ['qwer']) == 'qwerasdf'
assert apply('asdf', [2, 'qwer']) == 'asqwerdf'
Delete
Object type : dict
Delete a string s at the current position is represented as {'d': s}
assert apply('asdf', [{'d': 'as'}]) == 'df'
assert apply('asdf', [1, {'d': 'sd'}]) == 'af'
Supported Functions
OT = int | str | dict[str, str]
check(ots: Sequence[OT], *, check_unoptimized: bool = True) -> bool
Check the sequence if it only contains valid OTs. If check_unoptimized is True, only normalized sequence of OTs is accepted.
assert check(['a', 4, 'b'])
assert not check(['a', 'b']) # is not normalized
assert not check([3]) # is not normalized
apply(doc: str, ots: Sequence[OT], *, check_unoptimized: bool = True) -> str
Apply a sequence of OTs to a string.
assert apply('abcde', [2, 'qq', {'d': 'c'}, 1, 'w']) == 'abqqdwe'
inverse_apply(doc: str, ots: Sequence[OT], *, check_unoptimized: bool = True) -> str
Inversely apply a sequence of OTs to a string.
assert inverse_apply(apply(doc, ots), ots) == doc
normalize(ots: Sequence[OT]) -> Sequence[OT]
Normalize a sequence of OTs : merge consecutive OTs and trim the last skip operation.
assert normalize([1, 2, 'as', 'df', {'d': 'qw'}, {'d': 'er'}, 3]) \
== [3, 'asdf', {'d': 'qwer'}]
transform(ots1: Sequence[OT], ots2: Sequence[OT]) -> Sequence[OT]
Transform a sequence of OTs with the property:
assert apply(apply(doc, ots1), transform(ots2, ots1, 'left')) \
== apply(apply(doc, ots2), transform(ots1, ots2, 'right'))
compose(ots1: Sequence[OT], ots2: Sequence[OT]) -> Sequence[OT]
Compose two sequences of OTs with the property:
assert apply(apply(doc, ots1), ots2) == apply(doc, compose(ots1, ots2))
diff(doc1: str, doc2: str) -> Sequence[OT]
Generate a sequence of OTs required to change doc1 to doc2:
assert apply(doc1, diff(doc1, doc2)) == doc2
Benchmark (at CPython 3.12.1)
Benchmark : apply operation
| len(doc) | len(ots) | python (Kops/s) | cython (Kops/s) |
|---|---|---|---|
| 100 | 5 | 289.58 ( 1.00x) | 663.47 ( 2.29x) |
| 100 | 10 | 206.50 ( 1.00x) | 513.00 ( 2.48x) |
| 100 | 20 | 114.52 ( 1.00x) | 298.82 ( 2.61x) |
| 100 | 50 | 48.37 ( 1.00x) | 127.90 ( 2.64x) |
| 100 | 100 | 26.96 ( 1.00x) | 71.84 ( 2.66x) |
| 1000 | 5 | 412.41 ( 1.00x) | 974.43 ( 2.36x) |
| 1000 | 10 | 220.19 ( 1.00x) | 493.53 ( 2.24x) |
| 1000 | 20 | 128.66 ( 1.00x) | 317.18 ( 2.47x) |
| 1000 | 50 | 37.56 ( 1.00x) | 98.56 ( 2.62x) |
| 1000 | 100 | 23.43 ( 1.00x) | 64.25 ( 2.74x) |
| 10000 | 5 | 203.14 ( 1.00x) | 322.31 ( 1.59x) |
| 10000 | 10 | 142.25 ( 1.00x) | 279.79 ( 1.97x) |
| 10000 | 20 | 95.63 ( 1.00x) | 202.97 ( 2.12x) |
| 10000 | 50 | 48.58 ( 1.00x) | 122.09 ( 2.51x) |
| 10000 | 100 | 21.17 ( 1.00x) | 57.59 ( 2.72x) |
Benchmark : inverse_apply operation
| len(doc) | len(ots) | python (Kops/s) | cython (Kops/s) |
|---|---|---|---|
| 100 | 5 | 194.12 ( 1.00x) | 408.56 ( 2.10x) |
| 100 | 10 | 113.27 ( 1.00x) | 269.10 ( 2.38x) |
| 100 | 20 | 60.99 ( 1.00x) | 150.49 ( 2.47x) |
| 100 | 50 | 26.35 ( 1.00x) | 64.27 ( 2.44x) |
| 100 | 100 | 16.62 ( 1.00x) | 42.87 ( 2.58x) |
| 1000 | 5 | 309.57 ( 1.00x) | 565.47 ( 1.83x) |
| 1000 | 10 | 153.62 ( 1.00x) | 351.55 ( 2.29x) |
| 1000 | 20 | 69.48 ( 1.00x) | 162.52 ( 2.34x) |
| 1000 | 50 | 37.12 ( 1.00x) | 91.88 ( 2.48x) |
| 1000 | 100 | 17.06 ( 1.00x) | 42.51 ( 2.49x) |
| 10000 | 5 | 145.11 ( 1.00x) | 257.81 ( 1.78x) |
| 10000 | 10 | 96.66 ( 1.00x) | 198.97 ( 2.06x) |
| 10000 | 20 | 65.18 ( 1.00x) | 140.90 ( 2.16x) |
| 10000 | 50 | 27.40 ( 1.00x) | 67.74 ( 2.47x) |
| 10000 | 100 | 13.53 ( 1.00x) | 32.23 ( 2.38x) |
Release files for python-ottype 25.7.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| python_ottype-25.7.0.tar.gz | 12.2 kB | Details |
Built distributions (wheels)
Total release size: 3.1 MB
Release files / python_ottype-25.7.0.tar.gz
| Download URL | python_ottype-25.7.0.tar.gz |
|---|---|
| Size | 12.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
3a3dac2accd7cae8c9a5216d59fdf50d8e94113cffc7c0791f0f4245c6c21f15
|
|
BLAKE2b-256 checksum How to use checksums |
81ebe24d6e8d810a87dd8a13891847f122db6dda3c80791e8794af38d6828df3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.12.1
|
Release files / python_ottype-25.7.0-pp311-pypy311_pp73-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl
| Download URL | python_ottype-25.7.0-pp311-pypy311_pp73-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl |
|---|---|
| Size | 185.9 kB |
| Tags | Linux glibc 2.17+ x86-64 Linux glibc 2.5+ x86-64 PyPy 3.11 PyPy 3.11 7.3 |
|
SHA-256 checksum How to use checksums |
292959aa9e49de780b20b169ec536e3d54d981b69527d6753b28dbe5c0fdc63a
|
|
BLAKE2b-256 checksum How to use checksums |
59c83313a21f5adc6bb1cce75c78a16cd1493210d163b651bb026ec00b53697f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.12.1
|
Release files / python_ottype-25.7.0-pp310-pypy310_pp73-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl
| Download URL | python_ottype-25.7.0-pp310-pypy310_pp73-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl |
|---|---|
| Size | 184.1 kB |
| Tags | Linux glibc 2.17+ x86-64 Linux glibc 2.5+ x86-64 PyPy 3.10 PyPy 3.10 7.3 |
|
SHA-256 checksum How to use checksums |
2b80fc3343139d04b9e40d6820010abf9d2fbe23b0973214b1ea812595558745
|
|
BLAKE2b-256 checksum How to use checksums |
d03215923079296911107a235d616742b95271682656732e9eb991d4f6ebfa15
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.12.1
|
Release files / python_ottype-25.7.0-cp313-cp313-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl
| Download URL | python_ottype-25.7.0-cp313-cp313-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl |
|---|---|
| Size | 534.4 kB |
| Tags | CPython 3.13 Linux glibc 2.17+ x86-64 Linux glibc 2.5+ x86-64 |
|
SHA-256 checksum How to use checksums |
8532f0f3f54cf12aaa0b1888bc604fa82fe941c352b6a02e4da6af0e93020d0d
|
|
BLAKE2b-256 checksum How to use checksums |
a9a654950696e769b30d4d52c7f750145dab2b6f1bfb2b48ab259efefa8ada44
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.12.1
|
Release files / python_ottype-25.7.0-cp312-cp312-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl
| Download URL | python_ottype-25.7.0-cp312-cp312-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl |
|---|---|
| Size | 542.0 kB |
| Tags | CPython 3.12 Linux glibc 2.17+ x86-64 Linux glibc 2.5+ x86-64 |
|
SHA-256 checksum How to use checksums |
f9da7865139104444b9ddbb4c4368a925ae35256e10d0c02c6538620443678e5
|
|
BLAKE2b-256 checksum How to use checksums |
e6dc1a4717b3262f7a07fd27f48eabd4ee63ad5c1fc9dda1a28f0e9922c2804b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.12.1
|
Release files / python_ottype-25.7.0-cp311-cp311-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl
| Download URL | python_ottype-25.7.0-cp311-cp311-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl |
|---|---|
| Size | 555.0 kB |
| Tags | CPython 3.11 Linux glibc 2.17+ x86-64 Linux glibc 2.5+ x86-64 |
|
SHA-256 checksum How to use checksums |
26300c10f849bf7a00ec24fd416c7289cb0bce15110cf7b69f2f32be6e6fe5c8
|
|
BLAKE2b-256 checksum How to use checksums |
b549e677c1c5eabd9118f6565fb45f62eb19e9bafe2baf67cc8adfe70c9161d4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.12.1
|
Release files / python_ottype-25.7.0-cp310-cp310-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl
| Download URL | python_ottype-25.7.0-cp310-cp310-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl |
|---|---|
| Size | 527.4 kB |
| Tags | CPython 3.10 Linux glibc 2.17+ x86-64 Linux glibc 2.5+ x86-64 |
|
SHA-256 checksum How to use checksums |
59a79ec503e964854f978c36029a494e3c7f390551b239f8f4dc14d1804c159c
|
|
BLAKE2b-256 checksum How to use checksums |
818ca7b766df7346fe01dedf082377d3e05521398d39f74e82992223526e6130
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.12.1
|
Release files / python_ottype-25.7.0-cp39-cp39-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl
| Download URL | python_ottype-25.7.0-cp39-cp39-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl |
|---|---|
| Size | 528.0 kB |
| Tags | CPython 3.9 Linux glibc 2.17+ x86-64 Linux glibc 2.5+ x86-64 |
|
SHA-256 checksum How to use checksums |
1990264b14ee36ea255e404d0c5ed33f2d4db767dbbbf5c7d6bca440929c855d
|
|
BLAKE2b-256 checksum How to use checksums |
56e0eaf7d773623a2a31b3703fbbe368d0e656ae584351cba4c40eb4d21b7fec
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.12.1
|