experiments with Cython

This commit is contained in:
Florian Förster 2025-11-28 15:40:09 +01:00
parent a7e9bc9bc1
commit 245b9532b9
4 changed files with 3469 additions and 1295 deletions

19
pdm.lock generated
View File

@ -5,7 +5,7 @@
groups = ["default", "dev", "lint", "nb", "tests"]
strategy = ["inherit_metadata"]
lock_version = "4.5.0"
content_hash = "sha256:71768c573eb20af8acecbc83c097fa086cd4b05e483dd1da4671252ec7d16329"
content_hash = "sha256:c0680aa00cf7474d542ab72daaea39fe9f3c23b3b68f724f49da67b2d74ff588"
[[metadata.targets]]
requires_python = ">=3.11"
@ -759,6 +759,20 @@ files = [
{file = "distlib-0.4.0.tar.gz", hash = "sha256:feec40075be03a04501a973d81f633735b4b69f98b05450592310c0f401a4e0d"},
]
[[package]]
name = "dopt-basics"
version = "0.2.4"
requires_python = ">=3.11"
summary = "basic cross-project tools for Python-based d-opt projects"
groups = ["default"]
dependencies = [
"tzdata>=2025.1",
]
files = [
{file = "dopt_basics-0.2.4-py3-none-any.whl", hash = "sha256:b7d05b80dde1f856b352580aeac500fc7505e4513ed162791d8735cdc182ebc1"},
{file = "dopt_basics-0.2.4.tar.gz", hash = "sha256:c21fbe183bec5eab4cfd1404e10baca670035801596960822d0019e6e885983f"},
]
[[package]]
name = "execnet"
version = "2.1.2"
@ -2530,8 +2544,7 @@ name = "tzdata"
version = "2025.2"
requires_python = ">=2"
summary = "Provider of IANA time zone data"
groups = ["nb"]
marker = "python_version >= \"3.9\""
groups = ["default", "nb"]
files = [
{file = "tzdata-2025.2-py2.py3-none-any.whl", hash = "sha256:1a403fada01ff9221ca8044d701868fa132215d84beb92242d9acd2147f667a8"},
{file = "tzdata-2025.2.tar.gz", hash = "sha256:b60a638fcc0daffadf82fe0f57e53d06bdec2f36c4df66280ae79bce6bd6f2b9"},

View File

@ -5,7 +5,7 @@ description = "blockchain module of the research project >Polluck<"
authors = [
{name = "d-opt GmbH, resp. Florian Foerster", email = "f.foerster@d-opt.com"},
]
dependencies = []
dependencies = ["dopt-basics>=0.2.4"]
requires-python = ">=3.11"
readme = "README.md"
license = {text = "LicenseRef-Proprietary"}

File diff suppressed because it is too large Load Diff

View File

@ -1,18 +1,47 @@
"""placeholder module for compilation"""
import typing as t
from __future__ import annotations
import datetime
import cython
from cython.cimports.cpython.ref import Py_INCREF
import dopt_basics.datetime
# from cython.cimports.cpython.ref import Py_INCREF, PyObject
PyStringC = cython.struct(
ptr=cython.p_char,
length=cython.Py_ssize_t,
)
@cython.cfunc
def PyStringC_to_unicode(
string: PyStringC,
) -> str:
return string.ptr[: string.length].decode("UTF-8", "strict")
@cython.cfunc
def PyStringC_to_bytes(
string: PyStringC,
) -> bytes:
return cython.cast(bytes, string.ptr[: string.length])
@cython.cfunc
def timestamp_to_datetime(
ts: cython.double,
) -> datetime.datetime:
return datetime.datetime.fromtimestamp(ts, dopt_basics.datetime.TIMEZONE_UTC)
@cython.cclass
class StringHolder:
_data = cython.declare(cython.p_char, visibility="private")
_length = cython.declare(cython.Py_ssize_t, visibility="readonly")
_py_cache = cython.declare(object, visibility="private")
c = cython.declare(PyStringC, visibility="readonly")
_py_data = cython.declare(object, visibility="private")
def __cinit__(self, data: str) -> None:
def __cinit__(self, data: str):
"""accepting Python str
Parameters
@ -23,23 +52,68 @@ class StringHolder:
if not isinstance(data, str):
raise TypeError("Data not 'str'")
tmp = data.encode("utf-8")
Py_INCREF(tmp)
self._data = tmp
self._length = len(tmp)
self._py_cache = None
@cython.cfunc
def _bytes_to_str(self) -> str:
tmp = t.cast(bytes, self._data[: self._length])
return tmp.decode("utf-8")
self._py_data = data.encode("UTF-8")
self.c = PyStringC(self._py_data, len(self._py_data))
@property
def py_string(self) -> str:
if self._py_cache is None:
self._py_cache = self._bytes_to_str()
return t.cast(str, self._py_cache)
def py_string(self):
return PyStringC_to_unicode(self.c)
@property
def py_bytes(self) -> bytes:
return t.cast(bytes, self._data[: self._length])
def py_bytes(self):
return PyStringC_to_bytes(self.c)
# BlockC = cython.struct(
# index=cython.ulonglong,
# timestamp=cython.double,
# data=PyStringC,
# previous_hash=PyStringC,
# nonce=cython.ulonglong,
# )
@cython.cclass
class Block:
_index = cython.declare(cython.ulong, visibility="private")
_timestamp = cython.declare(cython.double, visibility="private")
_data = cython.declare(StringHolder, visibility="private")
_prev_hash = cython.declare(StringHolder, visibility="private")
_nonce = cython.declare(cython.ulong, visibility="private")
def __init__(
self,
index: int,
data: str,
previous_hash: str,
nonce: int,
):
self._index = index
self._timestamp = dopt_basics.datetime.current_time_tz().timestamp()
self._data = StringHolder.__new__(StringHolder, data)
self._prev_hash = StringHolder.__new__(StringHolder, previous_hash)
self._nonce = nonce
@property
def index(self):
return self._index
@property
def timestamp(self):
return timestamp_to_datetime(self._timestamp)
@property
def data(self):
return self._data.py_string
@property
def prev_hash(self):
return self._prev_hash.py_string
@property
def nonce(self):
return self._nonce
@nonce.setter
def nonce(self, value: int):
self._nonce = value