pydiverse-common 0.3.0__py3-none-any.whl → 0.3.4__py3-none-any.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.
- pydiverse/common/__init__.py +2 -0
- pydiverse/common/dtypes.py +66 -9
- pydiverse/common/testing.py +14 -0
- pydiverse/common/version.py +10 -0
- {pydiverse_common-0.3.0.dist-info → pydiverse_common-0.3.4.dist-info}/METADATA +3 -2
- {pydiverse_common-0.3.0.dist-info → pydiverse_common-0.3.4.dist-info}/RECORD +8 -6
- {pydiverse_common-0.3.0.dist-info → pydiverse_common-0.3.4.dist-info}/WHEEL +0 -0
- {pydiverse_common-0.3.0.dist-info → pydiverse_common-0.3.4.dist-info}/licenses/LICENSE +0 -0
pydiverse/common/__init__.py
CHANGED
pydiverse/common/dtypes.py
CHANGED
@@ -12,24 +12,33 @@ class Dtype:
|
|
12
12
|
"""Base class for all data types."""
|
13
13
|
|
14
14
|
def __eq__(self, rhs):
|
15
|
+
"""Return ``True`` if this dtype is equal to `rhs`."""
|
15
16
|
return isinstance(rhs, Dtype) and type(self) is type(rhs)
|
16
17
|
|
17
18
|
def __hash__(self):
|
19
|
+
"""Return a hash for this dtype."""
|
18
20
|
return hash(type(self))
|
19
21
|
|
20
22
|
def __repr__(self):
|
23
|
+
"""Return a string representation of this dtype."""
|
21
24
|
return self.__class__.__name__
|
22
25
|
|
23
26
|
@classmethod
|
24
27
|
def is_int(cls):
|
28
|
+
"""Return ``True`` if this dtype is an integer type."""
|
25
29
|
return False
|
26
30
|
|
27
31
|
@classmethod
|
28
32
|
def is_float(cls):
|
33
|
+
"""Return ``True`` if this dtype is a float type."""
|
29
34
|
return False
|
30
35
|
|
31
36
|
@classmethod
|
32
37
|
def is_subtype(cls, rhs):
|
38
|
+
"""Return ``True`` if this dtype is a subtype of `rhs`.
|
39
|
+
|
40
|
+
For example, ``Int8.is_subtype(Int())`` is ``True``.
|
41
|
+
"""
|
33
42
|
rhs_cls = type(rhs)
|
34
43
|
return (
|
35
44
|
(cls is rhs_cls)
|
@@ -39,6 +48,7 @@ class Dtype:
|
|
39
48
|
|
40
49
|
@staticmethod
|
41
50
|
def from_sql(sql_type) -> "Dtype":
|
51
|
+
"""Convert a SQL type to a Dtype."""
|
42
52
|
import sqlalchemy as sqa
|
43
53
|
|
44
54
|
if isinstance(sql_type, sqa.SmallInteger):
|
@@ -70,15 +80,18 @@ class Dtype:
|
|
70
80
|
return Time()
|
71
81
|
if isinstance(sql_type, sqa.DateTime):
|
72
82
|
return Datetime()
|
83
|
+
if isinstance(sql_type, sqa.Interval):
|
84
|
+
return Duration()
|
73
85
|
if isinstance(sql_type, sqa.ARRAY):
|
74
|
-
return List(Dtype.from_sql(sql_type.item_type
|
75
|
-
if isinstance(sql_type, sqa.
|
86
|
+
return List(Dtype.from_sql(sql_type.item_type))
|
87
|
+
if isinstance(sql_type, sqa.types.NullType):
|
76
88
|
return NullType()
|
77
89
|
|
78
90
|
raise TypeError
|
79
91
|
|
80
92
|
@staticmethod
|
81
93
|
def from_pandas(pandas_type) -> "Dtype":
|
94
|
+
"""Convert a pandas type to a Dtype."""
|
82
95
|
import numpy as np
|
83
96
|
import pandas as pd
|
84
97
|
|
@@ -123,12 +136,16 @@ class Dtype:
|
|
123
136
|
return Bool()
|
124
137
|
if pd.api.types.is_datetime64_any_dtype(pandas_type):
|
125
138
|
return Datetime()
|
126
|
-
|
139
|
+
if pd.api.types.is_timedelta64_dtype(pandas_type):
|
140
|
+
return Duration()
|
141
|
+
# we don't know any decimal/time/null dtypes in pandas if column is not
|
142
|
+
# arrow backed
|
127
143
|
|
128
144
|
raise TypeError
|
129
145
|
|
130
146
|
@staticmethod
|
131
147
|
def from_arrow(arrow_type) -> "Dtype":
|
148
|
+
"""Convert a PyArrow type to a Dtype."""
|
132
149
|
import pyarrow as pa
|
133
150
|
|
134
151
|
if pa.types.is_signed_integer(arrow_type):
|
@@ -172,10 +189,17 @@ class Dtype:
|
|
172
189
|
return Date()
|
173
190
|
if pa.types.is_time(arrow_type):
|
174
191
|
return Time()
|
192
|
+
if pa.types.is_duration(arrow_type):
|
193
|
+
return Duration()
|
194
|
+
if pa.types.is_null(arrow_type):
|
195
|
+
return NullType()
|
196
|
+
if pa.types.is_list(arrow_type):
|
197
|
+
return List(Dtype.from_arrow(arrow_type.value_type))
|
175
198
|
raise TypeError
|
176
199
|
|
177
200
|
@staticmethod
|
178
201
|
def from_polars(polars_type) -> "Dtype":
|
202
|
+
"""Convert a Polars type to a Dtype."""
|
179
203
|
import polars as pl
|
180
204
|
|
181
205
|
if isinstance(polars_type, pl.List):
|
@@ -204,6 +228,7 @@ class Dtype:
|
|
204
228
|
}[polars_type.base_type()]
|
205
229
|
|
206
230
|
def to_sql(self):
|
231
|
+
"""Convert this Dtype to a SQL type."""
|
207
232
|
import sqlalchemy as sqa
|
208
233
|
|
209
234
|
return {
|
@@ -225,10 +250,12 @@ class Dtype:
|
|
225
250
|
Date(): sqa.Date(),
|
226
251
|
Time(): sqa.Time(),
|
227
252
|
Datetime(): sqa.DateTime(),
|
253
|
+
Duration(): sqa.Interval(),
|
228
254
|
NullType(): sqa.types.NullType(),
|
229
255
|
}[self]
|
230
256
|
|
231
257
|
def to_pandas(self, backend: PandasBackend = PandasBackend.ARROW):
|
258
|
+
"""Convert this Dtype to a pandas type."""
|
232
259
|
import pandas as pd
|
233
260
|
|
234
261
|
if backend == PandasBackend.NUMPY:
|
@@ -239,12 +266,32 @@ class Dtype:
|
|
239
266
|
return pd.ArrowDtype(self.to_arrow())
|
240
267
|
|
241
268
|
def to_pandas_nullable(self, backend: PandasBackend = PandasBackend.ARROW):
|
269
|
+
"""Convert this Dtype to a pandas nullable type.
|
270
|
+
|
271
|
+
Nullable can be either pandas extension types like StringDtype or ArrowDtype.
|
272
|
+
|
273
|
+
Parameters
|
274
|
+
----------
|
275
|
+
backend : PandasBackend, optional
|
276
|
+
The pandas backend to use. Defaults to ``PandasBackend.ARROW``.
|
277
|
+
If ``PandasBackend.NUMPY`` is selected, this method will attempt
|
278
|
+
to return a NumPy-backed nullable pandas dtype. Note that
|
279
|
+
Time, NullType, and List will raise a TypeError for the
|
280
|
+
NUMPY backend as pandas doesn't have corresponding native
|
281
|
+
nullable dtypes for these.
|
282
|
+
"""
|
242
283
|
import pandas as pd
|
243
284
|
|
244
|
-
if
|
245
|
-
|
246
|
-
|
285
|
+
if backend == PandasBackend.ARROW:
|
286
|
+
return pd.ArrowDtype(self.to_arrow())
|
287
|
+
|
288
|
+
# we don't want to produce object columns
|
289
|
+
if isinstance(self, Time):
|
247
290
|
raise TypeError("pandas doesn't have a native time dtype")
|
291
|
+
if isinstance(self, NullType):
|
292
|
+
raise TypeError("pandas doesn't have a native null dtype")
|
293
|
+
if isinstance(self, List):
|
294
|
+
raise TypeError("pandas doesn't have a native list dtype")
|
248
295
|
|
249
296
|
return {
|
250
297
|
Int(): pd.Int64Dtype(), # we default to 64 bit
|
@@ -263,11 +310,13 @@ class Dtype:
|
|
263
310
|
String(): pd.StringDtype(),
|
264
311
|
Bool(): pd.BooleanDtype(),
|
265
312
|
Date(): "datetime64[s]",
|
266
|
-
# Time() not supported
|
267
313
|
Datetime(): "datetime64[us]",
|
314
|
+
Time(): "timedelta64[us]",
|
315
|
+
Duration(): "timedelta64[us]",
|
268
316
|
}[self]
|
269
317
|
|
270
318
|
def to_arrow(self):
|
319
|
+
"""Convert this Dtype to a PyArrow type."""
|
271
320
|
import pyarrow as pa
|
272
321
|
|
273
322
|
return {
|
@@ -289,9 +338,12 @@ class Dtype:
|
|
289
338
|
Date(): pa.date32(),
|
290
339
|
Time(): pa.time64("us"),
|
291
340
|
Datetime(): pa.timestamp("us"),
|
341
|
+
Duration(): pa.duration("us"),
|
342
|
+
NullType(): pa.null(),
|
292
343
|
}[self]
|
293
344
|
|
294
345
|
def to_polars(self: "Dtype"):
|
346
|
+
"""Convert this Dtype to a Polars type."""
|
295
347
|
import polars as pl
|
296
348
|
|
297
349
|
return {
|
@@ -311,8 +363,8 @@ class Dtype:
|
|
311
363
|
String(): pl.Utf8,
|
312
364
|
Bool(): pl.Boolean,
|
313
365
|
Datetime(): pl.Datetime("us"),
|
314
|
-
Duration(): pl.Duration,
|
315
|
-
Time(): pl.Time,
|
366
|
+
Duration(): pl.Duration("us"),
|
367
|
+
Time(): pl.Time, # Polars uses nanoseconds since midnight
|
316
368
|
Date(): pl.Date,
|
317
369
|
NullType(): pl.Null,
|
318
370
|
}[self]
|
@@ -406,3 +458,8 @@ class List(Dtype):
|
|
406
458
|
import polars as pl
|
407
459
|
|
408
460
|
return pl.List(self.inner.to_polars())
|
461
|
+
|
462
|
+
def to_arrow(self):
|
463
|
+
import pyarrow as pa
|
464
|
+
|
465
|
+
return pa.list_(self.inner.to_arrow())
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# Copyright (c) QuantCo and pydiverse contributors 2025-2025
|
2
|
+
# SPDX-License-Identifier: BSD-3-Clause
|
3
|
+
|
4
|
+
import inspect
|
5
|
+
|
6
|
+
import pydiverse.common.dtypes as dtypes
|
7
|
+
|
8
|
+
ALL_TYPES = [
|
9
|
+
getattr(dtypes, c)
|
10
|
+
for c in dir(dtypes)
|
11
|
+
if inspect.isclass(getattr(dtypes, c))
|
12
|
+
and issubclass(getattr(dtypes, c), dtypes.Dtype)
|
13
|
+
and c != "Dtype"
|
14
|
+
]
|
@@ -0,0 +1,10 @@
|
|
1
|
+
# Copyright (c) QuantCo and pydiverse contributors 2025-2025
|
2
|
+
# SPDX-License-Identifier: BSD-3-Clause
|
3
|
+
|
4
|
+
from importlib.metadata import PackageNotFoundError, version
|
5
|
+
|
6
|
+
try:
|
7
|
+
__version__ = version(__package__ or __name__)
|
8
|
+
except PackageNotFoundError:
|
9
|
+
# Running from a Git checkout or an editable install
|
10
|
+
__version__ = "0.0.0+dev"
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: pydiverse-common
|
3
|
-
Version: 0.3.
|
3
|
+
Version: 0.3.4
|
4
4
|
Summary: Common functionality shared between pydiverse libraries
|
5
5
|
Author: QuantCo, Inc.
|
6
6
|
Author-email: Martin Trautmann <windiana@users.sf.net>, Finn Rudolph <finn.rudolph@t-online.de>
|
@@ -47,7 +47,8 @@ Classifier: Programming Language :: SQL
|
|
47
47
|
Classifier: Topic :: Database
|
48
48
|
Classifier: Topic :: Scientific/Engineering
|
49
49
|
Classifier: Topic :: Software Development
|
50
|
-
Requires-Python:
|
50
|
+
Requires-Python: <3.14,>=3.10
|
51
|
+
Requires-Dist: python-box<8.0.0,>=7.3.2
|
51
52
|
Description-Content-Type: text/markdown
|
52
53
|
|
53
54
|
# pydiverse.common
|
@@ -1,5 +1,7 @@
|
|
1
|
-
pydiverse/common/__init__.py,sha256=
|
2
|
-
pydiverse/common/dtypes.py,sha256=
|
1
|
+
pydiverse/common/__init__.py,sha256=eK3Wji6868cvXeq6e9YPRxi20vU6i9Lql4IzG6iB4B4,784
|
2
|
+
pydiverse/common/dtypes.py,sha256=1ADpaWJbdNIFEE2DFjdIy2RRsp5Wg3UVnSM1ZN8XVdw,14555
|
3
|
+
pydiverse/common/testing.py,sha256=FcivI5wn0X3gzJhwnysKvCOgjSTTXaN6FtSFJ72jfSg,341
|
4
|
+
pydiverse/common/version.py,sha256=1IU_m4r76_Qq0u-Tyo2_bERZFOkh0ZFueVzDqcCfLO0,336
|
3
5
|
pydiverse/common/errors/__init__.py,sha256=FNeEfVbUa23b9sHkFsmxHYhY6sRgjaZysPQmlovpJrI,262
|
4
6
|
pydiverse/common/util/__init__.py,sha256=fGdKZtLaTVBW7NfCpX7rZhKHwUzmBnsuY2akDOnAnjc,315
|
5
7
|
pydiverse/common/util/computation_tracing.py,sha256=HeXRHRUI8vxpzQ27Xcpa0StndSTP63EMT9vj4trPJUY,9697
|
@@ -9,7 +11,7 @@ pydiverse/common/util/disposable.py,sha256=4XoGz70YRWA9TAqnUBvRCTAdsOGBviFN0gzxU
|
|
9
11
|
pydiverse/common/util/hashing.py,sha256=6x77BKg-w61u59fuTe9di0BtU-kEKH6UTRcKsRoYJ84,1196
|
10
12
|
pydiverse/common/util/import_.py,sha256=K7dSgz4YyrqEvqhoOzbwgD7D8HScMoO5XoSWtjbaoUs,4056
|
11
13
|
pydiverse/common/util/structlog.py,sha256=g0d8yaXBzAxmGNGZYMnMP9dsSQ__jN44GAY8Mb0ABeI,3487
|
12
|
-
pydiverse_common-0.3.
|
13
|
-
pydiverse_common-0.3.
|
14
|
-
pydiverse_common-0.3.
|
15
|
-
pydiverse_common-0.3.
|
14
|
+
pydiverse_common-0.3.4.dist-info/METADATA,sha256=iV-aHd6IDEbgTaIsbB5lgAstdXaAAdotwZCh05laHA4,3403
|
15
|
+
pydiverse_common-0.3.4.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
16
|
+
pydiverse_common-0.3.4.dist-info/licenses/LICENSE,sha256=AcE6SDVuAq6v9ZLE_8eOCe_NvSE0rAPR3NR7lSowYh4,1517
|
17
|
+
pydiverse_common-0.3.4.dist-info/RECORD,,
|
File without changes
|
File without changes
|