dataframely 1.3.1__tar.gz → 1.5.0__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 (169) hide show
  1. {dataframely-1.3.1 → dataframely-1.5.0}/.copier-answers.yml +1 -1
  2. dataframely-1.5.0/.gitattributes +1 -0
  3. {dataframely-1.3.1 → dataframely-1.5.0}/.github/workflows/build.yml +2 -0
  4. {dataframely-1.3.1 → dataframely-1.5.0}/.github/workflows/chore.yml +4 -4
  5. {dataframely-1.3.1 → dataframely-1.5.0}/.github/workflows/ci.yml +5 -2
  6. dataframely-1.5.0/.github/workflows/scorecard.yml +79 -0
  7. {dataframely-1.3.1 → dataframely-1.5.0}/PKG-INFO +3 -3
  8. dataframely-1.5.0/SECURITY.md +7 -0
  9. dataframely-1.5.0/dataframely/_deprecation.py +39 -0
  10. {dataframely-1.3.1 → dataframely-1.5.0}/dataframely/collection.py +8 -15
  11. {dataframely-1.3.1 → dataframely-1.5.0}/dataframely/columns/_base.py +77 -5
  12. {dataframely-1.3.1 → dataframely-1.5.0}/dataframely/columns/any.py +17 -3
  13. {dataframely-1.3.1 → dataframely-1.5.0}/dataframely/columns/array.py +17 -3
  14. {dataframely-1.3.1 → dataframely-1.5.0}/dataframely/columns/datetime.py +105 -20
  15. {dataframely-1.3.1 → dataframely-1.5.0}/dataframely/columns/decimal.py +21 -4
  16. {dataframely-1.3.1 → dataframely-1.5.0}/dataframely/columns/enum.py +21 -4
  17. {dataframely-1.3.1 → dataframely-1.5.0}/dataframely/columns/float.py +21 -4
  18. {dataframely-1.3.1 → dataframely-1.5.0}/dataframely/columns/integer.py +21 -4
  19. {dataframely-1.3.1 → dataframely-1.5.0}/dataframely/columns/list.py +21 -4
  20. {dataframely-1.3.1 → dataframely-1.5.0}/dataframely/columns/object.py +17 -3
  21. {dataframely-1.3.1 → dataframely-1.5.0}/dataframely/columns/string.py +21 -4
  22. {dataframely-1.3.1 → dataframely-1.5.0}/dataframely/columns/struct.py +21 -4
  23. {dataframely-1.3.1 → dataframely-1.5.0}/dataframely/failure.py +20 -12
  24. {dataframely-1.3.1 → dataframely-1.5.0}/dataframely/random.py +10 -2
  25. {dataframely-1.3.1 → dataframely-1.5.0}/docs/_api/dataframely.columns.rst +16 -0
  26. {dataframely-1.3.1 → dataframely-1.5.0}/docs/index.rst +1 -1
  27. {dataframely-1.3.1 → dataframely-1.5.0}/docs/sites/development.rst +1 -0
  28. dataframely-1.5.0/docs/sites/versioning.rst +20 -0
  29. {dataframely-1.3.1 → dataframely-1.5.0}/pixi.lock +3591 -3676
  30. {dataframely-1.3.1 → dataframely-1.5.0}/pixi.toml +1 -1
  31. {dataframely-1.3.1 → dataframely-1.5.0}/pyproject.toml +5 -4
  32. {dataframely-1.3.1 → dataframely-1.5.0}/tests/column_types/test_datetime.py +42 -2
  33. dataframely-1.5.0/tests/columns/test_check.py +68 -0
  34. {dataframely-1.3.1 → dataframely-1.5.0}/tests/columns/test_pyarrow.py +7 -0
  35. {dataframely-1.3.1 → dataframely-1.5.0}/tests/columns/test_sql_schema.py +2 -0
  36. dataframely-1.5.0/tests/test_deprecation.py +28 -0
  37. {dataframely-1.3.1 → dataframely-1.5.0}/tests/test_failure_info.py +33 -0
  38. {dataframely-1.3.1 → dataframely-1.5.0}/tests/test_typing.py +1 -1
  39. dataframely-1.3.1/.gitattributes +0 -1
  40. dataframely-1.3.1/tests/columns/test_check.py +0 -19
  41. {dataframely-1.3.1 → dataframely-1.5.0}/.envrc +0 -0
  42. {dataframely-1.3.1 → dataframely-1.5.0}/.github/CODEOWNERS +0 -0
  43. {dataframely-1.3.1 → dataframely-1.5.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  44. {dataframely-1.3.1 → dataframely-1.5.0}/.github/dependabot.yml +0 -0
  45. {dataframely-1.3.1 → dataframely-1.5.0}/.github/release-drafter.yml +0 -0
  46. {dataframely-1.3.1 → dataframely-1.5.0}/.gitignore +0 -0
  47. {dataframely-1.3.1 → dataframely-1.5.0}/.pre-commit-config.yaml +0 -0
  48. {dataframely-1.3.1 → dataframely-1.5.0}/.prettierignore +0 -0
  49. {dataframely-1.3.1 → dataframely-1.5.0}/.prettierrc +0 -0
  50. {dataframely-1.3.1 → dataframely-1.5.0}/.readthedocs.yml +0 -0
  51. {dataframely-1.3.1 → dataframely-1.5.0}/Cargo.lock +0 -0
  52. {dataframely-1.3.1 → dataframely-1.5.0}/Cargo.toml +0 -0
  53. {dataframely-1.3.1 → dataframely-1.5.0}/LICENSE +0 -0
  54. {dataframely-1.3.1 → dataframely-1.5.0}/README.md +0 -0
  55. {dataframely-1.3.1 → dataframely-1.5.0}/dataframely/__init__.py +0 -0
  56. {dataframely-1.3.1 → dataframely-1.5.0}/dataframely/_base_collection.py +0 -0
  57. {dataframely-1.3.1 → dataframely-1.5.0}/dataframely/_base_schema.py +0 -0
  58. {dataframely-1.3.1 → dataframely-1.5.0}/dataframely/_compat.py +0 -0
  59. {dataframely-1.3.1 → dataframely-1.5.0}/dataframely/_extre.pyi +0 -0
  60. {dataframely-1.3.1 → dataframely-1.5.0}/dataframely/_filter.py +0 -0
  61. {dataframely-1.3.1 → dataframely-1.5.0}/dataframely/_polars.py +0 -0
  62. {dataframely-1.3.1 → dataframely-1.5.0}/dataframely/_rule.py +0 -0
  63. {dataframely-1.3.1 → dataframely-1.5.0}/dataframely/_typing.py +0 -0
  64. {dataframely-1.3.1 → dataframely-1.5.0}/dataframely/_validation.py +0 -0
  65. {dataframely-1.3.1 → dataframely-1.5.0}/dataframely/columns/__init__.py +0 -0
  66. {dataframely-1.3.1 → dataframely-1.5.0}/dataframely/columns/_mixins.py +0 -0
  67. {dataframely-1.3.1 → dataframely-1.5.0}/dataframely/columns/_utils.py +0 -0
  68. {dataframely-1.3.1 → dataframely-1.5.0}/dataframely/columns/bool.py +0 -0
  69. {dataframely-1.3.1 → dataframely-1.5.0}/dataframely/config.py +0 -0
  70. {dataframely-1.3.1 → dataframely-1.5.0}/dataframely/exc.py +0 -0
  71. {dataframely-1.3.1 → dataframely-1.5.0}/dataframely/functional.py +0 -0
  72. {dataframely-1.3.1 → dataframely-1.5.0}/dataframely/mypy.py +0 -0
  73. {dataframely-1.3.1 → dataframely-1.5.0}/dataframely/py.typed +0 -0
  74. {dataframely-1.3.1 → dataframely-1.5.0}/dataframely/schema.py +0 -0
  75. {dataframely-1.3.1 → dataframely-1.5.0}/dataframely/testing/__init__.py +0 -0
  76. {dataframely-1.3.1 → dataframely-1.5.0}/dataframely/testing/const.py +0 -0
  77. {dataframely-1.3.1 → dataframely-1.5.0}/dataframely/testing/factory.py +0 -0
  78. {dataframely-1.3.1 → dataframely-1.5.0}/dataframely/testing/mask.py +0 -0
  79. {dataframely-1.3.1 → dataframely-1.5.0}/dataframely/testing/rules.py +0 -0
  80. {dataframely-1.3.1 → dataframely-1.5.0}/dataframely/testing/typing.py +0 -0
  81. {dataframely-1.3.1 → dataframely-1.5.0}/docker-compose.yml +0 -0
  82. {dataframely-1.3.1 → dataframely-1.5.0}/docs/Makefile +0 -0
  83. {dataframely-1.3.1 → dataframely-1.5.0}/docs/_api/dataframely.collection.rst +0 -0
  84. {dataframely-1.3.1 → dataframely-1.5.0}/docs/_api/dataframely.columns.any.rst +0 -0
  85. {dataframely-1.3.1 → dataframely-1.5.0}/docs/_api/dataframely.columns.bool.rst +0 -0
  86. {dataframely-1.3.1 → dataframely-1.5.0}/docs/_api/dataframely.columns.datetime.rst +0 -0
  87. {dataframely-1.3.1 → dataframely-1.5.0}/docs/_api/dataframely.columns.decimal.rst +0 -0
  88. {dataframely-1.3.1 → dataframely-1.5.0}/docs/_api/dataframely.columns.enum.rst +0 -0
  89. {dataframely-1.3.1 → dataframely-1.5.0}/docs/_api/dataframely.columns.float.rst +0 -0
  90. {dataframely-1.3.1 → dataframely-1.5.0}/docs/_api/dataframely.columns.integer.rst +0 -0
  91. {dataframely-1.3.1 → dataframely-1.5.0}/docs/_api/dataframely.columns.list.rst +0 -0
  92. {dataframely-1.3.1 → dataframely-1.5.0}/docs/_api/dataframely.columns.string.rst +0 -0
  93. {dataframely-1.3.1 → dataframely-1.5.0}/docs/_api/dataframely.columns.struct.rst +0 -0
  94. {dataframely-1.3.1 → dataframely-1.5.0}/docs/_api/dataframely.config.rst +0 -0
  95. {dataframely-1.3.1 → dataframely-1.5.0}/docs/_api/dataframely.exc.rst +0 -0
  96. {dataframely-1.3.1 → dataframely-1.5.0}/docs/_api/dataframely.failure.rst +0 -0
  97. {dataframely-1.3.1 → dataframely-1.5.0}/docs/_api/dataframely.functional.rst +0 -0
  98. {dataframely-1.3.1 → dataframely-1.5.0}/docs/_api/dataframely.mypy.rst +0 -0
  99. {dataframely-1.3.1 → dataframely-1.5.0}/docs/_api/dataframely.random.rst +0 -0
  100. {dataframely-1.3.1 → dataframely-1.5.0}/docs/_api/dataframely.rst +0 -0
  101. {dataframely-1.3.1 → dataframely-1.5.0}/docs/_api/dataframely.schema.rst +0 -0
  102. {dataframely-1.3.1 → dataframely-1.5.0}/docs/_api/dataframely.testing.const.rst +0 -0
  103. {dataframely-1.3.1 → dataframely-1.5.0}/docs/_api/dataframely.testing.factory.rst +0 -0
  104. {dataframely-1.3.1 → dataframely-1.5.0}/docs/_api/dataframely.testing.mask.rst +0 -0
  105. {dataframely-1.3.1 → dataframely-1.5.0}/docs/_api/dataframely.testing.rst +0 -0
  106. {dataframely-1.3.1 → dataframely-1.5.0}/docs/_api/dataframely.testing.rules.rst +0 -0
  107. {dataframely-1.3.1 → dataframely-1.5.0}/docs/_api/dataframely.testing.typing.rst +0 -0
  108. {dataframely-1.3.1 → dataframely-1.5.0}/docs/_api/modules.rst +0 -0
  109. {dataframely-1.3.1 → dataframely-1.5.0}/docs/_static/custom.css +0 -0
  110. {dataframely-1.3.1 → dataframely-1.5.0}/docs/_static/favicon.ico +0 -0
  111. {dataframely-1.3.1 → dataframely-1.5.0}/docs/conf.py +0 -0
  112. {dataframely-1.3.1 → dataframely-1.5.0}/docs/make.bat +0 -0
  113. {dataframely-1.3.1 → dataframely-1.5.0}/docs/sites/examples/real-world.ipynb +0 -0
  114. {dataframely-1.3.1 → dataframely-1.5.0}/docs/sites/faq.rst +0 -0
  115. {dataframely-1.3.1 → dataframely-1.5.0}/docs/sites/installation.rst +0 -0
  116. {dataframely-1.3.1 → dataframely-1.5.0}/docs/sites/quickstart.rst +0 -0
  117. {dataframely-1.3.1 → dataframely-1.5.0}/src/errdefs.rs +0 -0
  118. {dataframely-1.3.1 → dataframely-1.5.0}/src/lib.rs +0 -0
  119. {dataframely-1.3.1 → dataframely-1.5.0}/src/regex_repr.rs +0 -0
  120. {dataframely-1.3.1 → dataframely-1.5.0}/tests/collection/test_base.py +0 -0
  121. {dataframely-1.3.1 → dataframely-1.5.0}/tests/collection/test_cast.py +0 -0
  122. {dataframely-1.3.1 → dataframely-1.5.0}/tests/collection/test_create_empty.py +0 -0
  123. {dataframely-1.3.1 → dataframely-1.5.0}/tests/collection/test_filter_one_to_n.py +0 -0
  124. {dataframely-1.3.1 → dataframely-1.5.0}/tests/collection/test_filter_validate.py +0 -0
  125. {dataframely-1.3.1 → dataframely-1.5.0}/tests/collection/test_ignore_in_filter.py +0 -0
  126. {dataframely-1.3.1 → dataframely-1.5.0}/tests/collection/test_implementation.py +0 -0
  127. {dataframely-1.3.1 → dataframely-1.5.0}/tests/collection/test_optional_members.py +0 -0
  128. {dataframely-1.3.1 → dataframely-1.5.0}/tests/collection/test_sample.py +0 -0
  129. {dataframely-1.3.1 → dataframely-1.5.0}/tests/collection/test_validate_input.py +0 -0
  130. {dataframely-1.3.1 → dataframely-1.5.0}/tests/column_types/__init__.py +0 -0
  131. {dataframely-1.3.1 → dataframely-1.5.0}/tests/column_types/test_any.py +0 -0
  132. {dataframely-1.3.1 → dataframely-1.5.0}/tests/column_types/test_array.py +0 -0
  133. {dataframely-1.3.1 → dataframely-1.5.0}/tests/column_types/test_decimal.py +0 -0
  134. {dataframely-1.3.1 → dataframely-1.5.0}/tests/column_types/test_enum.py +0 -0
  135. {dataframely-1.3.1 → dataframely-1.5.0}/tests/column_types/test_float.py +0 -0
  136. {dataframely-1.3.1 → dataframely-1.5.0}/tests/column_types/test_integer.py +0 -0
  137. {dataframely-1.3.1 → dataframely-1.5.0}/tests/column_types/test_list.py +0 -0
  138. {dataframely-1.3.1 → dataframely-1.5.0}/tests/column_types/test_object.py +0 -0
  139. {dataframely-1.3.1 → dataframely-1.5.0}/tests/column_types/test_string.py +0 -0
  140. {dataframely-1.3.1 → dataframely-1.5.0}/tests/column_types/test_struct.py +0 -0
  141. {dataframely-1.3.1 → dataframely-1.5.0}/tests/columns/__init__.py +0 -0
  142. {dataframely-1.3.1 → dataframely-1.5.0}/tests/columns/test_alias.py +0 -0
  143. {dataframely-1.3.1 → dataframely-1.5.0}/tests/columns/test_default_dtypes.py +0 -0
  144. {dataframely-1.3.1 → dataframely-1.5.0}/tests/columns/test_metadata.py +0 -0
  145. {dataframely-1.3.1 → dataframely-1.5.0}/tests/columns/test_polars_schema.py +0 -0
  146. {dataframely-1.3.1 → dataframely-1.5.0}/tests/columns/test_rules.py +0 -0
  147. {dataframely-1.3.1 → dataframely-1.5.0}/tests/columns/test_sample.py +0 -0
  148. {dataframely-1.3.1 → dataframely-1.5.0}/tests/columns/test_str.py +0 -0
  149. {dataframely-1.3.1 → dataframely-1.5.0}/tests/columns/test_utils.py +0 -0
  150. {dataframely-1.3.1 → dataframely-1.5.0}/tests/core_validation/__init__.py +0 -0
  151. {dataframely-1.3.1 → dataframely-1.5.0}/tests/core_validation/test_column_validation.py +0 -0
  152. {dataframely-1.3.1 → dataframely-1.5.0}/tests/core_validation/test_dtype_validation.py +0 -0
  153. {dataframely-1.3.1 → dataframely-1.5.0}/tests/core_validation/test_rule_evaluation.py +0 -0
  154. {dataframely-1.3.1 → dataframely-1.5.0}/tests/functional/test_concat.py +0 -0
  155. {dataframely-1.3.1 → dataframely-1.5.0}/tests/functional/test_relationships.py +0 -0
  156. {dataframely-1.3.1 → dataframely-1.5.0}/tests/schema/test_base.py +0 -0
  157. {dataframely-1.3.1 → dataframely-1.5.0}/tests/schema/test_cast.py +0 -0
  158. {dataframely-1.3.1 → dataframely-1.5.0}/tests/schema/test_create_empty.py +0 -0
  159. {dataframely-1.3.1 → dataframely-1.5.0}/tests/schema/test_create_empty_if_none.py +0 -0
  160. {dataframely-1.3.1 → dataframely-1.5.0}/tests/schema/test_filter.py +0 -0
  161. {dataframely-1.3.1 → dataframely-1.5.0}/tests/schema/test_inheritance.py +0 -0
  162. {dataframely-1.3.1 → dataframely-1.5.0}/tests/schema/test_rule_implementation.py +0 -0
  163. {dataframely-1.3.1 → dataframely-1.5.0}/tests/schema/test_sample.py +0 -0
  164. {dataframely-1.3.1 → dataframely-1.5.0}/tests/schema/test_validate.py +0 -0
  165. {dataframely-1.3.1 → dataframely-1.5.0}/tests/test_compat.py +0 -0
  166. {dataframely-1.3.1 → dataframely-1.5.0}/tests/test_config.py +0 -0
  167. {dataframely-1.3.1 → dataframely-1.5.0}/tests/test_exc.py +0 -0
  168. {dataframely-1.3.1 → dataframely-1.5.0}/tests/test_extre.py +0 -0
  169. {dataframely-1.3.1 → dataframely-1.5.0}/tests/test_random.py +0 -0
@@ -1,5 +1,5 @@
1
1
  # This file is managed by Copier; DO NOT EDIT OR REMOVE.
2
- _commit: v0.3.0
2
+ _commit: v0.4.1
3
3
  _src_path: https://github.com/quantco/copier-template-python-open-source
4
4
  add_autobump_workflow: false
5
5
  author_email: oliver.borchert@quantco.com
@@ -0,0 +1 @@
1
+ pixi.lock merge=binary linguist-language=YAML linguist-generated=true
@@ -10,6 +10,8 @@ jobs:
10
10
  build-sdist:
11
11
  name: Build Sdist
12
12
  runs-on: ubuntu-latest
13
+ permissions:
14
+ contents: read
13
15
  steps:
14
16
  - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
15
17
  with:
@@ -21,14 +21,14 @@ jobs:
21
21
  steps:
22
22
  - name: Check valid conventional commit message
23
23
  id: lint
24
- uses: amannn/action-semantic-pull-request@v5
24
+ uses: amannn/action-semantic-pull-request@0723387faaf9b38adef4775cd42cfd5155ed6017 # v5.5.3
25
25
  with:
26
26
  subjectPattern: ^[A-Z].+[^. ]$ # subject must start with uppercase letter and may not end with a dot/space
27
27
  env:
28
28
  GITHUB_TOKEN: ${{ github.token }}
29
29
  - name: Post comment about invalid PR title
30
30
  if: failure()
31
- uses: marocchino/sticky-pull-request-comment@v2
31
+ uses: marocchino/sticky-pull-request-comment@52423e01640425a022ef5fd42c6fb5f633a02728 # v2.9.1
32
32
  with:
33
33
  header: conventional-commit-pr-title
34
34
  message: |
@@ -45,7 +45,7 @@ jobs:
45
45
  </details>
46
46
  - name: Delete comment about invalid PR title
47
47
  if: success()
48
- uses: marocchino/sticky-pull-request-comment@v2
48
+ uses: marocchino/sticky-pull-request-comment@52423e01640425a022ef5fd42c6fb5f633a02728 # v2.9.1
49
49
  with:
50
50
  header: conventional-commit-pr-title
51
51
  delete: true
@@ -58,7 +58,7 @@ jobs:
58
58
  pull-requests: write
59
59
  steps:
60
60
  - name: ${{ github.event_name == 'pull_request_target' && 'Assign labels' || 'Update release draft' }}
61
- uses: release-drafter/release-drafter@v6
61
+ uses: release-drafter/release-drafter@b1476f6e6eb133afa41ed8589daba6dc69b4d3f5 # v6.1.0
62
62
  with:
63
63
  disable-releaser: ${{ github.event_name == 'pull_request_target' }}
64
64
  disable-autolabeler: ${{ github.event_name == 'push' }}
@@ -9,6 +9,9 @@ concurrency:
9
9
  group: ${{ github.workflow }}-${{ github.ref }}
10
10
  cancel-in-progress: true
11
11
 
12
+ permissions:
13
+ contents: read
14
+
12
15
  jobs:
13
16
  pre-commit-checks:
14
17
  name: Pre-commit Checks
@@ -40,7 +43,7 @@ jobs:
40
43
  environment: [py311, py312, py313]
41
44
  steps:
42
45
  - name: Checkout branch
43
- uses: actions/checkout@v4
46
+ uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
44
47
  - name: Set up pixi
45
48
  uses: prefix-dev/setup-pixi@19eac09b398e3d0c747adc7921926a6d802df4da # v0.8.8
46
49
  with:
@@ -50,7 +53,7 @@ jobs:
50
53
  - name: Run pytest
51
54
  run: pixi run -e ${{ matrix.environment }} test-coverage --color=yes
52
55
  - name: Upload codecov
53
- uses: codecov/codecov-action@v5
56
+ uses: codecov/codecov-action@18283e04ce6e62d37312384ff67231eb8fd56d24 # v5.4.3
54
57
  with:
55
58
  files: ./coverage.xml
56
59
  token: ${{ secrets.CODECOV_TOKEN }}
@@ -0,0 +1,79 @@
1
+ # This workflow uses actions that are not certified by GitHub. They are provided
2
+ # by a third-party and are governed by separate terms of service, privacy
3
+ # policy, and support documentation.
4
+
5
+ name: Scorecard supply-chain security
6
+ on:
7
+ # For Branch-Protection check. Only the default branch is supported. See
8
+ # https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection
9
+ branch_protection_rule:
10
+ # To guarantee Maintained check is occasionally updated. See
11
+ # https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained
12
+ schedule:
13
+ - cron: "34 5 * * 0"
14
+ workflow_dispatch:
15
+ push:
16
+ branches: ["main"]
17
+
18
+ # Declare default permissions as read only.
19
+ permissions: read-all
20
+
21
+ jobs:
22
+ analysis:
23
+ name: Scorecard analysis
24
+ runs-on: ubuntu-latest
25
+ # `publish_results: true` only works when run from the default branch. conditional can be removed if disabled.
26
+ if: (github.event.repository.default_branch == github.ref_name || github.event_name == 'pull_request') && github.repository == 'quantco/dataframely'
27
+ permissions:
28
+ # Needed to upload the results to code-scanning dashboard.
29
+ security-events: write
30
+ # Needed to publish results and get a badge (see publish_results below).
31
+ id-token: write
32
+ # Uncomment the permissions below if installing in a private repository.
33
+ # contents: read
34
+ # actions: read
35
+
36
+ steps:
37
+ - name: "Checkout code"
38
+ uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
39
+ with:
40
+ persist-credentials: false
41
+
42
+ - name: "Run analysis"
43
+ uses: ossf/scorecard-action@05b42c624433fc40578a4040d5cf5e36ddca8cde # v2.4.2
44
+ with:
45
+ results_file: results.sarif
46
+ results_format: sarif
47
+ # (Optional) "write" PAT token. Uncomment the `repo_token` line below if:
48
+ # - you want to enable the Branch-Protection check on a *public* repository, or
49
+ # - you are installing Scorecard on a *private* repository
50
+ # To create the PAT, follow the steps in https://github.com/ossf/scorecard-action?tab=readme-ov-file#authentication-with-fine-grained-pat-optional.
51
+ # repo_token: ${{ secrets.SCORECARD_TOKEN }}
52
+
53
+ # Public repositories:
54
+ # - Publish results to OpenSSF REST API for easy access by consumers
55
+ # - Allows the repository to include the Scorecard badge.
56
+ # - See https://github.com/ossf/scorecard-action#publishing-results.
57
+ # For private repositories:
58
+ # - `publish_results` will always be set to `false`, regardless
59
+ # of the value entered here.
60
+ publish_results: true
61
+
62
+ # (Optional) Uncomment file_mode if you have a .gitattributes with files marked export-ignore
63
+ # file_mode: git
64
+
65
+ # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
66
+ # format to the repository Actions tab.
67
+ - name: "Upload artifact"
68
+ uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
69
+ with:
70
+ name: SARIF file
71
+ path: results.sarif
72
+ retention-days: 5
73
+
74
+ # Upload the results to GitHub's code scanning dashboard (optional).
75
+ # Commenting out will disable upload of results to your repo's Code Scanning dashboard
76
+ - name: "Upload to code-scanning"
77
+ uses: github/codeql-action/upload-sarif@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18
78
+ with:
79
+ sarif_file: results.sarif
@@ -1,19 +1,19 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dataframely
3
- Version: 1.3.1
3
+ Version: 1.5.0
4
4
  Classifier: Programming Language :: Python :: 3
5
5
  Classifier: Programming Language :: Python :: 3.11
6
6
  Classifier: Programming Language :: Python :: 3.12
7
7
  Classifier: Programming Language :: Python :: 3.13
8
8
  Requires-Dist: numpy
9
- Requires-Dist: polars>=1.12
9
+ Requires-Dist: polars>=1.30
10
10
  License-File: LICENSE
11
11
  Summary: A declarative, polars-native data frame validation library
12
12
  Author-email: Andreas Albert <andreas.albert@quantco.com>, Daniel Elsner <daniel.elsner@quantco.com>, Oliver Borchert <oliver.borchert@quantco.com>
13
13
  Requires-Python: >=3.11
14
14
  Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
15
- Project-URL: Repository, https://github.com/quantco/dataframely
16
15
  Project-URL: Documentation, https://dataframely.readthedocs.io/
16
+ Project-URL: Repository, https://github.com/quantco/dataframely
17
17
 
18
18
  <!-- LOGO -->
19
19
  <br />
@@ -0,0 +1,7 @@
1
+ # Reporting Security Issues
2
+
3
+ We take security bugs in our projects seriously. We appreciate your efforts to responsibly disclose your findings, and will make every effort to acknowledge your contributions.
4
+
5
+ To report a security issue, please use the GitHub Security Advisory ["Report a Vulnerability"](https://github.com/quantco/dataframely/security/advisories/new) tab.
6
+
7
+ We will send a response indicating the next steps in handling your report. After the initial reply to your report, the security team will keep you informed of the progress towards a fix and full announcement, and may ask for additional information or guidance.
@@ -0,0 +1,39 @@
1
+ # Copyright (c) QuantCo 2025-2025
2
+ # SPDX-License-Identifier: BSD-3-Clause
3
+
4
+ import os
5
+ import warnings
6
+ from collections.abc import Callable
7
+ from functools import wraps
8
+
9
+ TRUTHY_VALUES = ["1", "true"]
10
+
11
+
12
+ def skip_if(env: str) -> Callable:
13
+ """Decorator to skip warnings based on environment variable.
14
+
15
+ If the environment variable is equivalent to any of TRUTHY_VALUES, the wrapped
16
+ function is skipped.
17
+ """
18
+
19
+ def decorator(fun: Callable) -> Callable:
20
+ @wraps(fun)
21
+ def wrapper() -> None:
22
+ if os.getenv(env, "").lower() in TRUTHY_VALUES:
23
+ return
24
+ fun()
25
+
26
+ return wrapper
27
+
28
+ return decorator
29
+
30
+
31
+ @skip_if(env="DATAFRAMELY_NO_FUTURE_WARNINGS")
32
+ def warn_nullable_default_change() -> None:
33
+ warnings.warn(
34
+ "The 'nullable' argument was not explicitly set. In a future release, "
35
+ "'nullable=False' will be the default if 'nullable' is not specified. "
36
+ "Explicitly set 'nullable=True' if you want your column to be nullable.",
37
+ FutureWarning,
38
+ stacklevel=4,
39
+ )
@@ -1,12 +1,11 @@
1
1
  # Copyright (c) QuantCo 2025-2025
2
2
  # SPDX-License-Identifier: BSD-3-Clause
3
3
 
4
- import sys
5
4
  import warnings
6
5
  from abc import ABC
7
6
  from collections.abc import Mapping, Sequence
8
7
  from pathlib import Path
9
- from typing import Any, Generic, Self, TypeVar, cast
8
+ from typing import Any, Self, cast
10
9
 
11
10
  import polars as pl
12
11
  import polars.exceptions as plexc
@@ -18,15 +17,8 @@ from ._polars import FrameType, join_all_inner, join_all_outer
18
17
  from .failure import FailureInfo
19
18
  from .random import Generator
20
19
 
21
- if sys.version_info >= (3, 13):
22
- SamplingType = TypeVar(
23
- "SamplingType", bound=Mapping[str, Any], default=Mapping[str, Any]
24
- )
25
- else: # pragma: no cover
26
- SamplingType = TypeVar("SamplingType", bound=Mapping[str, Any])
27
20
 
28
-
29
- class Collection(BaseCollection, ABC, Generic[SamplingType]):
21
+ class Collection(BaseCollection, ABC):
30
22
  """Base class for all collections of data frames with a predefined schema.
31
23
 
32
24
  A collection is comprised of a set of *members* which are collectively "consistent",
@@ -86,7 +78,7 @@ class Collection(BaseCollection, ABC, Generic[SamplingType]):
86
78
  cls,
87
79
  num_rows: int | None = None,
88
80
  *,
89
- overrides: Sequence[SamplingType] | None = None,
81
+ overrides: Sequence[Mapping[str, Any]] | None = None,
90
82
  generator: Generator | None = None,
91
83
  ) -> Self:
92
84
  """Create a random sample from the members of this collection.
@@ -162,10 +154,11 @@ class Collection(BaseCollection, ABC, Generic[SamplingType]):
162
154
  samples = (
163
155
  overrides
164
156
  if overrides is not None
165
- else [cast(SamplingType, {}) for _ in range(cast(int, num_rows))]
157
+ else [{} for _ in range(cast(int, num_rows))]
166
158
  )
167
159
  processed_samples = [
168
- cls._preprocess_sample(sample, i, g) for i, sample in enumerate(samples)
160
+ cls._preprocess_sample(dict(sample.items()), i, g)
161
+ for i, sample in enumerate(samples)
169
162
  ]
170
163
 
171
164
  # 2) Ensure that all samples have primary keys assigned to ensure that we
@@ -234,8 +227,8 @@ class Collection(BaseCollection, ABC, Generic[SamplingType]):
234
227
 
235
228
  @classmethod
236
229
  def _preprocess_sample(
237
- cls, sample: SamplingType, index: int, generator: Generator
238
- ) -> SamplingType:
230
+ cls, sample: dict[str, Any], index: int, generator: Generator
231
+ ) -> dict[str, Any]:
239
232
  """Overridable method to preprocess a sample passed to :meth:`sample`.
240
233
 
241
234
  The purpose of this method is to (1) set the primary key columns to enable
@@ -4,12 +4,14 @@
4
4
  from __future__ import annotations
5
5
 
6
6
  from abc import ABC, abstractmethod
7
+ from collections import Counter
7
8
  from collections.abc import Callable
8
9
  from typing import Any
9
10
 
10
11
  import polars as pl
11
12
 
12
13
  from dataframely._compat import pa, sa, sa_TypeEngine
14
+ from dataframely._deprecation import warn_nullable_default_change
13
15
  from dataframely._polars import PolarsDataType
14
16
  from dataframely.random import Generator
15
17
 
@@ -28,19 +30,36 @@ class Column(ABC):
28
30
  def __init__(
29
31
  self,
30
32
  *,
31
- nullable: bool = True,
33
+ nullable: bool | None = None,
32
34
  primary_key: bool = False,
33
- check: Callable[[pl.Expr], pl.Expr] | None = None,
35
+ check: (
36
+ Callable[[pl.Expr], pl.Expr]
37
+ | list[Callable[[pl.Expr], pl.Expr]]
38
+ | dict[str, Callable[[pl.Expr], pl.Expr]]
39
+ | None
40
+ ) = None,
34
41
  alias: str | None = None,
35
42
  metadata: dict[str, Any] | None = None,
36
43
  ):
37
44
  """
38
45
  Args:
39
46
  nullable: Whether this column may contain null values.
47
+ Explicitly set `nullable=True` if you want your column to be nullable.
48
+ In a future release, `nullable=False` will be the default if `nullable`
49
+ is not specified.
40
50
  primary_key: Whether this column is part of the primary key of the schema.
41
51
  If ``True``, ``nullable`` is automatically set to ``False``.
42
- check: A custom check to run for this column. Must return a non-aggregated
43
- boolean expression.
52
+ check: A custom rule or multiple rules to run for this column. This can be:
53
+ - A single callable that returns a non-aggregated boolean expression.
54
+ The name of the rule is derived from the callable name, or defaults to
55
+ "check" for lambdas.
56
+ - A list of callables, where each callable returns a non-aggregated
57
+ boolean expression. The name of the rule is derived from the callable
58
+ name, or defaults to "check" for lambdas. Where multiple rules result
59
+ in the same name, the suffix __i is appended to the name.
60
+ - A dictionary mapping rule names to callables, where each callable
61
+ returns a non-aggregated boolean expression.
62
+ All rule names provided here are given the prefix "check_".
44
63
  alias: An overwrite for this column's name which allows for using a column
45
64
  name that is not a valid Python identifier. Especially note that setting
46
65
  this option does _not_ allow to refer to the column with two different
@@ -48,6 +67,10 @@ class Column(ABC):
48
67
  internally sets the alias to the column's name in the parent schema.
49
68
  metadata: A dictionary of metadata to attach to the column.
50
69
  """
70
+ if nullable is None:
71
+ warn_nullable_default_change()
72
+ nullable = True
73
+
51
74
  self.nullable = nullable and not primary_key
52
75
  self.primary_key = primary_key
53
76
  self.check = check
@@ -96,10 +119,59 @@ class Column(ABC):
96
119
  result = {}
97
120
  if not self.nullable:
98
121
  result["nullability"] = expr.is_not_null()
122
+
99
123
  if self.check is not None:
100
- result["check"] = self.check(expr)
124
+ if isinstance(self.check, dict):
125
+ for rule_name, rule_callable in self.check.items():
126
+ result[f"check__{rule_name}"] = rule_callable(expr)
127
+ else:
128
+ list_of_rules = (
129
+ self.check if isinstance(self.check, list) else [self.check]
130
+ )
131
+ # Get unique names for rules from callables
132
+ rule_names = self._derive_check_rule_names(list_of_rules)
133
+ for rule_name, rule_callable in zip(rule_names, list_of_rules):
134
+ result[rule_name] = rule_callable(expr)
135
+
101
136
  return result
102
137
 
138
+ def _derive_check_rule_names(
139
+ self, rules: list[Callable[[pl.Expr], pl.Expr]]
140
+ ) -> list[str]:
141
+ """Generate unique names for rule callables.
142
+
143
+ For callables with the same name, appends a suffix __i where i is the index
144
+ of occurrence (starting from 0), but only if there are duplicates.
145
+
146
+ Args:
147
+ rules: List of rule callables.
148
+
149
+ Returns:
150
+ List of unique names corresponding to the rule callables.
151
+ """
152
+ base_names = [
153
+ f"check__{rule.__name__}" if rule.__name__ != "<lambda>" else "check"
154
+ for rule in rules
155
+ ]
156
+
157
+ # Count occurrences using Counter
158
+ name_counts = Counter(base_names)
159
+
160
+ # Append suffixes to names that are duplicated
161
+ final_names = []
162
+ duplicate_counter: dict[str, int] = {
163
+ name: 0 for name in name_counts if name_counts[name] > 1
164
+ }
165
+ for name in base_names:
166
+ if name_counts[name] > 1:
167
+ postfix = duplicate_counter[name]
168
+ final_names.append(f"{name}__{postfix}")
169
+ duplicate_counter[name] += 1
170
+ else:
171
+ final_names.append(name)
172
+
173
+ return final_names
174
+
103
175
  # -------------------------------------- SQL ------------------------------------- #
104
176
 
105
177
  def sqlalchemy_column(self, name: str, dialect: sa.Dialect) -> sa.Column:
@@ -25,14 +25,28 @@ class Any(Column):
25
25
  def __init__(
26
26
  self,
27
27
  *,
28
- check: Callable[[pl.Expr], pl.Expr] | None = None,
28
+ check: (
29
+ Callable[[pl.Expr], pl.Expr]
30
+ | list[Callable[[pl.Expr], pl.Expr]]
31
+ | dict[str, Callable[[pl.Expr], pl.Expr]]
32
+ | None
33
+ ) = None,
29
34
  alias: str | None = None,
30
35
  metadata: dict[str, Any] | None = None,
31
36
  ):
32
37
  """
33
38
  Args:
34
- check: A custom check to run for this column. Must return a non-aggregated
35
- boolean expression.
39
+ check: A custom rule or multiple rules to run for this column. This can be:
40
+ - A single callable that returns a non-aggregated boolean expression.
41
+ The name of the rule is derived from the callable name, or defaults to
42
+ "check" for lambdas.
43
+ - A list of callables, where each callable returns a non-aggregated
44
+ boolean expression. The name of the rule is derived from the callable
45
+ name, or defaults to "check" for lambdas. Where multiple rules result
46
+ in the same name, the suffix __i is appended to the name.
47
+ - A dictionary mapping rule names to callables, where each callable
48
+ returns a non-aggregated boolean expression.
49
+ All rule names provided here are given the prefix "check_".
36
50
  alias: An overwrite for this column's name which allows for using a column
37
51
  name that is not a valid Python identifier. Especially note that setting
38
52
  this option does _not_ allow to refer to the column with two different
@@ -28,7 +28,12 @@ class Array(Column):
28
28
  # polars doesn't yet support grouping by arrays,
29
29
  # see https://github.com/pola-rs/polars/issues/22574
30
30
  primary_key: Literal[False] = False,
31
- check: Callable[[pl.Expr], pl.Expr] | None = None,
31
+ check: (
32
+ Callable[[pl.Expr], pl.Expr]
33
+ | list[Callable[[pl.Expr], pl.Expr]]
34
+ | dict[str, Callable[[pl.Expr], pl.Expr]]
35
+ | None
36
+ ) = None,
32
37
  alias: str | None = None,
33
38
  metadata: dict[str, Any] | None = None,
34
39
  ):
@@ -39,8 +44,17 @@ class Array(Column):
39
44
  nullable: Whether this column may contain null values.
40
45
  primary_key: Whether this column is part of the primary key of the schema.
41
46
  Not yet supported for the Array type.
42
- check: A custom check to run for this column. Must return a non-aggregated
43
- boolean expression.
47
+ check: A custom rule or multiple rules to run for this column. This can be:
48
+ - A single callable that returns a non-aggregated boolean expression.
49
+ The name of the rule is derived from the callable name, or defaults to
50
+ "check" for lambdas.
51
+ - A list of callables, where each callable returns a non-aggregated
52
+ boolean expression. The name of the rule is derived from the callable
53
+ name, or defaults to "check" for lambdas. Where multiple rules result
54
+ in the same name, the suffix __i is appended to the name.
55
+ - A dictionary mapping rule names to callables, where each callable
56
+ returns a non-aggregated boolean expression.
57
+ All rule names provided here are given the prefix "check_".
44
58
  alias: An overwrite for this column's name which allows for using a column
45
59
  name that is not a valid Python identifier. Especially note that setting
46
60
  this option does _not_ allow to refer to the column with two different