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.
@@ -25,8 +25,10 @@ from .dtypes import (
25
25
  UInt32,
26
26
  UInt64,
27
27
  )
28
+ from .version import __version__
28
29
 
29
30
  __all__ = [
31
+ "__version__",
30
32
  "Dtype",
31
33
  "Bool",
32
34
  "Date",
@@ -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.from_sql))
75
- if isinstance(sql_type, sqa.Null):
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
- # we don't know any decimal dtype in pandas if column is not arrow backed
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 self == Time():
245
- if backend == PandasBackend.ARROW:
246
- return pd.ArrowDtype(self.to_arrow())
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.0
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: >=3.10
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=2t3wnZGY_KITo5lysb-GAgXizeyd_iZvPjEHKnMsYpA,732
2
- pydiverse/common/dtypes.py,sha256=7qPxKH1yqVSacANi5Kl36DdBTHKSMZI2WkZCiEEejyU,12074
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.0.dist-info/METADATA,sha256=5pwbOinMHcsH1Nbhe69cbh0eouevUvFNGt-QlLdl-HU,3357
13
- pydiverse_common-0.3.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
14
- pydiverse_common-0.3.0.dist-info/licenses/LICENSE,sha256=AcE6SDVuAq6v9ZLE_8eOCe_NvSE0rAPR3NR7lSowYh4,1517
15
- pydiverse_common-0.3.0.dist-info/RECORD,,
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,,