tea-bond 0.2.8__cp310-abi3-manylinux_2_34_x86_64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of tea-bond might be problematic. Click here for more details.
- pybond/__init__.py +17 -0
- pybond/bond.py +185 -0
- pybond/download.py +147 -0
- pybond/ffi/__init__.py +3 -0
- pybond/ffi/bond.py +68 -0
- pybond/ffi/datetime.py +58 -0
- pybond/ffi/duration.py +19 -0
- pybond/ffi/lib.py +8 -0
- pybond/nb/__init__.py +27 -0
- pybond/nb/ir_utils.py +47 -0
- pybond/nb/nb_bond.py +219 -0
- pybond/nb/nb_date.py +209 -0
- pybond/nb/nb_datetime.py +420 -0
- pybond/nb/nb_duration.py +81 -0
- pybond/nb/nb_time.py +279 -0
- pybond/pnl.py +59 -0
- pybond/polars_utils.py +96 -0
- pybond/pybond.abi3.so +0 -0
- pybond/pybond.pyi +371 -0
- pybond.libs/libcrypto-fca80f7e.so.3 +0 -0
- pybond.libs/libssl-e50e007b.so.3 +0 -0
- tea_bond-0.2.8.dist-info/METADATA +7 -0
- tea_bond-0.2.8.dist-info/RECORD +24 -0
- tea_bond-0.2.8.dist-info/WHEEL +4 -0
pybond/nb/nb_time.py
ADDED
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
import datetime
|
|
2
|
+
import operator
|
|
3
|
+
|
|
4
|
+
from llvmlite import ir
|
|
5
|
+
from numba import types
|
|
6
|
+
from numba.core import cgutils
|
|
7
|
+
from numba.extending import (
|
|
8
|
+
NativeValue,
|
|
9
|
+
as_numba_type,
|
|
10
|
+
box,
|
|
11
|
+
lower_builtin,
|
|
12
|
+
make_attribute_wrapper,
|
|
13
|
+
models,
|
|
14
|
+
overload,
|
|
15
|
+
overload_attribute,
|
|
16
|
+
# overload_method,
|
|
17
|
+
register_model,
|
|
18
|
+
type_callable,
|
|
19
|
+
typeof_impl,
|
|
20
|
+
unbox,
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
from .ir_utils import ir_isinstance, long_as_ulong
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class Time:
|
|
27
|
+
def __init__(self, hour, minute, second, nanosecond):
|
|
28
|
+
# secs = hour * 3600 + minute * 60 + sec
|
|
29
|
+
# self.val = int(secs * 1e9 + nsecs)
|
|
30
|
+
self.hour = hour
|
|
31
|
+
self.minute = minute
|
|
32
|
+
self.second = second
|
|
33
|
+
self.nanosecond = nanosecond
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class TimeType(types.Type):
|
|
37
|
+
def __init__(self):
|
|
38
|
+
super().__init__(name="Time")
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
time_type = TimeType()
|
|
42
|
+
as_numba_type.register(datetime.time, time_type)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
@typeof_impl.register(datetime.time)
|
|
46
|
+
@typeof_impl.register(Time)
|
|
47
|
+
def typeof_datetime_time(val, c):
|
|
48
|
+
return time_type
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
@type_callable(datetime.time)
|
|
52
|
+
@type_callable(Time)
|
|
53
|
+
def type_time(context):
|
|
54
|
+
def typer(hour, minute, second, nanosecond=0):
|
|
55
|
+
return time_type
|
|
56
|
+
|
|
57
|
+
return typer
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
@register_model(TimeType)
|
|
61
|
+
class TimeModel(models.StructModel):
|
|
62
|
+
def __init__(self, dmm, fe_type):
|
|
63
|
+
members = [
|
|
64
|
+
("hour", types.uint32),
|
|
65
|
+
("minute", types.uint32),
|
|
66
|
+
("second", types.uint32),
|
|
67
|
+
("nanosecond", types.uint32),
|
|
68
|
+
]
|
|
69
|
+
models.StructModel.__init__(self, dmm, fe_type, members)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
make_attribute_wrapper(TimeType, "hour", "hour")
|
|
73
|
+
make_attribute_wrapper(TimeType, "minute", "minute")
|
|
74
|
+
make_attribute_wrapper(TimeType, "second", "second")
|
|
75
|
+
make_attribute_wrapper(TimeType, "nanosecond", "nanosecond")
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
@lower_builtin(Time, types.uint32, types.uint32, types.uint32, types.uint32)
|
|
79
|
+
@lower_builtin(Time, types.int32, types.int32, types.int32, types.int32)
|
|
80
|
+
def time_constructor_u32(context, builder, sig, args):
|
|
81
|
+
time_type = sig.return_type
|
|
82
|
+
time = cgutils.create_struct_proxy(time_type)(context, builder)
|
|
83
|
+
time.hour = args[0]
|
|
84
|
+
time.minute = args[1]
|
|
85
|
+
time.second = args[2]
|
|
86
|
+
time.nanosecond = args[3]
|
|
87
|
+
return time._getvalue()
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
@lower_builtin(datetime.time, types.uint32, types.uint32, types.uint32, types.uint32)
|
|
91
|
+
@lower_builtin(datetime.time, types.int32, types.int32, types.int32, types.int32)
|
|
92
|
+
def datetime_time_constructor_u32(context, builder, sig, args):
|
|
93
|
+
time_type = sig.return_type
|
|
94
|
+
time = cgutils.create_struct_proxy(time_type)(context, builder)
|
|
95
|
+
time.hour = args[0]
|
|
96
|
+
time.minute = args[1]
|
|
97
|
+
time.second = args[2]
|
|
98
|
+
# the last param of datetime time is microsecond, but we store nanosecond
|
|
99
|
+
time.nanosecond = builder.mul(args[3], ir.Constant(ir.IntType(32), 1000))
|
|
100
|
+
return time._getvalue()
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
@lower_builtin(Time, types.int64, types.int64, types.int64, types.int64)
|
|
104
|
+
def time_constructor_i64(context, builder, sig, args):
|
|
105
|
+
time_type = sig.return_type
|
|
106
|
+
time = cgutils.create_struct_proxy(time_type)(context, builder)
|
|
107
|
+
time.hour = builder.trunc(args[0], ir.IntType(32))
|
|
108
|
+
time.minute = builder.trunc(args[1], ir.IntType(32))
|
|
109
|
+
time.second = builder.trunc(args[2], ir.IntType(32))
|
|
110
|
+
time.nanosecond = builder.trunc(args[3], ir.IntType(32))
|
|
111
|
+
return time._getvalue()
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
@lower_builtin(datetime.time, types.int64, types.int64, types.int64, types.int64)
|
|
115
|
+
def datetime_time_constructor_i64(context, builder, sig, args):
|
|
116
|
+
time_type = sig.return_type
|
|
117
|
+
time = cgutils.create_struct_proxy(time_type)(context, builder)
|
|
118
|
+
time.hour = builder.trunc(args[0], ir.IntType(32))
|
|
119
|
+
time.minute = builder.trunc(args[1], ir.IntType(32))
|
|
120
|
+
time.second = builder.trunc(args[2], ir.IntType(32))
|
|
121
|
+
nanosecond = builder.mul(args[3], ir.Constant(ir.IntType(64), 1000))
|
|
122
|
+
time.nanosecond = builder.trunc(nanosecond, ir.IntType(32))
|
|
123
|
+
return time._getvalue()
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
@lower_builtin(datetime.time, types.int64, types.int64, types.int64)
|
|
127
|
+
@lower_builtin(Time, types.int64, types.int64, types.int64)
|
|
128
|
+
def time_constructor_i64_hms(context, builder, sig, args):
|
|
129
|
+
time_type = sig.return_type
|
|
130
|
+
time = cgutils.create_struct_proxy(time_type)(context, builder)
|
|
131
|
+
time.hour = builder.trunc(args[0], ir.IntType(32))
|
|
132
|
+
time.minute = builder.trunc(args[1], ir.IntType(32))
|
|
133
|
+
time.second = builder.trunc(args[2], ir.IntType(32))
|
|
134
|
+
time.nanosecond = ir.Constant(ir.IntType(32), 0)
|
|
135
|
+
return time._getvalue()
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
@unbox(TimeType)
|
|
139
|
+
def unbox_time(typ, obj, c):
|
|
140
|
+
time_type_c = c.pyapi.unserialize(c.pyapi.serialize_object(datetime.time))
|
|
141
|
+
is_time = ir_isinstance(c.pyapi, obj, time_type_c)
|
|
142
|
+
c.pyapi.decref(time_type_c)
|
|
143
|
+
|
|
144
|
+
hour_obj = c.pyapi.object_getattr_string(obj, "hour")
|
|
145
|
+
hour = c.builder.trunc(long_as_ulong(c.pyapi, hour_obj), ir.IntType(32))
|
|
146
|
+
minute_obj = c.pyapi.object_getattr_string(obj, "minute")
|
|
147
|
+
minute = c.builder.trunc(long_as_ulong(c.pyapi, minute_obj), ir.IntType(32))
|
|
148
|
+
second_obj = c.pyapi.object_getattr_string(obj, "second")
|
|
149
|
+
second = c.builder.trunc(long_as_ulong(c.pyapi, second_obj), ir.IntType(32))
|
|
150
|
+
c.pyapi.decref(hour_obj)
|
|
151
|
+
c.pyapi.decref(minute_obj)
|
|
152
|
+
c.pyapi.decref(second_obj)
|
|
153
|
+
|
|
154
|
+
nsecs_ptr = cgutils.alloca_once(c.builder, ir.IntType(32))
|
|
155
|
+
with c.builder.if_else(is_time) as (then, otherwise):
|
|
156
|
+
with then:
|
|
157
|
+
msecs_obj = c.pyapi.object_getattr_string(obj, "microsecond")
|
|
158
|
+
msecs = long_as_ulong(c.pyapi, msecs_obj)
|
|
159
|
+
nsecs = c.builder.mul(msecs, ir.Constant(c.pyapi.ulong, 1000))
|
|
160
|
+
nsecs = c.builder.trunc(nsecs, ir.IntType(32))
|
|
161
|
+
c.pyapi.decref(msecs_obj)
|
|
162
|
+
c.builder.store(nsecs, nsecs_ptr)
|
|
163
|
+
with otherwise:
|
|
164
|
+
nsecs_obj = c.pyapi.object_getattr_string(obj, "nanosecond")
|
|
165
|
+
nsecs = long_as_ulong(c.pyapi, nsecs_obj)
|
|
166
|
+
nsecs = c.builder.trunc(nsecs, ir.IntType(32))
|
|
167
|
+
c.pyapi.decref(nsecs_obj)
|
|
168
|
+
c.builder.store(nsecs, nsecs_ptr)
|
|
169
|
+
nanosecond = c.builder.load(nsecs_ptr)
|
|
170
|
+
time = cgutils.create_struct_proxy(typ)(c.context, c.builder)
|
|
171
|
+
time.hour = hour
|
|
172
|
+
time.minute = minute
|
|
173
|
+
time.second = second
|
|
174
|
+
time.nanosecond = nanosecond
|
|
175
|
+
# Check for errors
|
|
176
|
+
is_error = cgutils.is_not_null(c.builder, c.pyapi.err_occurred())
|
|
177
|
+
return NativeValue(time._getvalue(), is_error=is_error)
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
@box(TimeType)
|
|
181
|
+
def box_time(typ, val, c):
|
|
182
|
+
"""
|
|
183
|
+
Box a native time object into a Python datetime.time object.
|
|
184
|
+
"""
|
|
185
|
+
time = cgutils.create_struct_proxy(typ)(c.context, c.builder, value=val)
|
|
186
|
+
hour_obj = c.pyapi.long_from_unsigned_int(time.hour)
|
|
187
|
+
minute_obj = c.pyapi.long_from_unsigned_int(time.minute)
|
|
188
|
+
second_obj = c.pyapi.long_from_unsigned_int(time.second)
|
|
189
|
+
microsecond = c.builder.udiv(
|
|
190
|
+
time.nanosecond, ir.Constant(time.nanosecond.type, 1000)
|
|
191
|
+
)
|
|
192
|
+
microsecond_obj = c.pyapi.long_from_unsigned_int(microsecond)
|
|
193
|
+
|
|
194
|
+
class_obj = c.pyapi.unserialize(c.pyapi.serialize_object(datetime.time))
|
|
195
|
+
time_obj = c.pyapi.call_function_objargs(
|
|
196
|
+
class_obj, (hour_obj, minute_obj, second_obj, microsecond_obj)
|
|
197
|
+
)
|
|
198
|
+
c.pyapi.decref(hour_obj)
|
|
199
|
+
c.pyapi.decref(minute_obj)
|
|
200
|
+
c.pyapi.decref(second_obj)
|
|
201
|
+
c.pyapi.decref(microsecond_obj)
|
|
202
|
+
return time_obj
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
@overload_attribute(TimeType, "nsecs")
|
|
206
|
+
def get_time_impl(dt):
|
|
207
|
+
def getter(dt):
|
|
208
|
+
return int(
|
|
209
|
+
(dt.hour * 3600 + dt.minute * 60 + dt.second) * 1_000_000_000
|
|
210
|
+
+ dt.nanosecond
|
|
211
|
+
)
|
|
212
|
+
|
|
213
|
+
return getter
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
@overload(operator.ge)
|
|
217
|
+
def impl_ge(dt, dt2):
|
|
218
|
+
if not isinstance(dt, TimeType) or not isinstance(dt, TimeType):
|
|
219
|
+
return
|
|
220
|
+
|
|
221
|
+
def impl(dt, dt2):
|
|
222
|
+
return dt.nsecs >= dt2.nsecs
|
|
223
|
+
|
|
224
|
+
return impl
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
@overload(operator.gt)
|
|
228
|
+
def impl_gt(dt, dt2):
|
|
229
|
+
if not isinstance(dt, TimeType) or not isinstance(dt, TimeType):
|
|
230
|
+
return
|
|
231
|
+
|
|
232
|
+
def impl(dt, dt2):
|
|
233
|
+
return dt.nsecs > dt2.nsecs
|
|
234
|
+
|
|
235
|
+
return impl
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
@overload(operator.le)
|
|
239
|
+
def impl_le(dt, dt2):
|
|
240
|
+
if not isinstance(dt, TimeType) or not isinstance(dt, TimeType):
|
|
241
|
+
return
|
|
242
|
+
|
|
243
|
+
def impl(dt, dt2):
|
|
244
|
+
return dt.nsecs <= dt2.nsecs
|
|
245
|
+
|
|
246
|
+
return impl
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
@overload(operator.lt)
|
|
250
|
+
def impl_lt(dt, dt2):
|
|
251
|
+
if not isinstance(dt, TimeType) or not isinstance(dt, TimeType):
|
|
252
|
+
return
|
|
253
|
+
|
|
254
|
+
def impl(dt, dt2):
|
|
255
|
+
return dt.nsecs < dt2.nsecs
|
|
256
|
+
|
|
257
|
+
return impl
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
@overload(operator.eq)
|
|
261
|
+
def impl_eq(dt, dt2):
|
|
262
|
+
if not isinstance(dt, TimeType) or not isinstance(dt, TimeType):
|
|
263
|
+
return
|
|
264
|
+
|
|
265
|
+
def impl(dt, dt2):
|
|
266
|
+
return dt.nsecs == dt2.nsecs
|
|
267
|
+
|
|
268
|
+
return impl
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
@overload(operator.ne)
|
|
272
|
+
def impl_ne(dt, dt2):
|
|
273
|
+
if not isinstance(dt, TimeType) or not isinstance(dt, TimeType):
|
|
274
|
+
return
|
|
275
|
+
|
|
276
|
+
def impl(dt, dt2):
|
|
277
|
+
return dt.nsecs != dt2.nsecs
|
|
278
|
+
|
|
279
|
+
return impl
|
pybond/pnl.py
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
|
+
|
|
5
|
+
if TYPE_CHECKING:
|
|
6
|
+
import polars as pl
|
|
7
|
+
from polars.type_aliases import IntoExpr
|
|
8
|
+
|
|
9
|
+
from .polars_utils import parse_into_expr, register_plugin
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def calc_bond_trade_pnl(
|
|
13
|
+
settle_time: IntoExpr,
|
|
14
|
+
qty: IntoExpr,
|
|
15
|
+
clean_price: IntoExpr,
|
|
16
|
+
clean_close: IntoExpr,
|
|
17
|
+
symbol: str = "",
|
|
18
|
+
bond_info_path: str | None = None,
|
|
19
|
+
multiplier: float = 1,
|
|
20
|
+
c_rate: float = 0,
|
|
21
|
+
borrowing_cost: float = 0,
|
|
22
|
+
capital_rate: float = 0,
|
|
23
|
+
begin_state=None,
|
|
24
|
+
) -> pl.Expr:
|
|
25
|
+
settle_time = parse_into_expr(settle_time)
|
|
26
|
+
qty = parse_into_expr(qty)
|
|
27
|
+
clean_price = parse_into_expr(clean_price)
|
|
28
|
+
clean_close = parse_into_expr(clean_close)
|
|
29
|
+
if bond_info_path is None:
|
|
30
|
+
from .bond import bonds_info_path as path
|
|
31
|
+
|
|
32
|
+
bond_info_path = str(path)
|
|
33
|
+
|
|
34
|
+
if begin_state is None:
|
|
35
|
+
begin_state = {
|
|
36
|
+
"pos": 0,
|
|
37
|
+
"avg_price": 0,
|
|
38
|
+
"pnl": 0,
|
|
39
|
+
"realized_pnl": 0,
|
|
40
|
+
"pos_price": 0,
|
|
41
|
+
"unrealized_pnl": 0,
|
|
42
|
+
"coupon_paid": 0,
|
|
43
|
+
"amt": 0,
|
|
44
|
+
}
|
|
45
|
+
kwargs = {
|
|
46
|
+
"symbol": symbol,
|
|
47
|
+
"multiplier": multiplier,
|
|
48
|
+
"c_rate": c_rate,
|
|
49
|
+
"borrowing_cost": borrowing_cost,
|
|
50
|
+
"capital_rate": capital_rate,
|
|
51
|
+
"begin_state": begin_state,
|
|
52
|
+
"bond_info_path": bond_info_path,
|
|
53
|
+
}
|
|
54
|
+
return register_plugin(
|
|
55
|
+
args=[settle_time, qty, clean_price, clean_close],
|
|
56
|
+
kwargs=kwargs,
|
|
57
|
+
symbol="calc_bond_trade_pnl",
|
|
58
|
+
is_elementwise=False,
|
|
59
|
+
)
|
pybond/polars_utils.py
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import re
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from typing import TYPE_CHECKING, Any, Sequence
|
|
6
|
+
|
|
7
|
+
import polars as pl
|
|
8
|
+
|
|
9
|
+
if TYPE_CHECKING:
|
|
10
|
+
from polars.type_aliases import IntoExpr, PolarsDataType
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def parse_into_expr(
|
|
14
|
+
expr: IntoExpr,
|
|
15
|
+
*,
|
|
16
|
+
str_as_lit: bool = False,
|
|
17
|
+
list_as_lit: bool = True,
|
|
18
|
+
dtype: PolarsDataType | None = None,
|
|
19
|
+
) -> pl.Expr:
|
|
20
|
+
"""
|
|
21
|
+
Parse a single input into an expression.
|
|
22
|
+
|
|
23
|
+
Parameters
|
|
24
|
+
----------
|
|
25
|
+
expr
|
|
26
|
+
The input to be parsed as an expression.
|
|
27
|
+
str_as_lit
|
|
28
|
+
Interpret string input as a string literal. If set to `False` (default),
|
|
29
|
+
strings are parsed as column names.
|
|
30
|
+
list_as_lit
|
|
31
|
+
Interpret list input as a lit literal, If set to `False`,
|
|
32
|
+
lists are parsed as `Series` literals.
|
|
33
|
+
dtype
|
|
34
|
+
If the input is expected to resolve to a literal with a known dtype, pass
|
|
35
|
+
this to the `lit` constructor.
|
|
36
|
+
|
|
37
|
+
Returns
|
|
38
|
+
-------
|
|
39
|
+
polars.Expr
|
|
40
|
+
"""
|
|
41
|
+
if isinstance(expr, pl.Expr):
|
|
42
|
+
pass
|
|
43
|
+
elif isinstance(expr, str) and not str_as_lit:
|
|
44
|
+
expr = pl.col(expr)
|
|
45
|
+
elif isinstance(expr, list) and not list_as_lit:
|
|
46
|
+
expr = pl.lit(pl.Series(expr), dtype=dtype)
|
|
47
|
+
else:
|
|
48
|
+
expr = pl.lit(expr, dtype=dtype)
|
|
49
|
+
|
|
50
|
+
return expr
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def register_plugin(
|
|
54
|
+
*,
|
|
55
|
+
symbol: str,
|
|
56
|
+
is_elementwise: bool,
|
|
57
|
+
kwargs: dict[str, Any] | None = None,
|
|
58
|
+
args: list[IntoExpr],
|
|
59
|
+
# lib: str | Path,
|
|
60
|
+
) -> pl.Expr:
|
|
61
|
+
global lib
|
|
62
|
+
if parse_version(pl.__version__) < parse_version("0.20.16"):
|
|
63
|
+
assert isinstance(args[0], pl.Expr)
|
|
64
|
+
assert isinstance(lib, str)
|
|
65
|
+
return args[0].register_plugin(
|
|
66
|
+
lib=lib,
|
|
67
|
+
symbol=symbol,
|
|
68
|
+
args=args[1:],
|
|
69
|
+
kwargs=kwargs,
|
|
70
|
+
is_elementwise=is_elementwise,
|
|
71
|
+
)
|
|
72
|
+
from polars.plugins import register_plugin_function
|
|
73
|
+
|
|
74
|
+
return register_plugin_function(
|
|
75
|
+
args=args,
|
|
76
|
+
plugin_path=lib,
|
|
77
|
+
function_name=symbol,
|
|
78
|
+
kwargs=kwargs,
|
|
79
|
+
is_elementwise=is_elementwise,
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def parse_version(version: Sequence[str | int]) -> tuple[int, ...]:
|
|
84
|
+
# Simple version parser; split into a tuple of ints for comparison.
|
|
85
|
+
# vendored from Polars
|
|
86
|
+
if isinstance(version, str):
|
|
87
|
+
version = version.split(".")
|
|
88
|
+
return tuple(int(re.sub(r"\D", "", str(v))) for v in version)
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
if parse_version(pl.__version__) < parse_version("0.20.16"):
|
|
92
|
+
from polars.utils.udfs import _get_shared_lib_location
|
|
93
|
+
|
|
94
|
+
lib: str | Path = _get_shared_lib_location(__file__)
|
|
95
|
+
else:
|
|
96
|
+
lib = Path(__file__).parent
|
pybond/pybond.abi3.so
ADDED
|
Binary file
|