pydiverse-common 0.3.4__tar.gz → 0.3.5__tar.gz

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.
Files changed (46) hide show
  1. pydiverse_common-0.3.5/.github/scripts/check_deps.sh +22 -0
  2. {pydiverse_common-0.3.4 → pydiverse_common-0.3.5}/.github/workflows/tests.yml +2 -1
  3. {pydiverse_common-0.3.4 → pydiverse_common-0.3.5}/PKG-INFO +2 -2
  4. {pydiverse_common-0.3.4 → pydiverse_common-0.3.5}/pixi.lock +56 -0
  5. {pydiverse_common-0.3.4 → pydiverse_common-0.3.5}/pixi.toml +3 -1
  6. {pydiverse_common-0.3.4 → pydiverse_common-0.3.5}/pyproject.toml +2 -2
  7. {pydiverse_common-0.3.4 → pydiverse_common-0.3.5}/src/pydiverse/common/__init__.py +2 -0
  8. {pydiverse_common-0.3.4 → pydiverse_common-0.3.5}/src/pydiverse/common/dtypes.py +46 -3
  9. {pydiverse_common-0.3.4 → pydiverse_common-0.3.5}/tests/dtypes/test_dtype_pandas.py +26 -7
  10. {pydiverse_common-0.3.4 → pydiverse_common-0.3.5}/tests/dtypes/test_dtype_polars.py +9 -1
  11. {pydiverse_common-0.3.4 → pydiverse_common-0.3.5}/tests/dtypes/test_dtype_pyarrow.py +15 -2
  12. {pydiverse_common-0.3.4 → pydiverse_common-0.3.5}/tests/dtypes/test_dtype_sqlalchemy.py +17 -8
  13. {pydiverse_common-0.3.4 → pydiverse_common-0.3.5}/.gitattributes +0 -0
  14. {pydiverse_common-0.3.4 → pydiverse_common-0.3.5}/.github/CODEOWNERS +0 -0
  15. {pydiverse_common-0.3.4 → pydiverse_common-0.3.5}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  16. {pydiverse_common-0.3.4 → pydiverse_common-0.3.5}/.github/dependabot.yml +0 -0
  17. {pydiverse_common-0.3.4 → pydiverse_common-0.3.5}/.github/workflows/release.yml +0 -0
  18. {pydiverse_common-0.3.4 → pydiverse_common-0.3.5}/.github/workflows/update-lockfiles.yml +0 -0
  19. {pydiverse_common-0.3.4 → pydiverse_common-0.3.5}/.gitignore +0 -0
  20. {pydiverse_common-0.3.4 → pydiverse_common-0.3.5}/.pre-commit-config.yaml +0 -0
  21. {pydiverse_common-0.3.4 → pydiverse_common-0.3.5}/.readthedocs.yaml +0 -0
  22. {pydiverse_common-0.3.4 → pydiverse_common-0.3.5}/LICENSE +0 -0
  23. {pydiverse_common-0.3.4 → pydiverse_common-0.3.5}/README.md +0 -0
  24. {pydiverse_common-0.3.4 → pydiverse_common-0.3.5}/docs/Makefile +0 -0
  25. {pydiverse_common-0.3.4 → pydiverse_common-0.3.5}/docs/make.bat +0 -0
  26. {pydiverse_common-0.3.4 → pydiverse_common-0.3.5}/docs/package/README.md +0 -0
  27. {pydiverse_common-0.3.4 → pydiverse_common-0.3.5}/docs/source/changelog.md +0 -0
  28. {pydiverse_common-0.3.4 → pydiverse_common-0.3.5}/docs/source/conf.py +0 -0
  29. {pydiverse_common-0.3.4 → pydiverse_common-0.3.5}/docs/source/index.md +0 -0
  30. {pydiverse_common-0.3.4 → pydiverse_common-0.3.5}/docs/source/license.md +0 -0
  31. {pydiverse_common-0.3.4 → pydiverse_common-0.3.5}/docs/source/reference/api.rst +0 -0
  32. {pydiverse_common-0.3.4 → pydiverse_common-0.3.5}/pytest.ini +0 -0
  33. {pydiverse_common-0.3.4 → pydiverse_common-0.3.5}/src/pydiverse/common/errors/__init__.py +0 -0
  34. {pydiverse_common-0.3.4 → pydiverse_common-0.3.5}/src/pydiverse/common/testing.py +0 -0
  35. {pydiverse_common-0.3.4 → pydiverse_common-0.3.5}/src/pydiverse/common/util/__init__.py +0 -0
  36. {pydiverse_common-0.3.4 → pydiverse_common-0.3.5}/src/pydiverse/common/util/computation_tracing.py +0 -0
  37. {pydiverse_common-0.3.4 → pydiverse_common-0.3.5}/src/pydiverse/common/util/deep_map.py +0 -0
  38. {pydiverse_common-0.3.4 → pydiverse_common-0.3.5}/src/pydiverse/common/util/deep_merge.py +0 -0
  39. {pydiverse_common-0.3.4 → pydiverse_common-0.3.5}/src/pydiverse/common/util/disposable.py +0 -0
  40. {pydiverse_common-0.3.4 → pydiverse_common-0.3.5}/src/pydiverse/common/util/hashing.py +0 -0
  41. {pydiverse_common-0.3.4 → pydiverse_common-0.3.5}/src/pydiverse/common/util/import_.py +0 -0
  42. {pydiverse_common-0.3.4 → pydiverse_common-0.3.5}/src/pydiverse/common/util/structlog.py +0 -0
  43. {pydiverse_common-0.3.4 → pydiverse_common-0.3.5}/src/pydiverse/common/version.py +0 -0
  44. {pydiverse_common-0.3.4 → pydiverse_common-0.3.5}/tests/conftest.py +0 -0
  45. {pydiverse_common-0.3.4 → pydiverse_common-0.3.5}/tests/test_util.py +0 -0
  46. {pydiverse_common-0.3.4 → pydiverse_common-0.3.5}/tests/test_version.py +0 -0
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env bash
2
+
3
+ set -euo pipefail
4
+
5
+ contains_dependency_all=true
6
+
7
+ while read -r package version; do
8
+ if [[ $package == "python" ]]; then
9
+ continue
10
+ fi
11
+
12
+ dependency="${package} ${version}"
13
+ contains_dependency=$(yq -r ".project.dependencies | map(. == \"${dependency}\") | any" pyproject.toml)
14
+ if [[ $contains_dependency == "false" ]]; then
15
+ echo "${dependency} not found in pyproject.toml"
16
+ contains_dependency_all=false
17
+ fi
18
+ done < <(yq -r '.dependencies | to_entries | .[] | "\(.key) \(.value)"' pixi.toml)
19
+
20
+ if [[ $contains_dependency_all == "false" ]]; then
21
+ exit 1
22
+ fi
@@ -23,7 +23,8 @@ jobs:
23
23
  run: pixi run postinstall
24
24
  - name: pre-commit
25
25
  run: pixi run pre-commit run -a --color=always --show-diff-on-failure
26
-
26
+ - name: Check pyproject.toml dependencies
27
+ run: pixi run check-deps
27
28
  test:
28
29
  name: pytest
29
30
  runs-on: ${{ matrix.os }}
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pydiverse-common
3
- Version: 0.3.4
3
+ Version: 0.3.5
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>
@@ -48,7 +48,7 @@ Classifier: Topic :: Database
48
48
  Classifier: Topic :: Scientific/Engineering
49
49
  Classifier: Topic :: Software Development
50
50
  Requires-Python: <3.14,>=3.10
51
- Requires-Dist: python-box<8.0.0,>=7.3.2
51
+ Requires-Dist: python-box<8,>=7.3.2
52
52
  Description-Content-Type: text/markdown
53
53
 
54
54
  # pydiverse.common
@@ -1180,6 +1180,7 @@ environments:
1180
1180
  - conda: https://conda.anaconda.org/conda-forge/noarch/docformatter-1.7.7-pyhd8ed1ab_0.conda
1181
1181
  - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.0-pyhd8ed1ab_0.conda
1182
1182
  - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.18.0-pyhd8ed1ab_0.conda
1183
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/go-yq-4.45.4-hdd9d35a_0.conda
1183
1184
  - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-75.1-he02047a_0.conda
1184
1185
  - conda: https://conda.anaconda.org/conda-forge/noarch/identify-2.6.12-pyhd8ed1ab_0.conda
1185
1186
  - conda: https://conda.anaconda.org/conda-forge/noarch/importlib_resources-6.5.2-pyhd8ed1ab_0.conda
@@ -1276,6 +1277,7 @@ environments:
1276
1277
  - conda: https://conda.anaconda.org/conda-forge/noarch/docformatter-1.7.7-pyhd8ed1ab_0.conda
1277
1278
  - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.0-pyhd8ed1ab_0.conda
1278
1279
  - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.18.0-pyhd8ed1ab_0.conda
1280
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/go-yq-4.45.4-h86ecc28_0.conda
1279
1281
  - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/icu-75.1-hf9b3779_0.conda
1280
1282
  - conda: https://conda.anaconda.org/conda-forge/noarch/identify-2.6.12-pyhd8ed1ab_0.conda
1281
1283
  - conda: https://conda.anaconda.org/conda-forge/noarch/importlib_resources-6.5.2-pyhd8ed1ab_0.conda
@@ -1370,6 +1372,7 @@ environments:
1370
1372
  - conda: https://conda.anaconda.org/conda-forge/noarch/docformatter-1.7.7-pyhd8ed1ab_0.conda
1371
1373
  - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.0-pyhd8ed1ab_0.conda
1372
1374
  - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.18.0-pyhd8ed1ab_0.conda
1375
+ - conda: https://conda.anaconda.org/conda-forge/osx-64/go-yq-4.45.4-h6e16a3a_0.conda
1373
1376
  - conda: https://conda.anaconda.org/conda-forge/osx-64/icu-75.1-h120a0e1_0.conda
1374
1377
  - conda: https://conda.anaconda.org/conda-forge/noarch/identify-2.6.12-pyhd8ed1ab_0.conda
1375
1378
  - conda: https://conda.anaconda.org/conda-forge/noarch/importlib_resources-6.5.2-pyhd8ed1ab_0.conda
@@ -1458,6 +1461,7 @@ environments:
1458
1461
  - conda: https://conda.anaconda.org/conda-forge/noarch/docformatter-1.7.7-pyhd8ed1ab_0.conda
1459
1462
  - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.0-pyhd8ed1ab_0.conda
1460
1463
  - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.18.0-pyhd8ed1ab_0.conda
1464
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/go-yq-4.45.4-h5505292_0.conda
1461
1465
  - conda: https://conda.anaconda.org/conda-forge/osx-arm64/icu-75.1-hfee45f7_0.conda
1462
1466
  - conda: https://conda.anaconda.org/conda-forge/noarch/identify-2.6.12-pyhd8ed1ab_0.conda
1463
1467
  - conda: https://conda.anaconda.org/conda-forge/noarch/importlib_resources-6.5.2-pyhd8ed1ab_0.conda
@@ -1548,6 +1552,7 @@ environments:
1548
1552
  - conda: https://conda.anaconda.org/conda-forge/noarch/docformatter-1.7.7-pyhd8ed1ab_0.conda
1549
1553
  - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.0-pyhd8ed1ab_0.conda
1550
1554
  - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.18.0-pyhd8ed1ab_0.conda
1555
+ - conda: https://conda.anaconda.org/conda-forge/win-64/go-yq-4.45.4-h2466b09_0.conda
1551
1556
  - conda: https://conda.anaconda.org/conda-forge/noarch/identify-2.6.12-pyhd8ed1ab_0.conda
1552
1557
  - conda: https://conda.anaconda.org/conda-forge/noarch/importlib_resources-6.5.2-pyhd8ed1ab_0.conda
1553
1558
  - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_1.conda
@@ -7609,6 +7614,57 @@ packages:
7609
7614
  license_family: BSD
7610
7615
  size: 112215
7611
7616
  timestamp: 1718284365403
7617
+ - conda: https://conda.anaconda.org/conda-forge/linux-64/go-yq-4.45.4-hdd9d35a_0.conda
7618
+ sha256: 710d614cd37077a1b8cb473d9d18b52e7ad4167a40a480f57afdeb42e658f318
7619
+ md5: 0c3da887d37e71224d0077fbb26d1bc5
7620
+ depends:
7621
+ - __glibc >=2.17
7622
+ - __glibc >=2.17,<3.0.a0
7623
+ - libgcc >=13
7624
+ license: MIT
7625
+ license_family: MIT
7626
+ size: 3962140
7627
+ timestamp: 1746984672469
7628
+ - conda: https://conda.anaconda.org/conda-forge/linux-aarch64/go-yq-4.45.4-h86ecc28_0.conda
7629
+ sha256: 5f7f6482aaa817807e43ec5e69967d2c2862687d4b683994b0f170521742c5a9
7630
+ md5: 550e6f0253305a62e99e113974502f14
7631
+ depends:
7632
+ - libgcc >=13
7633
+ license: MIT
7634
+ license_family: MIT
7635
+ size: 3574358
7636
+ timestamp: 1746984625484
7637
+ - conda: https://conda.anaconda.org/conda-forge/osx-64/go-yq-4.45.4-h6e16a3a_0.conda
7638
+ sha256: 446b4cf3173b27ba3bad51b57592e0ffd3345ffbae60e04d184b9e70c6172082
7639
+ md5: 34bec47340c1e15660de53e6ac2256ab
7640
+ depends:
7641
+ - __osx >=10.13
7642
+ constrains:
7643
+ - __osx>=10.12
7644
+ license: MIT
7645
+ license_family: MIT
7646
+ size: 3854128
7647
+ timestamp: 1746984683074
7648
+ - conda: https://conda.anaconda.org/conda-forge/osx-arm64/go-yq-4.45.4-h5505292_0.conda
7649
+ sha256: 5749df601e7039b023481b3fede7cef428e05620f230e016103cd78373bde04f
7650
+ md5: 9e123f64b7084c63ae3c167e68efcfa7
7651
+ depends:
7652
+ - __osx >=11.0
7653
+ license: MIT
7654
+ license_family: MIT
7655
+ size: 3556744
7656
+ timestamp: 1746984719572
7657
+ - conda: https://conda.anaconda.org/conda-forge/win-64/go-yq-4.45.4-h2466b09_0.conda
7658
+ sha256: 7032ee8e93fb4f4af7a793df7d2166d226ae8a0b43580a5b4fa759b19af0e5e2
7659
+ md5: 571bc8198620709a5bcaa824fc467b57
7660
+ depends:
7661
+ - ucrt >=10.0.20348.0
7662
+ - vc >=14.2,<15
7663
+ - vc14_runtime >=14.29.30139
7664
+ license: MIT
7665
+ license_family: MIT
7666
+ size: 8291388
7667
+ timestamp: 1746984722615
7612
7668
  - conda: https://conda.anaconda.org/conda-forge/linux-64/greenlet-3.2.3-py310hf71b8c6_0.conda
7613
7669
  sha256: 9d02287ff70b5734ee7a23acde4012df62f851e787aad4219d4259b591aeb054
7614
7670
  md5: 8455091aed2d84aa239354f67cbdfe74
@@ -41,7 +41,7 @@ Sphinx = ">=7.3.7"
41
41
  furo = ">=2023.5.20"
42
42
  sphinxcontrib-apidoc = ">=0.3.0"
43
43
  myst-parser = ">=2.0.0"
44
- sphinx-autosummary-accessors = "2023.4.0"
44
+ sphinx-autosummary-accessors = ">=2023.4.0"
45
45
  sphinx-click = ">=4.4.0"
46
46
  sphinx-autobuild = ">=2021.3.14"
47
47
  sphinx-copybutton = ">=0.5.2"
@@ -63,6 +63,7 @@ taplo = "*"
63
63
  pre-commit-hooks = "*"
64
64
  typos = "*"
65
65
  conda-deny = "*"
66
+ go-yq = "*"
66
67
 
67
68
  [feature.lint.tasks]
68
69
  #commitit-install = "commitit install"
@@ -70,6 +71,7 @@ conda-deny = "*"
70
71
  pre-commit-install = "pre-commit install"
71
72
  pre-commit-run = "pre-commit run -a"
72
73
  conda-deny = "conda-deny check"
74
+ check-deps = "sh -c .github/scripts/check_deps.sh"
73
75
 
74
76
  [feature.py310.dependencies]
75
77
  python = "3.10.*"
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "pydiverse-common"
3
- version = "0.3.4"
3
+ version = "0.3.5"
4
4
  description = "Common functionality shared between pydiverse libraries"
5
5
  authors = [
6
6
  { name = "QuantCo, Inc." },
@@ -25,7 +25,7 @@ classifiers = [
25
25
  "Topic :: Software Development",
26
26
  ]
27
27
  requires-python = ">=3.10,<3.14"
28
- dependencies = ["python-box>=7.3.2,<8.0.0"]
28
+ dependencies = ["python-box >=7.3.2,<8"]
29
29
 
30
30
  [tool.hatch.build.targets.wheel]
31
31
  packages = ["src/pydiverse"]
@@ -7,6 +7,7 @@ from .dtypes import (
7
7
  Decimal,
8
8
  Dtype,
9
9
  Duration,
10
+ Enum,
10
11
  Float,
11
12
  Float32,
12
13
  Float64,
@@ -51,5 +52,6 @@ __all__ = [
51
52
  "UInt32",
52
53
  "UInt64",
53
54
  "List",
55
+ "Enum",
54
56
  "PandasBackend",
55
57
  ]
@@ -1,9 +1,9 @@
1
1
  # Copyright (c) QuantCo and pydiverse contributors 2025-2025
2
2
  # SPDX-License-Identifier: BSD-3-Clause
3
- from enum import Enum
3
+ import enum
4
4
 
5
5
 
6
- class PandasBackend(str, Enum):
6
+ class PandasBackend(str, enum.Enum):
7
7
  NUMPY = "numpy"
8
8
  ARROW = "arrow"
9
9
 
@@ -141,6 +141,9 @@ class Dtype:
141
141
  # we don't know any decimal/time/null dtypes in pandas if column is not
142
142
  # arrow backed
143
143
 
144
+ if pandas_type.name == "category":
145
+ return Enum(*pandas_type.categories.to_list())
146
+
144
147
  raise TypeError
145
148
 
146
149
  @staticmethod
@@ -204,6 +207,8 @@ class Dtype:
204
207
 
205
208
  if isinstance(polars_type, pl.List):
206
209
  return List(Dtype.from_polars(polars_type.inner))
210
+ if isinstance(polars_type, pl.Enum):
211
+ return Enum(*polars_type.categories)
207
212
 
208
213
  return {
209
214
  pl.Int64: Int64(),
@@ -224,7 +229,6 @@ class Dtype:
224
229
  pl.Date: Date(),
225
230
  pl.Null: NullType(),
226
231
  pl.Duration: Duration(),
227
- pl.Enum: String(),
228
232
  }[polars_type.base_type()]
229
233
 
230
234
  def to_sql(self):
@@ -293,6 +297,9 @@ class Dtype:
293
297
  if isinstance(self, List):
294
298
  raise TypeError("pandas doesn't have a native list dtype")
295
299
 
300
+ if isinstance(self, Enum):
301
+ return pd.CategoricalDtype(self.categories)
302
+
296
303
  return {
297
304
  Int(): pd.Int64Dtype(), # we default to 64 bit
298
305
  Int8(): pd.Int8Dtype(),
@@ -319,6 +326,9 @@ class Dtype:
319
326
  """Convert this Dtype to a PyArrow type."""
320
327
  import pyarrow as pa
321
328
 
329
+ if isinstance(self, Enum):
330
+ return pa.string()
331
+
322
332
  return {
323
333
  Int(): pa.int64(), # we default to 64 bit
324
334
  Int8(): pa.int8(),
@@ -463,3 +473,36 @@ class List(Dtype):
463
473
  import pyarrow as pa
464
474
 
465
475
  return pa.list_(self.inner.to_arrow())
476
+
477
+
478
+ class Enum(String):
479
+ def __init__(self, *categories: str):
480
+ if not all(isinstance(c, str) for c in categories):
481
+ raise TypeError("arguments for `Enum` must have type `str`")
482
+ self.categories = list(categories)
483
+
484
+ def __eq__(self, rhs):
485
+ return isinstance(rhs, Enum) and self.categories == rhs.categories
486
+
487
+ def __repr__(self) -> str:
488
+ return f"Enum[{', '.join(repr(c) for c in self.categories)}]"
489
+
490
+ def __hash__(self):
491
+ return hash(tuple(self.categories))
492
+
493
+ def to_polars(self):
494
+ import polars as pl
495
+
496
+ return pl.Enum(self.categories)
497
+
498
+ def to_sql(self):
499
+ import sqlalchemy as sqa
500
+
501
+ return sqa.String()
502
+
503
+ def to_arrow(self):
504
+ import pyarrow as pa
505
+
506
+ # There is also pa.dictionary(), which seems to be kind of similar to an enum.
507
+ # Maybe it is better to convert to this.
508
+ return pa.string()
@@ -21,9 +21,13 @@ from pydiverse.common import (
21
21
  Bool,
22
22
  Date,
23
23
  Datetime,
24
+ Decimal,
24
25
  Dtype,
26
+ Enum,
27
+ Float,
25
28
  Float32,
26
29
  Float64,
30
+ Int,
27
31
  Int8,
28
32
  Int16,
29
33
  Int32,
@@ -154,8 +158,11 @@ def test_dtype_to_pandas_pyarrow():
154
158
  def test_all_types_numpy(type_):
155
159
  if type_ is pdc.List:
156
160
  type_obj = type_(pdc.Int64())
161
+ elif type_ is pdc.Enum:
162
+ type_obj = type_("a", "b", "c")
157
163
  else:
158
164
  type_obj = type_()
165
+
159
166
  if type_ is pdc.NullType:
160
167
  with pytest.raises(TypeError, match="pandas doesn't have a native null dtype"):
161
168
  type_obj.to_pandas(PandasBackend.NUMPY)
@@ -166,14 +173,17 @@ def test_all_types_numpy(type_):
166
173
  with pytest.raises(TypeError, match="pandas doesn't have a native list dtype"):
167
174
  type_obj.to_pandas(PandasBackend.NUMPY)
168
175
  else:
176
+ acceptance_map = {
177
+ Float: Float64(),
178
+ Int: Int64(),
179
+ Decimal: Float64(),
180
+ Date: Datetime(),
181
+ }
182
+
169
183
  dst_type = type_obj.to_pandas(PandasBackend.NUMPY)
170
184
  back_type = Dtype.from_pandas(dst_type)
171
- if type_ is pdc.Decimal:
172
- assert isinstance(back_type, pdc.Float64)
173
- elif type_ is pdc.Date:
174
- assert isinstance(back_type, pdc.Datetime)
175
- else:
176
- assert isinstance(back_type, type_)
185
+
186
+ assert back_type == acceptance_map.get(type_, type_obj)
177
187
 
178
188
 
179
189
  @pytest.mark.skipif(np is None, reason="requires pandas, numpy, and pyarrow")
@@ -184,8 +194,17 @@ def test_all_types_numpy(type_):
184
194
  def test_all_types_arrow(type_):
185
195
  if type_ is pdc.List:
186
196
  type_obj = type_(pdc.Int64())
197
+ elif type_ is pdc.Enum:
198
+ type_obj = type_("a", "b", "c")
187
199
  else:
188
200
  type_obj = type_()
201
+
202
+ acceptance_map = {
203
+ Enum: String(),
204
+ Float: Float64(),
205
+ Int: Int64(),
206
+ }
207
+
189
208
  dst_type = type_obj.to_pandas(PandasBackend.ARROW)
190
209
  back_type = Dtype.from_pandas(dst_type)
191
- assert isinstance(back_type, type_)
210
+ assert back_type == acceptance_map.get(type_, type_obj)
@@ -9,8 +9,10 @@ from pydiverse.common import (
9
9
  Date,
10
10
  Datetime,
11
11
  Dtype,
12
+ Float,
12
13
  Float32,
13
14
  Float64,
15
+ Int,
14
16
  Int8,
15
17
  Int16,
16
18
  Int32,
@@ -95,6 +97,12 @@ def test_all_types(type_):
95
97
  type_obj = type_(pdc.Int64())
96
98
  else:
97
99
  type_obj = type_()
100
+
101
+ acceptance_map = {
102
+ Float: Float64(),
103
+ Int: Int64(),
104
+ }
105
+
98
106
  dst_type = type_obj.to_polars()
99
107
  back_type = Dtype.from_polars(dst_type)
100
- assert isinstance(back_type, type_)
108
+ assert back_type == acceptance_map.get(type_, type_obj)
@@ -15,8 +15,11 @@ from pydiverse.common import (
15
15
  Date,
16
16
  Datetime,
17
17
  Dtype,
18
+ Enum,
19
+ Float,
18
20
  Float32,
19
21
  Float64,
22
+ Int,
20
23
  Int8,
21
24
  Int16,
22
25
  Int32,
@@ -92,7 +95,7 @@ def test_dtype_to_pyarrow():
92
95
  assert_conversion(Datetime(), pa.timestamp("us"))
93
96
 
94
97
 
95
- @pytest.mark.skipif(pa is None, reason="requires pandas, numpy, and pyarrow")
98
+ @pytest.mark.skipif(pa is None, reason="requires pyarrow")
96
99
  @pytest.mark.parametrize(
97
100
  "type_",
98
101
  ALL_TYPES,
@@ -100,8 +103,18 @@ def test_dtype_to_pyarrow():
100
103
  def test_all_types(type_):
101
104
  if type_ is pdc.List:
102
105
  type_obj = type_(pdc.Int64())
106
+ elif type_ is pdc.Enum:
107
+ type_obj = type_("a", "b", "c")
103
108
  else:
104
109
  type_obj = type_()
110
+
111
+ acceptance_map = {
112
+ Enum: String(),
113
+ Float: Float64(),
114
+ Int: Int64(),
115
+ }
116
+
105
117
  dst_type = type_obj.to_arrow()
106
118
  back_type = Dtype.from_arrow(dst_type)
107
- assert isinstance(back_type, type_)
119
+
120
+ assert back_type == acceptance_map.get(type_, type_obj)
@@ -9,8 +9,11 @@ from pydiverse.common import (
9
9
  Datetime,
10
10
  Decimal,
11
11
  Dtype,
12
+ Enum,
13
+ Float,
12
14
  Float32,
13
15
  Float64,
16
+ Int,
14
17
  Int8,
15
18
  Int16,
16
19
  Int32,
@@ -82,7 +85,7 @@ def test_dtype_to_sqlalchemy():
82
85
  assert_conversion(Datetime(), sa.DateTime)
83
86
 
84
87
 
85
- @pytest.mark.skipif(sa is None, reason="requires polars")
88
+ @pytest.mark.skipif(sa is None, reason="requires sqlalchemy")
86
89
  @pytest.mark.parametrize(
87
90
  "type_",
88
91
  ALL_TYPES,
@@ -90,19 +93,25 @@ def test_dtype_to_sqlalchemy():
90
93
  def test_all_types(type_):
91
94
  if type_ is pdc.List:
92
95
  type_obj = type_(pdc.Int64())
96
+ elif type_ is pdc.Enum:
97
+ type_obj = type_("a", "b", "c")
93
98
  else:
94
99
  type_obj = type_()
95
100
  dst_type = type_obj.to_sql()
96
101
  back_type = Dtype.from_sql(dst_type)
97
102
  acceptance_map = {
98
103
  # SQL is a bit less strict about integer precisions
99
- Int8: Int16,
100
- UInt8: Int16,
101
- UInt16: Int32,
102
- UInt32: Int64,
103
- UInt64: Int64,
104
+ Int8: Int16(),
105
+ UInt8: Int16(),
106
+ UInt16: Int32(),
107
+ UInt32: Int64(),
108
+ UInt64: Int64(),
104
109
  # we intentionally fetch Decimal as Float since Decimal is more a relational
105
110
  # database thing
106
- Decimal: Float64,
111
+ Decimal: Float64(),
112
+ Float: Float64(),
113
+ Int: Int64(),
114
+ # there is no Enum
115
+ Enum: String(),
107
116
  }
108
- assert isinstance(back_type, acceptance_map.get(type_, type_))
117
+ assert back_type == acceptance_map.get(type_, type_obj)