diggity 0.1.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.
- diggity-0.1.0/.github/workflows/CI.yml +143 -0
- diggity-0.1.0/.gitignore +78 -0
- diggity-0.1.0/Cargo.lock +171 -0
- diggity-0.1.0/Cargo.toml +13 -0
- diggity-0.1.0/LICENSE +21 -0
- diggity-0.1.0/PKG-INFO +118 -0
- diggity-0.1.0/README.md +104 -0
- diggity-0.1.0/pyproject.toml +45 -0
- diggity-0.1.0/src/lib.rs +199 -0
- diggity-0.1.0/tests/test_all.py +101 -0
- diggity-0.1.0/uv.lock +208 -0
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- main
|
|
7
|
+
- master
|
|
8
|
+
tags:
|
|
9
|
+
- '*'
|
|
10
|
+
pull_request:
|
|
11
|
+
workflow_dispatch:
|
|
12
|
+
|
|
13
|
+
permissions:
|
|
14
|
+
contents: read
|
|
15
|
+
|
|
16
|
+
jobs:
|
|
17
|
+
linux:
|
|
18
|
+
runs-on: ${{ matrix.platform.runner }}
|
|
19
|
+
strategy:
|
|
20
|
+
matrix:
|
|
21
|
+
platform:
|
|
22
|
+
- runner: ubuntu-22.04
|
|
23
|
+
target: x86_64
|
|
24
|
+
- runner: ubuntu-22.04
|
|
25
|
+
target: x86
|
|
26
|
+
- runner: ubuntu-22.04
|
|
27
|
+
target: aarch64
|
|
28
|
+
- runner: ubuntu-22.04
|
|
29
|
+
target: armv7
|
|
30
|
+
steps:
|
|
31
|
+
- uses: actions/checkout@v4
|
|
32
|
+
- uses: actions/setup-python@v5
|
|
33
|
+
with:
|
|
34
|
+
python-version: 3.x
|
|
35
|
+
- name: Build wheels
|
|
36
|
+
uses: PyO3/maturin-action@v1
|
|
37
|
+
with:
|
|
38
|
+
target: ${{ matrix.platform.target }}
|
|
39
|
+
args: --release --out dist --find-interpreter
|
|
40
|
+
sccache: ${{ !startsWith(github.ref, 'refs/tags/') }}
|
|
41
|
+
manylinux: auto
|
|
42
|
+
- name: Upload wheels
|
|
43
|
+
uses: actions/upload-artifact@v4
|
|
44
|
+
with:
|
|
45
|
+
name: wheels-linux-${{ matrix.platform.target }}
|
|
46
|
+
path: dist
|
|
47
|
+
|
|
48
|
+
windows:
|
|
49
|
+
runs-on: ${{ matrix.platform.runner }}
|
|
50
|
+
strategy:
|
|
51
|
+
matrix:
|
|
52
|
+
platform:
|
|
53
|
+
- runner: windows-latest
|
|
54
|
+
target: x64
|
|
55
|
+
- runner: windows-latest
|
|
56
|
+
target: x86
|
|
57
|
+
steps:
|
|
58
|
+
- uses: actions/checkout@v4
|
|
59
|
+
- uses: actions/setup-python@v5
|
|
60
|
+
with:
|
|
61
|
+
python-version: 3.x
|
|
62
|
+
architecture: ${{ matrix.platform.target }}
|
|
63
|
+
- name: Build wheels
|
|
64
|
+
uses: PyO3/maturin-action@v1
|
|
65
|
+
with:
|
|
66
|
+
target: ${{ matrix.platform.target }}
|
|
67
|
+
args: --release --out dist --find-interpreter
|
|
68
|
+
sccache: ${{ !startsWith(github.ref, 'refs/tags/') }}
|
|
69
|
+
- name: Upload wheels
|
|
70
|
+
uses: actions/upload-artifact@v4
|
|
71
|
+
with:
|
|
72
|
+
name: wheels-windows-${{ matrix.platform.target }}
|
|
73
|
+
path: dist
|
|
74
|
+
|
|
75
|
+
pytest:
|
|
76
|
+
name: test ${{ matrix.python-version }}
|
|
77
|
+
strategy:
|
|
78
|
+
fail-fast: false
|
|
79
|
+
matrix:
|
|
80
|
+
python-version: ['3.9', '3.10', '3.11', '3.12', '3.13']
|
|
81
|
+
runs-on: ubuntu-22.04
|
|
82
|
+
permissions:
|
|
83
|
+
contents: read
|
|
84
|
+
steps:
|
|
85
|
+
- uses: actions/checkout@v4
|
|
86
|
+
- name: Install Rust stable
|
|
87
|
+
uses: dtolnay/rust-toolchain@stable
|
|
88
|
+
- name: Cache Rust
|
|
89
|
+
uses: Swatinem/rust-cache@v2
|
|
90
|
+
with:
|
|
91
|
+
key: test-${{ matrix.python-version }}-v3
|
|
92
|
+
- name: Install uv
|
|
93
|
+
uses: astral-sh/setup-uv@v5
|
|
94
|
+
with:
|
|
95
|
+
python-version: ${{ matrix.python-version }}
|
|
96
|
+
- name: Install deps
|
|
97
|
+
run: uv sync --group testing
|
|
98
|
+
- run: uv pip install -e .
|
|
99
|
+
env:
|
|
100
|
+
RUST_BACKTRACE: 1
|
|
101
|
+
- run: uv pip freeze
|
|
102
|
+
- run: uv run pytest
|
|
103
|
+
|
|
104
|
+
sdist:
|
|
105
|
+
runs-on: ubuntu-latest
|
|
106
|
+
permissions:
|
|
107
|
+
contents: read
|
|
108
|
+
steps:
|
|
109
|
+
- uses: actions/checkout@v4
|
|
110
|
+
- name: Build sdist
|
|
111
|
+
uses: PyO3/maturin-action@v1
|
|
112
|
+
with:
|
|
113
|
+
command: sdist
|
|
114
|
+
args: --out dist
|
|
115
|
+
- name: Upload sdist
|
|
116
|
+
uses: actions/upload-artifact@v4
|
|
117
|
+
with:
|
|
118
|
+
name: wheels-sdist
|
|
119
|
+
path: dist
|
|
120
|
+
|
|
121
|
+
release:
|
|
122
|
+
name: Release
|
|
123
|
+
runs-on: ubuntu-latest
|
|
124
|
+
if: ${{ startsWith(github.ref, 'refs/tags/') || github.event_name == 'workflow_dispatch' }}
|
|
125
|
+
needs: [linux, windows, pytest, sdist]
|
|
126
|
+
permissions:
|
|
127
|
+
id-token: write
|
|
128
|
+
contents: write
|
|
129
|
+
attestations: write
|
|
130
|
+
steps:
|
|
131
|
+
- uses: actions/download-artifact@v4
|
|
132
|
+
- name: Generate artifact attestation
|
|
133
|
+
uses: actions/attest-build-provenance@v1
|
|
134
|
+
with:
|
|
135
|
+
subject-path: 'wheels-*/*'
|
|
136
|
+
- name: Publish to PyPI
|
|
137
|
+
if: ${{ startsWith(github.ref, 'refs/tags/') }}
|
|
138
|
+
uses: PyO3/maturin-action@v1
|
|
139
|
+
env:
|
|
140
|
+
MATURIN_PYPI_TOKEN: ${{ secrets.PYPI_API_TOKEN }}
|
|
141
|
+
with:
|
|
142
|
+
command: upload
|
|
143
|
+
args: --non-interactive --skip-existing wheels-*/*
|
diggity-0.1.0/.gitignore
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
debug/
|
|
2
|
+
target/
|
|
3
|
+
/target
|
|
4
|
+
|
|
5
|
+
**/*.rs.bk
|
|
6
|
+
|
|
7
|
+
*.pdb
|
|
8
|
+
|
|
9
|
+
# Byte-compiled / optimized / DLL files
|
|
10
|
+
__pycache__/
|
|
11
|
+
.pytest_cache/
|
|
12
|
+
*.py[cod]
|
|
13
|
+
|
|
14
|
+
# C extensions
|
|
15
|
+
*.so
|
|
16
|
+
|
|
17
|
+
# Distribution / packaging
|
|
18
|
+
.Python
|
|
19
|
+
.venv/
|
|
20
|
+
env/
|
|
21
|
+
bin/
|
|
22
|
+
build/
|
|
23
|
+
develop-eggs/
|
|
24
|
+
dist/
|
|
25
|
+
eggs/
|
|
26
|
+
lib/
|
|
27
|
+
lib64/
|
|
28
|
+
parts/
|
|
29
|
+
sdist/
|
|
30
|
+
var/
|
|
31
|
+
include/
|
|
32
|
+
man/
|
|
33
|
+
venv/
|
|
34
|
+
*.egg-info/
|
|
35
|
+
.installed.cfg
|
|
36
|
+
*.egg
|
|
37
|
+
|
|
38
|
+
# Installer logs
|
|
39
|
+
pip-log.txt
|
|
40
|
+
pip-delete-this-directory.txt
|
|
41
|
+
pip-selfcheck.json
|
|
42
|
+
|
|
43
|
+
# Unit test / coverage reports
|
|
44
|
+
htmlcov/
|
|
45
|
+
.tox/
|
|
46
|
+
.coverage
|
|
47
|
+
.cache
|
|
48
|
+
nosetests.xml
|
|
49
|
+
coverage.xml
|
|
50
|
+
|
|
51
|
+
# Translations
|
|
52
|
+
*.mo
|
|
53
|
+
|
|
54
|
+
# Mr Developer
|
|
55
|
+
.mr.developer.cfg
|
|
56
|
+
.project
|
|
57
|
+
.pydevproject
|
|
58
|
+
|
|
59
|
+
# Rope
|
|
60
|
+
.ropeproject
|
|
61
|
+
|
|
62
|
+
# Django stuff:
|
|
63
|
+
*.log
|
|
64
|
+
*.pot
|
|
65
|
+
|
|
66
|
+
.DS_Store
|
|
67
|
+
|
|
68
|
+
# Sphinx documentation
|
|
69
|
+
docs/_build/
|
|
70
|
+
|
|
71
|
+
# PyCharm
|
|
72
|
+
.idea/
|
|
73
|
+
|
|
74
|
+
# VSCode
|
|
75
|
+
.vscode/
|
|
76
|
+
|
|
77
|
+
# Pyenv
|
|
78
|
+
.python-version
|
diggity-0.1.0/Cargo.lock
ADDED
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
# This file is automatically @generated by Cargo.
|
|
2
|
+
# It is not intended for manual editing.
|
|
3
|
+
version = 4
|
|
4
|
+
|
|
5
|
+
[[package]]
|
|
6
|
+
name = "autocfg"
|
|
7
|
+
version = "1.3.0"
|
|
8
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
9
|
+
checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
|
|
10
|
+
|
|
11
|
+
[[package]]
|
|
12
|
+
name = "cfg-if"
|
|
13
|
+
version = "1.0.0"
|
|
14
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
15
|
+
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
|
16
|
+
|
|
17
|
+
[[package]]
|
|
18
|
+
name = "diggity"
|
|
19
|
+
version = "0.1.0"
|
|
20
|
+
dependencies = [
|
|
21
|
+
"pyo3",
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
[[package]]
|
|
25
|
+
name = "heck"
|
|
26
|
+
version = "0.5.0"
|
|
27
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
28
|
+
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
|
29
|
+
|
|
30
|
+
[[package]]
|
|
31
|
+
name = "indoc"
|
|
32
|
+
version = "2.0.5"
|
|
33
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
34
|
+
checksum = "b248f5224d1d606005e02c97f5aa4e88eeb230488bcc03bc9ca4d7991399f2b5"
|
|
35
|
+
|
|
36
|
+
[[package]]
|
|
37
|
+
name = "libc"
|
|
38
|
+
version = "0.2.158"
|
|
39
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
40
|
+
checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439"
|
|
41
|
+
|
|
42
|
+
[[package]]
|
|
43
|
+
name = "memoffset"
|
|
44
|
+
version = "0.9.1"
|
|
45
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
46
|
+
checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a"
|
|
47
|
+
dependencies = [
|
|
48
|
+
"autocfg",
|
|
49
|
+
]
|
|
50
|
+
|
|
51
|
+
[[package]]
|
|
52
|
+
name = "once_cell"
|
|
53
|
+
version = "1.20.0"
|
|
54
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
55
|
+
checksum = "33ea5043e58958ee56f3e15a90aee535795cd7dfd319846288d93c5b57d85cbe"
|
|
56
|
+
|
|
57
|
+
[[package]]
|
|
58
|
+
name = "portable-atomic"
|
|
59
|
+
version = "1.7.0"
|
|
60
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
61
|
+
checksum = "da544ee218f0d287a911e9c99a39a8c9bc8fcad3cb8db5959940044ecfc67265"
|
|
62
|
+
|
|
63
|
+
[[package]]
|
|
64
|
+
name = "proc-macro2"
|
|
65
|
+
version = "1.0.86"
|
|
66
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
67
|
+
checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
|
|
68
|
+
dependencies = [
|
|
69
|
+
"unicode-ident",
|
|
70
|
+
]
|
|
71
|
+
|
|
72
|
+
[[package]]
|
|
73
|
+
name = "pyo3"
|
|
74
|
+
version = "0.23.4"
|
|
75
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
76
|
+
checksum = "57fe09249128b3173d092de9523eaa75136bf7ba85e0d69eca241c7939c933cc"
|
|
77
|
+
dependencies = [
|
|
78
|
+
"cfg-if",
|
|
79
|
+
"indoc",
|
|
80
|
+
"libc",
|
|
81
|
+
"memoffset",
|
|
82
|
+
"once_cell",
|
|
83
|
+
"portable-atomic",
|
|
84
|
+
"pyo3-build-config",
|
|
85
|
+
"pyo3-ffi",
|
|
86
|
+
"pyo3-macros",
|
|
87
|
+
"unindent",
|
|
88
|
+
]
|
|
89
|
+
|
|
90
|
+
[[package]]
|
|
91
|
+
name = "pyo3-build-config"
|
|
92
|
+
version = "0.23.4"
|
|
93
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
94
|
+
checksum = "1cd3927b5a78757a0d71aa9dff669f903b1eb64b54142a9bd9f757f8fde65fd7"
|
|
95
|
+
dependencies = [
|
|
96
|
+
"once_cell",
|
|
97
|
+
"target-lexicon",
|
|
98
|
+
]
|
|
99
|
+
|
|
100
|
+
[[package]]
|
|
101
|
+
name = "pyo3-ffi"
|
|
102
|
+
version = "0.23.4"
|
|
103
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
104
|
+
checksum = "dab6bb2102bd8f991e7749f130a70d05dd557613e39ed2deeee8e9ca0c4d548d"
|
|
105
|
+
dependencies = [
|
|
106
|
+
"libc",
|
|
107
|
+
"pyo3-build-config",
|
|
108
|
+
]
|
|
109
|
+
|
|
110
|
+
[[package]]
|
|
111
|
+
name = "pyo3-macros"
|
|
112
|
+
version = "0.23.4"
|
|
113
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
114
|
+
checksum = "91871864b353fd5ffcb3f91f2f703a22a9797c91b9ab497b1acac7b07ae509c7"
|
|
115
|
+
dependencies = [
|
|
116
|
+
"proc-macro2",
|
|
117
|
+
"pyo3-macros-backend",
|
|
118
|
+
"quote",
|
|
119
|
+
"syn",
|
|
120
|
+
]
|
|
121
|
+
|
|
122
|
+
[[package]]
|
|
123
|
+
name = "pyo3-macros-backend"
|
|
124
|
+
version = "0.23.4"
|
|
125
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
126
|
+
checksum = "43abc3b80bc20f3facd86cd3c60beed58c3e2aa26213f3cda368de39c60a27e4"
|
|
127
|
+
dependencies = [
|
|
128
|
+
"heck",
|
|
129
|
+
"proc-macro2",
|
|
130
|
+
"pyo3-build-config",
|
|
131
|
+
"quote",
|
|
132
|
+
"syn",
|
|
133
|
+
]
|
|
134
|
+
|
|
135
|
+
[[package]]
|
|
136
|
+
name = "quote"
|
|
137
|
+
version = "1.0.37"
|
|
138
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
139
|
+
checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
|
|
140
|
+
dependencies = [
|
|
141
|
+
"proc-macro2",
|
|
142
|
+
]
|
|
143
|
+
|
|
144
|
+
[[package]]
|
|
145
|
+
name = "syn"
|
|
146
|
+
version = "2.0.77"
|
|
147
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
148
|
+
checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed"
|
|
149
|
+
dependencies = [
|
|
150
|
+
"proc-macro2",
|
|
151
|
+
"quote",
|
|
152
|
+
"unicode-ident",
|
|
153
|
+
]
|
|
154
|
+
|
|
155
|
+
[[package]]
|
|
156
|
+
name = "target-lexicon"
|
|
157
|
+
version = "0.12.16"
|
|
158
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
159
|
+
checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1"
|
|
160
|
+
|
|
161
|
+
[[package]]
|
|
162
|
+
name = "unicode-ident"
|
|
163
|
+
version = "1.0.13"
|
|
164
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
165
|
+
checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe"
|
|
166
|
+
|
|
167
|
+
[[package]]
|
|
168
|
+
name = "unindent"
|
|
169
|
+
version = "0.2.3"
|
|
170
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
171
|
+
checksum = "c7de7d73e1754487cb58364ee906a499937a0dfabd86bcb980fa99ec8c8fa2ce"
|
diggity-0.1.0/Cargo.toml
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
[package]
|
|
2
|
+
name = "diggity"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
edition = "2021"
|
|
5
|
+
|
|
6
|
+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
|
7
|
+
[lib]
|
|
8
|
+
name = "diggity"
|
|
9
|
+
crate-type = ["cdylib"]
|
|
10
|
+
|
|
11
|
+
[dependencies]
|
|
12
|
+
pyo3 = { version = "~0.23.4", features = ["extension-module"]}
|
|
13
|
+
|
diggity-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Andrey Torsunov
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
diggity-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: diggity
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Classifier: Programming Language :: Rust
|
|
5
|
+
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
6
|
+
License-File: LICENSE
|
|
7
|
+
Summary: A utility library for working with nested objects and handling optional values. Inspired by Ruby `dig` function for safely accessing deeply nested structures
|
|
8
|
+
Author-email: Andrey Torsunov <andrey.torsunov@gmail.com>
|
|
9
|
+
Requires-Python: >=3.8
|
|
10
|
+
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
|
|
11
|
+
Project-URL: Homepage, https://github.com/gtors/diggity
|
|
12
|
+
Project-URL: Source, https://github.com/gtors/diggity
|
|
13
|
+
|
|
14
|
+
# Diggity
|
|
15
|
+
|
|
16
|
+
**Diggity** is a Python library that provides functionality similar to Ruby's `dig` method.
|
|
17
|
+
It allows you to traverse nested data structures to extract values using a specified path or return a default value when the traversal is unsuccessful.
|
|
18
|
+
|
|
19
|
+
Additionally, it includes `coalesce` and `coalesce_logical` functions for handling optional values and finding the first non-`None` or truthy value in a sequence.
|
|
20
|
+
|
|
21
|
+
## Features
|
|
22
|
+
- **`dig_path`**: Extract value from nested data structures using dot-separated path.
|
|
23
|
+
- **`dig`**: Extract value from nested data structures using a sequence of keys, indices or attributes provided via `*args`.
|
|
24
|
+
- **`coalesce`**: Returns the first non-`None` value from a sequence of arguments.
|
|
25
|
+
- **`coalesce_logical`**: Returns the first truthy value from a sequence of arguments.
|
|
26
|
+
|
|
27
|
+
## Installation
|
|
28
|
+
|
|
29
|
+
To install **Diggity**, simply run the following command:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
pip install diggity
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Usage
|
|
36
|
+
|
|
37
|
+
### Extracting Nested Values
|
|
38
|
+
|
|
39
|
+
You can extract values from nested data structures in various ways. Below are some examples.
|
|
40
|
+
|
|
41
|
+
```python
|
|
42
|
+
import diggity
|
|
43
|
+
|
|
44
|
+
data = {
|
|
45
|
+
"users": [
|
|
46
|
+
{
|
|
47
|
+
"name": "Alice",
|
|
48
|
+
"age": 30,
|
|
49
|
+
"preferences": {
|
|
50
|
+
"languages": ["Python", "Rust", "Go"]
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
]
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
# Extracting a value using a dotted path
|
|
57
|
+
name = diggity.dig_path(data, "users.0.name") # Returns: "Alice"
|
|
58
|
+
# Or
|
|
59
|
+
name = diggity.dig(data, "users", 0, "name") # Also returns: "Alice"
|
|
60
|
+
|
|
61
|
+
# Extracting a non-existing value, returning None
|
|
62
|
+
hobby = diggity.dig_path(data, "users.0.hobby") # Returns: None
|
|
63
|
+
# Or
|
|
64
|
+
hobby = diggity.dig(data, "users", 0, "hobby") # Also returns: None
|
|
65
|
+
|
|
66
|
+
# Providing a default value for a non-existing path
|
|
67
|
+
hobby_with_default = diggity.dig(data, "users", 0, "hobby", default="No hobby specified") # Returns: "No hobby specified"
|
|
68
|
+
|
|
69
|
+
# Using a custom separator
|
|
70
|
+
favorite_language = diggity.dig_path(data, "users:0:preferences:languages:0", sep=":") # Returns: "Python"
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Handling Optional Values with `coalesce`
|
|
74
|
+
|
|
75
|
+
The `coalesce` function returns the first non-`None` value from a sequence of arguments.
|
|
76
|
+
|
|
77
|
+
```python
|
|
78
|
+
import diggity
|
|
79
|
+
|
|
80
|
+
# Returns the first non-None value
|
|
81
|
+
result = diggity.coalesce(None, None, 42, None) # Returns: 42
|
|
82
|
+
|
|
83
|
+
# Returns None if all values are None
|
|
84
|
+
result = diggity.coalesce(None, None, None) # Returns: None
|
|
85
|
+
|
|
86
|
+
# Works with mixed types
|
|
87
|
+
result = diggity.coalesce(None, False, 0, "hello") # Returns: False
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### Finding the First Truthy Value with `coalesce_logical`
|
|
91
|
+
|
|
92
|
+
The `coalesce_logical` function returns the first truthy value from a sequence of arguments.
|
|
93
|
+
|
|
94
|
+
```python
|
|
95
|
+
import diggity
|
|
96
|
+
|
|
97
|
+
# Returns the first truthy value
|
|
98
|
+
result = diggity.coalesce_logical(None, False, 42, 0) # Returns: 42
|
|
99
|
+
|
|
100
|
+
# Returns None if all values are falsy
|
|
101
|
+
result = diggity.coalesce_logical(None, False, 0, "") # Returns: None
|
|
102
|
+
|
|
103
|
+
# Works with mixed types
|
|
104
|
+
result = diggity.coalesce_logical(None, False, "hello", 0) # Returns: "hello"
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## License
|
|
108
|
+
|
|
109
|
+
This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.
|
|
110
|
+
|
|
111
|
+
## Contributing
|
|
112
|
+
|
|
113
|
+
Contributions are welcome! Please feel free to submit a pull request or open an issue.
|
|
114
|
+
|
|
115
|
+
## Acknowledgments
|
|
116
|
+
|
|
117
|
+
This project uses [PyO3](https://pyo3.rs/) to bridge Rust and Python. Special thanks to the contributors of the PyO3 library.
|
|
118
|
+
|
diggity-0.1.0/README.md
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# Diggity
|
|
2
|
+
|
|
3
|
+
**Diggity** is a Python library that provides functionality similar to Ruby's `dig` method.
|
|
4
|
+
It allows you to traverse nested data structures to extract values using a specified path or return a default value when the traversal is unsuccessful.
|
|
5
|
+
|
|
6
|
+
Additionally, it includes `coalesce` and `coalesce_logical` functions for handling optional values and finding the first non-`None` or truthy value in a sequence.
|
|
7
|
+
|
|
8
|
+
## Features
|
|
9
|
+
- **`dig_path`**: Extract value from nested data structures using dot-separated path.
|
|
10
|
+
- **`dig`**: Extract value from nested data structures using a sequence of keys, indices or attributes provided via `*args`.
|
|
11
|
+
- **`coalesce`**: Returns the first non-`None` value from a sequence of arguments.
|
|
12
|
+
- **`coalesce_logical`**: Returns the first truthy value from a sequence of arguments.
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
To install **Diggity**, simply run the following command:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
pip install diggity
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Usage
|
|
23
|
+
|
|
24
|
+
### Extracting Nested Values
|
|
25
|
+
|
|
26
|
+
You can extract values from nested data structures in various ways. Below are some examples.
|
|
27
|
+
|
|
28
|
+
```python
|
|
29
|
+
import diggity
|
|
30
|
+
|
|
31
|
+
data = {
|
|
32
|
+
"users": [
|
|
33
|
+
{
|
|
34
|
+
"name": "Alice",
|
|
35
|
+
"age": 30,
|
|
36
|
+
"preferences": {
|
|
37
|
+
"languages": ["Python", "Rust", "Go"]
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
]
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
# Extracting a value using a dotted path
|
|
44
|
+
name = diggity.dig_path(data, "users.0.name") # Returns: "Alice"
|
|
45
|
+
# Or
|
|
46
|
+
name = diggity.dig(data, "users", 0, "name") # Also returns: "Alice"
|
|
47
|
+
|
|
48
|
+
# Extracting a non-existing value, returning None
|
|
49
|
+
hobby = diggity.dig_path(data, "users.0.hobby") # Returns: None
|
|
50
|
+
# Or
|
|
51
|
+
hobby = diggity.dig(data, "users", 0, "hobby") # Also returns: None
|
|
52
|
+
|
|
53
|
+
# Providing a default value for a non-existing path
|
|
54
|
+
hobby_with_default = diggity.dig(data, "users", 0, "hobby", default="No hobby specified") # Returns: "No hobby specified"
|
|
55
|
+
|
|
56
|
+
# Using a custom separator
|
|
57
|
+
favorite_language = diggity.dig_path(data, "users:0:preferences:languages:0", sep=":") # Returns: "Python"
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Handling Optional Values with `coalesce`
|
|
61
|
+
|
|
62
|
+
The `coalesce` function returns the first non-`None` value from a sequence of arguments.
|
|
63
|
+
|
|
64
|
+
```python
|
|
65
|
+
import diggity
|
|
66
|
+
|
|
67
|
+
# Returns the first non-None value
|
|
68
|
+
result = diggity.coalesce(None, None, 42, None) # Returns: 42
|
|
69
|
+
|
|
70
|
+
# Returns None if all values are None
|
|
71
|
+
result = diggity.coalesce(None, None, None) # Returns: None
|
|
72
|
+
|
|
73
|
+
# Works with mixed types
|
|
74
|
+
result = diggity.coalesce(None, False, 0, "hello") # Returns: False
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Finding the First Truthy Value with `coalesce_logical`
|
|
78
|
+
|
|
79
|
+
The `coalesce_logical` function returns the first truthy value from a sequence of arguments.
|
|
80
|
+
|
|
81
|
+
```python
|
|
82
|
+
import diggity
|
|
83
|
+
|
|
84
|
+
# Returns the first truthy value
|
|
85
|
+
result = diggity.coalesce_logical(None, False, 42, 0) # Returns: 42
|
|
86
|
+
|
|
87
|
+
# Returns None if all values are falsy
|
|
88
|
+
result = diggity.coalesce_logical(None, False, 0, "") # Returns: None
|
|
89
|
+
|
|
90
|
+
# Works with mixed types
|
|
91
|
+
result = diggity.coalesce_logical(None, False, "hello", 0) # Returns: "hello"
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## License
|
|
95
|
+
|
|
96
|
+
This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.
|
|
97
|
+
|
|
98
|
+
## Contributing
|
|
99
|
+
|
|
100
|
+
Contributions are welcome! Please feel free to submit a pull request or open an issue.
|
|
101
|
+
|
|
102
|
+
## Acknowledgments
|
|
103
|
+
|
|
104
|
+
This project uses [PyO3](https://pyo3.rs/) to bridge Rust and Python. Special thanks to the contributors of the PyO3 library.
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["maturin>=1.7,<2.0"]
|
|
3
|
+
build-backend = "maturin"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "diggity"
|
|
7
|
+
description = "A utility library for working with nested objects and handling optional values. Inspired by Ruby `dig` function for safely accessing deeply nested structures"
|
|
8
|
+
license = { file = "LICENSE" }
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
authors = [{ name = "Andrey Torsunov", email = "andrey.torsunov@gmail.com" }]
|
|
11
|
+
requires-python = ">=3.8"
|
|
12
|
+
classifiers = [
|
|
13
|
+
"Programming Language :: Rust",
|
|
14
|
+
"Programming Language :: Python :: Implementation :: CPython",
|
|
15
|
+
]
|
|
16
|
+
dynamic = ["version"]
|
|
17
|
+
|
|
18
|
+
[project.urls]
|
|
19
|
+
Homepage = 'https://github.com/gtors/diggity'
|
|
20
|
+
Source = 'https://github.com/gtors/diggity'
|
|
21
|
+
|
|
22
|
+
[tool.maturin]
|
|
23
|
+
features = ["pyo3/extension-module"]
|
|
24
|
+
|
|
25
|
+
[dependency-groups]
|
|
26
|
+
dev = ["maturin"]
|
|
27
|
+
testing = [
|
|
28
|
+
{ include-group = "dev" },
|
|
29
|
+
'hypothesis',
|
|
30
|
+
'pytest',
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
[tool.pytest.ini_options]
|
|
34
|
+
testpaths = 'tests'
|
|
35
|
+
log_format = '%(name)s %(levelname)s: %(message)s'
|
|
36
|
+
filterwarnings = [
|
|
37
|
+
'error',
|
|
38
|
+
# Python 3.9 and below allowed truncation of float to integers in some
|
|
39
|
+
# cases, by not making this an error we can test for this behaviour
|
|
40
|
+
'ignore:(.+)Implicit conversion to integers using __int__ is deprecated',
|
|
41
|
+
]
|
|
42
|
+
xfail_strict = true
|
|
43
|
+
|
|
44
|
+
[tool.uv]
|
|
45
|
+
package = false
|
diggity-0.1.0/src/lib.rs
ADDED
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
/// A utility module for working with nested Python objects and handling optional values.
|
|
2
|
+
///
|
|
3
|
+
/// This module provides functions to extract values from nested structures, handle `None` values,
|
|
4
|
+
/// and find the first truthy/not-None value in a sequence of arguments.
|
|
5
|
+
///
|
|
6
|
+
/// # Functions
|
|
7
|
+
/// - `dig`: Extracts values from nested structures using a sequence of keys or attributes.
|
|
8
|
+
/// - `dig_path`: Extracts values from nested structures using a path string with a specified separator.
|
|
9
|
+
/// - `coalesce`: Returns the first non-`None` value from a sequence of arguments.
|
|
10
|
+
/// - `coalesce_logical`: Returns the first truthy value from a sequence of arguments.
|
|
11
|
+
///
|
|
12
|
+
/// # Notes
|
|
13
|
+
/// - The `dig` function is inspired by Ruby's `Hash#dig` and `Array#dig` methods, providing
|
|
14
|
+
/// a safe way to access deeply nested values without raising errors for missing keys or indices
|
|
15
|
+
/// - The `dig` and `dig_path` functions are useful for traversing deeply nested dictionaries, sequences and objects.
|
|
16
|
+
/// - The `coalesce` and `coalesce_logical` functions are helpful for providing fallback values in cases
|
|
17
|
+
/// where `None` or falsy values are present.
|
|
18
|
+
use pyo3::{
|
|
19
|
+
exceptions::PyValueError,
|
|
20
|
+
prelude::*,
|
|
21
|
+
types::{PyAny, PyString, PyTuple},
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
use std::ops::ControlFlow;
|
|
25
|
+
|
|
26
|
+
#[pymodule]
|
|
27
|
+
fn diggity(m: &Bound<'_, PyModule>) -> PyResult<()> {
|
|
28
|
+
m.add_function(wrap_pyfunction!(dig, m)?)?;
|
|
29
|
+
m.add_function(wrap_pyfunction!(dig_path, m)?)?;
|
|
30
|
+
m.add_function(wrap_pyfunction!(coalesce, m)?)?;
|
|
31
|
+
m.add_function(wrap_pyfunction!(coalesce_logical, m)?)?;
|
|
32
|
+
Ok(())
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/// Returns the first non-`None` value from the provided arguments.
|
|
36
|
+
///
|
|
37
|
+
/// This function iterates through the given arguments and returns the first one that is not `None`.
|
|
38
|
+
/// If all arguments are `None`, it returns `None`.
|
|
39
|
+
///
|
|
40
|
+
/// # Arguments
|
|
41
|
+
/// - `*args`: A variable number of arguments to check for the first non-`None` value.
|
|
42
|
+
///
|
|
43
|
+
/// # Returns
|
|
44
|
+
/// - The first non-`None` value if found.
|
|
45
|
+
/// - `None` if all arguments are `None`.
|
|
46
|
+
///
|
|
47
|
+
/// # Examples
|
|
48
|
+
/// ```python
|
|
49
|
+
/// assert coalesce(None, None, 42, None) == 42
|
|
50
|
+
/// assert coalesce(None, None, None) is None
|
|
51
|
+
/// ```
|
|
52
|
+
#[pyfunction]
|
|
53
|
+
#[pyo3(signature = (*args))]
|
|
54
|
+
fn coalesce(args: Bound<'_, PyTuple>) -> PyObject {
|
|
55
|
+
args.iter()
|
|
56
|
+
.find(|arg| !arg.is_none())
|
|
57
|
+
.map_or_else(|| args.py().None(), |arg| arg.unbind())
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/// Returns the first truthy value from the provided arguments.
|
|
61
|
+
///
|
|
62
|
+
/// This function iterates through the given arguments and returns the first one that evaluates to `True`
|
|
63
|
+
/// in a boolean context. If all arguments are falsy, it returns `None`.
|
|
64
|
+
///
|
|
65
|
+
/// # Arguments
|
|
66
|
+
/// - `*args`: A variable number of arguments to check for the first truthy value.
|
|
67
|
+
///
|
|
68
|
+
/// # Returns
|
|
69
|
+
/// - The first truthy value if found.
|
|
70
|
+
/// - `None` if all arguments are falsy.
|
|
71
|
+
///
|
|
72
|
+
/// # Examples
|
|
73
|
+
/// ```python
|
|
74
|
+
/// assert coalesce_logical(None, False, 42, 0) == 42
|
|
75
|
+
/// assert coalesce_logical(None, False, 0, "") is None
|
|
76
|
+
/// ```
|
|
77
|
+
#[pyfunction]
|
|
78
|
+
#[pyo3(signature = (*args))]
|
|
79
|
+
fn coalesce_logical(args: Bound<'_, PyTuple>) -> PyObject {
|
|
80
|
+
args.iter()
|
|
81
|
+
.find(|arg| arg.is_truthy().unwrap_or(false))
|
|
82
|
+
.map_or_else(|| args.py().None(), |arg| arg.unbind())
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/// Tries to extract the value from a nested structure
|
|
86
|
+
///
|
|
87
|
+
/// This function traverses the given object using the keys or attributes provided in `args`.
|
|
88
|
+
/// If the path is not found, it returns `None` or a specified default value.
|
|
89
|
+
///
|
|
90
|
+
/// # Arguments
|
|
91
|
+
/// - `obj`: The object containing nested structures from which to extract values.
|
|
92
|
+
/// - `*args`: A variable number of keys or attributes to traverse the nested structure.
|
|
93
|
+
/// - `default`: An optional default value to return if the path is not found.
|
|
94
|
+
///
|
|
95
|
+
/// # Returns
|
|
96
|
+
/// - The value at the specified path if found.
|
|
97
|
+
/// - `None` or the provided default value if the path is not found.
|
|
98
|
+
///
|
|
99
|
+
/// # Examples
|
|
100
|
+
/// ```python
|
|
101
|
+
/// data = {"a": {"b": {"c": 42}}}
|
|
102
|
+
/// assert dig(data, "a", "b", "c") == 42
|
|
103
|
+
/// assert dig(data, "a", "x", default=0) == 0
|
|
104
|
+
/// ```
|
|
105
|
+
#[pyfunction]
|
|
106
|
+
#[pyo3(signature = (obj, *args, r#default=None))]
|
|
107
|
+
fn dig(
|
|
108
|
+
py: Python,
|
|
109
|
+
obj: Bound<'_, PyAny>,
|
|
110
|
+
args: &Bound<'_, PyTuple>,
|
|
111
|
+
r#default: Option<&Bound<'_, PyAny>>,
|
|
112
|
+
) -> PyResult<PyObject> {
|
|
113
|
+
let default_value = r#default;
|
|
114
|
+
|
|
115
|
+
if args.is_empty() {
|
|
116
|
+
return Ok(obj.unbind());
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
let value = args.iter().try_fold(obj, |acc, arg| {
|
|
120
|
+
if let Ok(key) = arg.downcast::<PyString>() {
|
|
121
|
+
acc.get_item(key).or_else(|_| acc.getattr(key)).map_or_else(
|
|
122
|
+
|_| ControlFlow::Break(default_value),
|
|
123
|
+
|v| ControlFlow::Continue(v),
|
|
124
|
+
)
|
|
125
|
+
} else {
|
|
126
|
+
acc.get_item(arg).map_or_else(
|
|
127
|
+
|_| ControlFlow::Break(default_value),
|
|
128
|
+
|v| ControlFlow::Continue(v),
|
|
129
|
+
)
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
extract_control_flow_value(value, py)
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/// Tries to extract the value from a nested structure within an object using a specified path.
|
|
136
|
+
///
|
|
137
|
+
/// This function traverses the given object using the keys or attributes specified in the `path` string,
|
|
138
|
+
/// split by the provided separator. If the path is not found, it returns `None` or a specified default value.
|
|
139
|
+
///
|
|
140
|
+
/// # Arguments
|
|
141
|
+
/// - `obj`: The object containing nested structures from which to extract values.
|
|
142
|
+
/// - `path`: A string representing the path to the desired value, with keys or attributes separated by `sep`.
|
|
143
|
+
/// - `default`: An optional default value to return if the path is not found.
|
|
144
|
+
/// - `sep`: An optional string to specify the separator used in the path (default is ".").
|
|
145
|
+
///
|
|
146
|
+
/// # Returns
|
|
147
|
+
/// - The value at the specified path if found.
|
|
148
|
+
/// - `None` or the provided default value if the path is not found.
|
|
149
|
+
///
|
|
150
|
+
/// # Examples
|
|
151
|
+
/// ```python
|
|
152
|
+
/// data = {"a": {"b": [{"c": 42}]}}
|
|
153
|
+
/// assert dig_path(data, "a.b.0.c") == 42
|
|
154
|
+
/// assert dig_path(data, "a.x.y", default=0) == 0
|
|
155
|
+
/// assert dig_path(data, "a/b/0/c", sep="/") == 42
|
|
156
|
+
/// ``
|
|
157
|
+
#[pyfunction]
|
|
158
|
+
#[pyo3(signature = (obj, path, r#default=None, sep = "."))]
|
|
159
|
+
fn dig_path(
|
|
160
|
+
py: Python,
|
|
161
|
+
obj: Bound<'_, PyAny>,
|
|
162
|
+
path: &str,
|
|
163
|
+
r#default: Option<&Bound<'_, PyAny>>,
|
|
164
|
+
sep: &str,
|
|
165
|
+
) -> PyResult<PyObject> {
|
|
166
|
+
let default_value = r#default;
|
|
167
|
+
|
|
168
|
+
if path.is_empty() {
|
|
169
|
+
return Ok(obj.unbind());
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
let value = path.split(sep).try_fold(obj, |acc, key| {
|
|
173
|
+
acc.get_item(key)
|
|
174
|
+
.or_else(|_| acc.getattr(key))
|
|
175
|
+
.or_else(|_| {
|
|
176
|
+
let index = key
|
|
177
|
+
.parse::<usize>()
|
|
178
|
+
.map_err(|_| PyValueError::new_err(py.None()))?;
|
|
179
|
+
acc.get_item(index)
|
|
180
|
+
})
|
|
181
|
+
.map_or_else(
|
|
182
|
+
|_| ControlFlow::Break(default_value),
|
|
183
|
+
|v| ControlFlow::Continue(v),
|
|
184
|
+
)
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
extract_control_flow_value(value, py)
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
#[inline]
|
|
191
|
+
fn extract_control_flow_value(
|
|
192
|
+
value: ControlFlow<Option<&Bound<'_, PyAny>>, Bound<'_, PyAny>>,
|
|
193
|
+
py: Python<'_>,
|
|
194
|
+
) -> PyResult<PyObject> {
|
|
195
|
+
match value {
|
|
196
|
+
ControlFlow::Continue(v) => Ok(v.unbind()),
|
|
197
|
+
ControlFlow::Break(v) => Ok(v.into_pyobject(py)?.unbind()),
|
|
198
|
+
}
|
|
199
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
from diggity import dig, dig_path, coalesce, coalesce_logical
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def test_dig():
|
|
5
|
+
# Test nested dictionary
|
|
6
|
+
data = {"a": {"b": [None, None, {"c": 42}]}}
|
|
7
|
+
assert dig(data, "a", "b", 2, "c") == 42
|
|
8
|
+
|
|
9
|
+
# Test missing key with default value
|
|
10
|
+
assert dig(data, "a", "x", default=0) == 0
|
|
11
|
+
|
|
12
|
+
# Test missing key without default value
|
|
13
|
+
assert dig(data, "a", "x") is None
|
|
14
|
+
|
|
15
|
+
# Test empty args
|
|
16
|
+
assert dig(data) == data
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def test_dig_path():
|
|
20
|
+
# Test nested dictionary with default separator
|
|
21
|
+
data = [{"a": {"b": {"c": 42}}}]
|
|
22
|
+
assert dig_path(data, "0.a.b.c") == 42
|
|
23
|
+
|
|
24
|
+
# Test nested dictionary with custom separator
|
|
25
|
+
assert dig_path(data, "0/a/b/c", sep="/") == 42
|
|
26
|
+
|
|
27
|
+
# Test missing path with default value
|
|
28
|
+
assert dig_path(data, "0.a.x.y", default=0) == 0
|
|
29
|
+
|
|
30
|
+
# Test missing path without default value
|
|
31
|
+
assert dig_path(data, "0.a.x.y") is None
|
|
32
|
+
|
|
33
|
+
# Test empty path
|
|
34
|
+
assert dig_path(data, "") == data
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def test_coalesce():
|
|
38
|
+
# Test with non-None values
|
|
39
|
+
assert coalesce(None, None, 42, None) == 42
|
|
40
|
+
|
|
41
|
+
# Test with all None values
|
|
42
|
+
assert coalesce(None, None, None) is None
|
|
43
|
+
|
|
44
|
+
# Test with mixed values
|
|
45
|
+
assert coalesce(None, False, 0, "hello") == False
|
|
46
|
+
|
|
47
|
+
# Test with no arguments
|
|
48
|
+
assert coalesce() is None
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def test_coalesce_logical():
|
|
52
|
+
# Test with truthy values
|
|
53
|
+
assert coalesce_logical(None, False, 42, 0) == 42
|
|
54
|
+
|
|
55
|
+
# Test with all falsy values
|
|
56
|
+
assert coalesce_logical(None, False, 0, "") is None
|
|
57
|
+
|
|
58
|
+
# Test with mixed values
|
|
59
|
+
assert coalesce_logical(None, False, "hello", 0) == "hello"
|
|
60
|
+
|
|
61
|
+
# Test with no arguments
|
|
62
|
+
assert coalesce_logical() is None
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
# Edge Cases and Error Handling
|
|
66
|
+
def test_dig_edge_cases():
|
|
67
|
+
# Test non-dictionary object
|
|
68
|
+
class TestObject:
|
|
69
|
+
def __init__(self):
|
|
70
|
+
self.a = {"b": 42}
|
|
71
|
+
|
|
72
|
+
obj = TestObject()
|
|
73
|
+
assert dig(obj, "a", "b") == 42
|
|
74
|
+
assert dig({"a": 1}, 123) is None
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def test_dig_path_edge_cases():
|
|
78
|
+
# Test invalid path separator
|
|
79
|
+
data = {"a": {"b": {"c": 42}}}
|
|
80
|
+
assert dig_path(data, "a-b-c", sep="-") == 42
|
|
81
|
+
|
|
82
|
+
# Test numeric keys in path
|
|
83
|
+
data = {"a": {0: {"c": 42}}}
|
|
84
|
+
assert dig_path(data, "a.0.c") == 42
|
|
85
|
+
assert dig_path(data, "a.x.y.z") is None
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def test_coalesce_edge_cases():
|
|
89
|
+
# Test with empty tuple
|
|
90
|
+
assert coalesce() is None
|
|
91
|
+
|
|
92
|
+
# Test with non-None falsy values
|
|
93
|
+
assert coalesce(0, "", False, None) == 0
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def test_coalesce_logical_edge_cases():
|
|
97
|
+
# Test with empty tuple
|
|
98
|
+
assert coalesce_logical() is None
|
|
99
|
+
|
|
100
|
+
# Test with non-truthy values
|
|
101
|
+
assert coalesce_logical(0, "", False, None) is None
|
diggity-0.1.0/uv.lock
ADDED
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
version = 1
|
|
2
|
+
revision = 1
|
|
3
|
+
requires-python = ">=3.8"
|
|
4
|
+
resolution-markers = [
|
|
5
|
+
"python_full_version >= '3.9'",
|
|
6
|
+
"python_full_version < '3.9'",
|
|
7
|
+
]
|
|
8
|
+
|
|
9
|
+
[[package]]
|
|
10
|
+
name = "attrs"
|
|
11
|
+
version = "25.1.0"
|
|
12
|
+
source = { registry = "https://pypi.org/simple" }
|
|
13
|
+
sdist = { url = "https://files.pythonhosted.org/packages/49/7c/fdf464bcc51d23881d110abd74b512a42b3d5d376a55a831b44c603ae17f/attrs-25.1.0.tar.gz", hash = "sha256:1c97078a80c814273a76b2a298a932eb681c87415c11dee0a6921de7f1b02c3e", size = 810562 }
|
|
14
|
+
wheels = [
|
|
15
|
+
{ url = "https://files.pythonhosted.org/packages/fc/30/d4986a882011f9df997a55e6becd864812ccfcd821d64aac8570ee39f719/attrs-25.1.0-py3-none-any.whl", hash = "sha256:c75a69e28a550a7e93789579c22aa26b0f5b83b75dc4e08fe092980051e1090a", size = 63152 },
|
|
16
|
+
]
|
|
17
|
+
|
|
18
|
+
[[package]]
|
|
19
|
+
name = "colorama"
|
|
20
|
+
version = "0.4.6"
|
|
21
|
+
source = { registry = "https://pypi.org/simple" }
|
|
22
|
+
sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697 }
|
|
23
|
+
wheels = [
|
|
24
|
+
{ url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335 },
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
[[package]]
|
|
28
|
+
name = "diggity"
|
|
29
|
+
source = { virtual = "." }
|
|
30
|
+
|
|
31
|
+
[package.dev-dependencies]
|
|
32
|
+
dev = [
|
|
33
|
+
{ name = "maturin" },
|
|
34
|
+
]
|
|
35
|
+
testing = [
|
|
36
|
+
{ name = "hypothesis", version = "6.113.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" },
|
|
37
|
+
{ name = "hypothesis", version = "6.127.9", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" },
|
|
38
|
+
{ name = "maturin" },
|
|
39
|
+
{ name = "pytest" },
|
|
40
|
+
]
|
|
41
|
+
|
|
42
|
+
[package.metadata]
|
|
43
|
+
|
|
44
|
+
[package.metadata.requires-dev]
|
|
45
|
+
dev = [{ name = "maturin" }]
|
|
46
|
+
testing = [
|
|
47
|
+
{ name = "hypothesis" },
|
|
48
|
+
{ name = "maturin" },
|
|
49
|
+
{ name = "pytest" },
|
|
50
|
+
]
|
|
51
|
+
|
|
52
|
+
[[package]]
|
|
53
|
+
name = "exceptiongroup"
|
|
54
|
+
version = "1.2.2"
|
|
55
|
+
source = { registry = "https://pypi.org/simple" }
|
|
56
|
+
sdist = { url = "https://files.pythonhosted.org/packages/09/35/2495c4ac46b980e4ca1f6ad6db102322ef3ad2410b79fdde159a4b0f3b92/exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc", size = 28883 }
|
|
57
|
+
wheels = [
|
|
58
|
+
{ url = "https://files.pythonhosted.org/packages/02/cc/b7e31358aac6ed1ef2bb790a9746ac2c69bcb3c8588b41616914eb106eaf/exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b", size = 16453 },
|
|
59
|
+
]
|
|
60
|
+
|
|
61
|
+
[[package]]
|
|
62
|
+
name = "hypothesis"
|
|
63
|
+
version = "6.113.0"
|
|
64
|
+
source = { registry = "https://pypi.org/simple" }
|
|
65
|
+
resolution-markers = [
|
|
66
|
+
"python_full_version < '3.9'",
|
|
67
|
+
]
|
|
68
|
+
dependencies = [
|
|
69
|
+
{ name = "attrs", marker = "python_full_version < '3.9'" },
|
|
70
|
+
{ name = "exceptiongroup", marker = "python_full_version < '3.9'" },
|
|
71
|
+
{ name = "sortedcontainers", marker = "python_full_version < '3.9'" },
|
|
72
|
+
]
|
|
73
|
+
sdist = { url = "https://files.pythonhosted.org/packages/28/32/6513cd7256f38c19a6c8a1d5ce9792bcd35c7f11651989994731f0e97672/hypothesis-6.113.0.tar.gz", hash = "sha256:5556ac66fdf72a4ccd5d237810f7cf6bdcd00534a4485015ef881af26e20f7c7", size = 408897 }
|
|
74
|
+
wheels = [
|
|
75
|
+
{ url = "https://files.pythonhosted.org/packages/14/fa/4acb477b86a94571958bd337eae5baf334d21b8c98a04b594d0dad381ba8/hypothesis-6.113.0-py3-none-any.whl", hash = "sha256:d539180eb2bb71ed28a23dfe94e67c851f9b09f3ccc4125afad43f17e32e2bad", size = 469790 },
|
|
76
|
+
]
|
|
77
|
+
|
|
78
|
+
[[package]]
|
|
79
|
+
name = "hypothesis"
|
|
80
|
+
version = "6.127.9"
|
|
81
|
+
source = { registry = "https://pypi.org/simple" }
|
|
82
|
+
resolution-markers = [
|
|
83
|
+
"python_full_version >= '3.9'",
|
|
84
|
+
]
|
|
85
|
+
dependencies = [
|
|
86
|
+
{ name = "attrs", marker = "python_full_version >= '3.9'" },
|
|
87
|
+
{ name = "exceptiongroup", marker = "python_full_version >= '3.9' and python_full_version < '3.11'" },
|
|
88
|
+
{ name = "sortedcontainers", marker = "python_full_version >= '3.9'" },
|
|
89
|
+
]
|
|
90
|
+
sdist = { url = "https://files.pythonhosted.org/packages/79/41/72e528551426dbb5156caf7946be53a0c685ee14b0628694ede55dd4a882/hypothesis-6.127.9.tar.gz", hash = "sha256:e8b065319b53ba62cd194912e6322e435daad862ca34e2da8997529e37edecda", size = 420334 }
|
|
91
|
+
wheels = [
|
|
92
|
+
{ url = "https://files.pythonhosted.org/packages/c6/00/d204a616fd127ee7830f649cca860b814331f591995e12aaa3931da10c45/hypothesis-6.127.9-py3-none-any.whl", hash = "sha256:51d54c033cfed4ebdc45c9d45ae890d822546151d8d58f52cbed3f049cf448cf", size = 484014 },
|
|
93
|
+
]
|
|
94
|
+
|
|
95
|
+
[[package]]
|
|
96
|
+
name = "iniconfig"
|
|
97
|
+
version = "2.0.0"
|
|
98
|
+
source = { registry = "https://pypi.org/simple" }
|
|
99
|
+
sdist = { url = "https://files.pythonhosted.org/packages/d7/4b/cbd8e699e64a6f16ca3a8220661b5f83792b3017d0f79807cb8708d33913/iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3", size = 4646 }
|
|
100
|
+
wheels = [
|
|
101
|
+
{ url = "https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374", size = 5892 },
|
|
102
|
+
]
|
|
103
|
+
|
|
104
|
+
[[package]]
|
|
105
|
+
name = "maturin"
|
|
106
|
+
version = "1.8.2"
|
|
107
|
+
source = { registry = "https://pypi.org/simple" }
|
|
108
|
+
dependencies = [
|
|
109
|
+
{ name = "tomli", marker = "python_full_version < '3.11'" },
|
|
110
|
+
]
|
|
111
|
+
sdist = { url = "https://files.pythonhosted.org/packages/e0/8f/6978427ce3f72b189012e1731d1d2d27b3151caa741666c905320e0a3662/maturin-1.8.2.tar.gz", hash = "sha256:e31abc70f6f93285d6e63d2f4459c079c94c259dd757370482d2d4ceb9ec1fa0", size = 199276 }
|
|
112
|
+
wheels = [
|
|
113
|
+
{ url = "https://files.pythonhosted.org/packages/67/7a/8fbcaf8f29e583567b21512aa56012fbe5f3e4293ae18a768f4106d584d5/maturin-1.8.2-py3-none-linux_armv6l.whl", hash = "sha256:174cb81c573c4a74be96b4e4469ac84e543cff75850fe2728a8eebb5f4d7b613", size = 7676631 },
|
|
114
|
+
{ url = "https://files.pythonhosted.org/packages/c8/88/e17f71a34d4c99558e33c2c3de2c53c4ec01e3fa1c931ba0a8cdc805ebc5/maturin-1.8.2-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:63ff7f612da90a26838a9c03aa8a80bab8b4e26f63e3df6ddb0e818394eb0aeb", size = 15126750 },
|
|
115
|
+
{ url = "https://files.pythonhosted.org/packages/cb/fa/aab9005b0edaeb04a47cc47b07fa4afa25484d2f72217b276e2a446b795f/maturin-1.8.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:c91504b4f05b07d0a9fb47c2a2a39c074328b6bc8f252190240e431f5f7ea8d7", size = 7885398 },
|
|
116
|
+
{ url = "https://files.pythonhosted.org/packages/24/59/0f12db41e683d82a48f92ac5499c89faa416036b3c3a7379b71aa1ce0ccb/maturin-1.8.2-py3-none-manylinux_2_12_i686.manylinux2010_i686.musllinux_1_1_i686.whl", hash = "sha256:05e3a2aa9611afa5e1205dfa1434607f9d8e223d613a8a7c85540a159af688c0", size = 7754886 },
|
|
117
|
+
{ url = "https://files.pythonhosted.org/packages/03/94/b9cb42cb5706389692b24f4691645e0b980708e46c9f008e89f4bb92a497/maturin-1.8.2-py3-none-manylinux_2_12_x86_64.manylinux2010_x86_64.musllinux_1_1_x86_64.whl", hash = "sha256:b408093e49d6d4ab98066eefd0fac64b01eb7af639e9b3151660c5fa96ce147c", size = 8226047 },
|
|
118
|
+
{ url = "https://files.pythonhosted.org/packages/1e/38/63c8198a626407b1cefa37670f9d995616249f541ed9616252895bb2710b/maturin-1.8.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:638c66616f9b10060197c48d9e1eedf444d975699d9cd829138e69014554cda7", size = 7485993 },
|
|
119
|
+
{ url = "https://files.pythonhosted.org/packages/d3/f3/8d7308902ab190a71c80bda92f3b72d446067fdf40a4c29d5de8e379f598/maturin-1.8.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.musllinux_1_1_armv7l.whl", hash = "sha256:c2001b5c57e0dbf5992be56b93ffa897d4bcd0d6ca3de448e381b621225d4d87", size = 7570380 },
|
|
120
|
+
{ url = "https://files.pythonhosted.org/packages/06/49/5458df84167506023b934b71488e75aa4a2f9af005f5659d9915adedca55/maturin-1.8.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.musllinux_1_1_ppc64le.whl", hash = "sha256:e015a5534aefb568b96a9cc7bc58995b1d90b5e2a44455d79e4f073a88cb0c83", size = 9811532 },
|
|
121
|
+
{ url = "https://files.pythonhosted.org/packages/d9/52/deb373d1a046287e6f77146204524adbf70184c5510ed95aab882570c69d/maturin-1.8.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5e624f73cb7fbfd8042e8c5cc5c11f58bede23a7931ea3ea9839812f5bd362fc", size = 10910211 },
|
|
122
|
+
{ url = "https://files.pythonhosted.org/packages/da/b8/f0475031de5f5328c8b2bbb9b50503a6b0a58b3c5cbe50a656c418ca7435/maturin-1.8.2-py3-none-win32.whl", hash = "sha256:4a62268975f98885a04ae9f0df875b304e4f8c1f0d989e8a7ab18e42793126ee", size = 6980868 },
|
|
123
|
+
{ url = "https://files.pythonhosted.org/packages/a2/f3/a67264d4ae3bf61a73abf616eba59543e0c8d182a77230703380f1858494/maturin-1.8.2-py3-none-win_amd64.whl", hash = "sha256:b6b29811013056f46a1e0b7f26907ae080028be65102d4fb23fbdf86847fffbd", size = 7886565 },
|
|
124
|
+
{ url = "https://files.pythonhosted.org/packages/5e/df/3641646696277249407c923795825176403c208a6553e0fd21b6764038b5/maturin-1.8.2-py3-none-win_arm64.whl", hash = "sha256:4232c2380faf61862d27269c6acf14e1d542c4ba64086a3f5c356d6e5e4823e7", size = 6656754 },
|
|
125
|
+
]
|
|
126
|
+
|
|
127
|
+
[[package]]
|
|
128
|
+
name = "packaging"
|
|
129
|
+
version = "24.2"
|
|
130
|
+
source = { registry = "https://pypi.org/simple" }
|
|
131
|
+
sdist = { url = "https://files.pythonhosted.org/packages/d0/63/68dbb6eb2de9cb10ee4c9c14a0148804425e13c4fb20d61cce69f53106da/packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f", size = 163950 }
|
|
132
|
+
wheels = [
|
|
133
|
+
{ url = "https://files.pythonhosted.org/packages/88/ef/eb23f262cca3c0c4eb7ab1933c3b1f03d021f2c48f54763065b6f0e321be/packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759", size = 65451 },
|
|
134
|
+
]
|
|
135
|
+
|
|
136
|
+
[[package]]
|
|
137
|
+
name = "pluggy"
|
|
138
|
+
version = "1.5.0"
|
|
139
|
+
source = { registry = "https://pypi.org/simple" }
|
|
140
|
+
sdist = { url = "https://files.pythonhosted.org/packages/96/2d/02d4312c973c6050a18b314a5ad0b3210edb65a906f868e31c111dede4a6/pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1", size = 67955 }
|
|
141
|
+
wheels = [
|
|
142
|
+
{ url = "https://files.pythonhosted.org/packages/88/5f/e351af9a41f866ac3f1fac4ca0613908d9a41741cfcf2228f4ad853b697d/pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669", size = 20556 },
|
|
143
|
+
]
|
|
144
|
+
|
|
145
|
+
[[package]]
|
|
146
|
+
name = "pytest"
|
|
147
|
+
version = "8.3.5"
|
|
148
|
+
source = { registry = "https://pypi.org/simple" }
|
|
149
|
+
dependencies = [
|
|
150
|
+
{ name = "colorama", marker = "sys_platform == 'win32'" },
|
|
151
|
+
{ name = "exceptiongroup", marker = "python_full_version < '3.11'" },
|
|
152
|
+
{ name = "iniconfig" },
|
|
153
|
+
{ name = "packaging" },
|
|
154
|
+
{ name = "pluggy" },
|
|
155
|
+
{ name = "tomli", marker = "python_full_version < '3.11'" },
|
|
156
|
+
]
|
|
157
|
+
sdist = { url = "https://files.pythonhosted.org/packages/ae/3c/c9d525a414d506893f0cd8a8d0de7706446213181570cdbd766691164e40/pytest-8.3.5.tar.gz", hash = "sha256:f4efe70cc14e511565ac476b57c279e12a855b11f48f212af1080ef2263d3845", size = 1450891 }
|
|
158
|
+
wheels = [
|
|
159
|
+
{ url = "https://files.pythonhosted.org/packages/30/3d/64ad57c803f1fa1e963a7946b6e0fea4a70df53c1a7fed304586539c2bac/pytest-8.3.5-py3-none-any.whl", hash = "sha256:c69214aa47deac29fad6c2a4f590b9c4a9fdb16a403176fe154b79c0b4d4d820", size = 343634 },
|
|
160
|
+
]
|
|
161
|
+
|
|
162
|
+
[[package]]
|
|
163
|
+
name = "sortedcontainers"
|
|
164
|
+
version = "2.4.0"
|
|
165
|
+
source = { registry = "https://pypi.org/simple" }
|
|
166
|
+
sdist = { url = "https://files.pythonhosted.org/packages/e8/c4/ba2f8066cceb6f23394729afe52f3bf7adec04bf9ed2c820b39e19299111/sortedcontainers-2.4.0.tar.gz", hash = "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88", size = 30594 }
|
|
167
|
+
wheels = [
|
|
168
|
+
{ url = "https://files.pythonhosted.org/packages/32/46/9cb0e58b2deb7f82b84065f37f3bffeb12413f947f9388e4cac22c4621ce/sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0", size = 29575 },
|
|
169
|
+
]
|
|
170
|
+
|
|
171
|
+
[[package]]
|
|
172
|
+
name = "tomli"
|
|
173
|
+
version = "2.2.1"
|
|
174
|
+
source = { registry = "https://pypi.org/simple" }
|
|
175
|
+
sdist = { url = "https://files.pythonhosted.org/packages/18/87/302344fed471e44a87289cf4967697d07e532f2421fdaf868a303cbae4ff/tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff", size = 17175 }
|
|
176
|
+
wheels = [
|
|
177
|
+
{ url = "https://files.pythonhosted.org/packages/43/ca/75707e6efa2b37c77dadb324ae7d9571cb424e61ea73fad7c56c2d14527f/tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249", size = 131077 },
|
|
178
|
+
{ url = "https://files.pythonhosted.org/packages/c7/16/51ae563a8615d472fdbffc43a3f3d46588c264ac4f024f63f01283becfbb/tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6", size = 123429 },
|
|
179
|
+
{ url = "https://files.pythonhosted.org/packages/f1/dd/4f6cd1e7b160041db83c694abc78e100473c15d54620083dbd5aae7b990e/tomli-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a", size = 226067 },
|
|
180
|
+
{ url = "https://files.pythonhosted.org/packages/a9/6b/c54ede5dc70d648cc6361eaf429304b02f2871a345bbdd51e993d6cdf550/tomli-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee", size = 236030 },
|
|
181
|
+
{ url = "https://files.pythonhosted.org/packages/1f/47/999514fa49cfaf7a92c805a86c3c43f4215621855d151b61c602abb38091/tomli-2.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e", size = 240898 },
|
|
182
|
+
{ url = "https://files.pythonhosted.org/packages/73/41/0a01279a7ae09ee1573b423318e7934674ce06eb33f50936655071d81a24/tomli-2.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4", size = 229894 },
|
|
183
|
+
{ url = "https://files.pythonhosted.org/packages/55/18/5d8bc5b0a0362311ce4d18830a5d28943667599a60d20118074ea1b01bb7/tomli-2.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106", size = 245319 },
|
|
184
|
+
{ url = "https://files.pythonhosted.org/packages/92/a3/7ade0576d17f3cdf5ff44d61390d4b3febb8a9fc2b480c75c47ea048c646/tomli-2.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8", size = 238273 },
|
|
185
|
+
{ url = "https://files.pythonhosted.org/packages/72/6f/fa64ef058ac1446a1e51110c375339b3ec6be245af9d14c87c4a6412dd32/tomli-2.2.1-cp311-cp311-win32.whl", hash = "sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff", size = 98310 },
|
|
186
|
+
{ url = "https://files.pythonhosted.org/packages/6a/1c/4a2dcde4a51b81be3530565e92eda625d94dafb46dbeb15069df4caffc34/tomli-2.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b", size = 108309 },
|
|
187
|
+
{ url = "https://files.pythonhosted.org/packages/52/e1/f8af4c2fcde17500422858155aeb0d7e93477a0d59a98e56cbfe75070fd0/tomli-2.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea", size = 132762 },
|
|
188
|
+
{ url = "https://files.pythonhosted.org/packages/03/b8/152c68bb84fc00396b83e7bbddd5ec0bd3dd409db4195e2a9b3e398ad2e3/tomli-2.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8", size = 123453 },
|
|
189
|
+
{ url = "https://files.pythonhosted.org/packages/c8/d6/fc9267af9166f79ac528ff7e8c55c8181ded34eb4b0e93daa767b8841573/tomli-2.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192", size = 233486 },
|
|
190
|
+
{ url = "https://files.pythonhosted.org/packages/5c/51/51c3f2884d7bab89af25f678447ea7d297b53b5a3b5730a7cb2ef6069f07/tomli-2.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222", size = 242349 },
|
|
191
|
+
{ url = "https://files.pythonhosted.org/packages/ab/df/bfa89627d13a5cc22402e441e8a931ef2108403db390ff3345c05253935e/tomli-2.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77", size = 252159 },
|
|
192
|
+
{ url = "https://files.pythonhosted.org/packages/9e/6e/fa2b916dced65763a5168c6ccb91066f7639bdc88b48adda990db10c8c0b/tomli-2.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6", size = 237243 },
|
|
193
|
+
{ url = "https://files.pythonhosted.org/packages/b4/04/885d3b1f650e1153cbb93a6a9782c58a972b94ea4483ae4ac5cedd5e4a09/tomli-2.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd", size = 259645 },
|
|
194
|
+
{ url = "https://files.pythonhosted.org/packages/9c/de/6b432d66e986e501586da298e28ebeefd3edc2c780f3ad73d22566034239/tomli-2.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e", size = 244584 },
|
|
195
|
+
{ url = "https://files.pythonhosted.org/packages/1c/9a/47c0449b98e6e7d1be6cbac02f93dd79003234ddc4aaab6ba07a9a7482e2/tomli-2.2.1-cp312-cp312-win32.whl", hash = "sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98", size = 98875 },
|
|
196
|
+
{ url = "https://files.pythonhosted.org/packages/ef/60/9b9638f081c6f1261e2688bd487625cd1e660d0a85bd469e91d8db969734/tomli-2.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4", size = 109418 },
|
|
197
|
+
{ url = "https://files.pythonhosted.org/packages/04/90/2ee5f2e0362cb8a0b6499dc44f4d7d48f8fff06d28ba46e6f1eaa61a1388/tomli-2.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7", size = 132708 },
|
|
198
|
+
{ url = "https://files.pythonhosted.org/packages/c0/ec/46b4108816de6b385141f082ba99e315501ccd0a2ea23db4a100dd3990ea/tomli-2.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c", size = 123582 },
|
|
199
|
+
{ url = "https://files.pythonhosted.org/packages/a0/bd/b470466d0137b37b68d24556c38a0cc819e8febe392d5b199dcd7f578365/tomli-2.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13", size = 232543 },
|
|
200
|
+
{ url = "https://files.pythonhosted.org/packages/d9/e5/82e80ff3b751373f7cead2815bcbe2d51c895b3c990686741a8e56ec42ab/tomli-2.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281", size = 241691 },
|
|
201
|
+
{ url = "https://files.pythonhosted.org/packages/05/7e/2a110bc2713557d6a1bfb06af23dd01e7dde52b6ee7dadc589868f9abfac/tomli-2.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272", size = 251170 },
|
|
202
|
+
{ url = "https://files.pythonhosted.org/packages/64/7b/22d713946efe00e0adbcdfd6d1aa119ae03fd0b60ebed51ebb3fa9f5a2e5/tomli-2.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140", size = 236530 },
|
|
203
|
+
{ url = "https://files.pythonhosted.org/packages/38/31/3a76f67da4b0cf37b742ca76beaf819dca0ebef26d78fc794a576e08accf/tomli-2.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2", size = 258666 },
|
|
204
|
+
{ url = "https://files.pythonhosted.org/packages/07/10/5af1293da642aded87e8a988753945d0cf7e00a9452d3911dd3bb354c9e2/tomli-2.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744", size = 243954 },
|
|
205
|
+
{ url = "https://files.pythonhosted.org/packages/5b/b9/1ed31d167be802da0fc95020d04cd27b7d7065cc6fbefdd2f9186f60d7bd/tomli-2.2.1-cp313-cp313-win32.whl", hash = "sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec", size = 98724 },
|
|
206
|
+
{ url = "https://files.pythonhosted.org/packages/c7/32/b0963458706accd9afcfeb867c0f9175a741bf7b19cd424230714d722198/tomli-2.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69", size = 109383 },
|
|
207
|
+
{ url = "https://files.pythonhosted.org/packages/6e/c2/61d3e0f47e2b74ef40a68b9e6ad5984f6241a942f7cd3bbfbdbd03861ea9/tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc", size = 14257 },
|
|
208
|
+
]
|