dynamo-pydantic 0.1.1__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.
- dynamo_pydantic-0.1.1/.gitignore +357 -0
- dynamo_pydantic-0.1.1/LICENSE +24 -0
- dynamo_pydantic-0.1.1/PKG-INFO +154 -0
- dynamo_pydantic-0.1.1/README.md +135 -0
- dynamo_pydantic-0.1.1/dynamo_pydantic/__init__.py +7 -0
- dynamo_pydantic-0.1.1/dynamo_pydantic/_internal/__init__.py +8 -0
- dynamo_pydantic-0.1.1/dynamo_pydantic/_internal/batching.py +155 -0
- dynamo_pydantic-0.1.1/dynamo_pydantic/_internal/client_subclass_mapping.py +91 -0
- dynamo_pydantic-0.1.1/dynamo_pydantic/_internal/dynamic_subclass.py +57 -0
- dynamo_pydantic-0.1.1/dynamo_pydantic/_internal/find_annotated.py +51 -0
- dynamo_pydantic-0.1.1/dynamo_pydantic/_internal/internal_types.py +44 -0
- dynamo_pydantic-0.1.1/dynamo_pydantic/_internal/pydantic_utils.py +69 -0
- dynamo_pydantic-0.1.1/dynamo_pydantic/_internal/query_criteria.py +585 -0
- dynamo_pydantic-0.1.1/dynamo_pydantic/dates.py +36 -0
- dynamo_pydantic-0.1.1/dynamo_pydantic/dynamo_model.py +155 -0
- dynamo_pydantic-0.1.1/dynamo_pydantic/errors.py +21 -0
- dynamo_pydantic-0.1.1/dynamo_pydantic/obj_manager.py +1247 -0
- dynamo_pydantic-0.1.1/dynamo_pydantic/settings.py +31 -0
- dynamo_pydantic-0.1.1/dynamo_pydantic/table.py +218 -0
- dynamo_pydantic-0.1.1/dynamo_pydantic/types.py +180 -0
- dynamo_pydantic-0.1.1/pyproject.toml +99 -0
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
|
|
2
|
+
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
|
3
|
+
|
|
4
|
+
# For now, just ignore all .idea files
|
|
5
|
+
.idea
|
|
6
|
+
|
|
7
|
+
/api
|
|
8
|
+
/scripts
|
|
9
|
+
|
|
10
|
+
# User-specific stuff
|
|
11
|
+
.idea/**/workspace.xml
|
|
12
|
+
.idea/**/tasks.xml
|
|
13
|
+
.idea/**/usage.statistics.xml
|
|
14
|
+
.idea/**/dictionaries
|
|
15
|
+
.idea/**/shelf
|
|
16
|
+
|
|
17
|
+
# AWS User-specific
|
|
18
|
+
.idea/**/aws.xml
|
|
19
|
+
|
|
20
|
+
# Generated files
|
|
21
|
+
.idea/**/contentModel.xml
|
|
22
|
+
|
|
23
|
+
# Sensitive or high-churn files
|
|
24
|
+
.idea/**/dataSources/
|
|
25
|
+
.idea/**/dataSources.ids
|
|
26
|
+
.idea/**/dataSources.local.xml
|
|
27
|
+
.idea/**/sqlDataSources.xml
|
|
28
|
+
.idea/**/dynamic.xml
|
|
29
|
+
.idea/**/uiDesigner.xml
|
|
30
|
+
.idea/**/dbnavigator.xml
|
|
31
|
+
|
|
32
|
+
# Gradle
|
|
33
|
+
.idea/**/gradle.xml
|
|
34
|
+
.idea/**/libraries
|
|
35
|
+
|
|
36
|
+
# Gradle and Maven with auto-import
|
|
37
|
+
# When using Gradle or Maven with auto-import, you should exclude module files,
|
|
38
|
+
# since they will be recreated, and may cause churn. Uncomment if using
|
|
39
|
+
# auto-import.
|
|
40
|
+
# .idea/artifacts
|
|
41
|
+
# .idea/compiler.xml
|
|
42
|
+
# .idea/jarRepositories.xml
|
|
43
|
+
# .idea/modules.xml
|
|
44
|
+
# .idea/*.iml
|
|
45
|
+
# .idea/modules
|
|
46
|
+
# *.iml
|
|
47
|
+
# *.ipr
|
|
48
|
+
|
|
49
|
+
# CMake
|
|
50
|
+
cmake-build-*/
|
|
51
|
+
|
|
52
|
+
# Mongo Explorer plugin
|
|
53
|
+
.idea/**/mongoSettings.xml
|
|
54
|
+
|
|
55
|
+
# File-based project format
|
|
56
|
+
*.iws
|
|
57
|
+
|
|
58
|
+
# IntelliJ
|
|
59
|
+
out/
|
|
60
|
+
|
|
61
|
+
# mpeltonen/sbt-idea plugin
|
|
62
|
+
.idea_modules/
|
|
63
|
+
|
|
64
|
+
# JIRA plugin
|
|
65
|
+
atlassian-ide-plugin.xml
|
|
66
|
+
|
|
67
|
+
# Cursive Clojure plugin
|
|
68
|
+
.idea/replstate.xml
|
|
69
|
+
|
|
70
|
+
# Crashlytics plugin (for Android Studio and IntelliJ)
|
|
71
|
+
com_crashlytics_export_strings.xml
|
|
72
|
+
crashlytics.properties
|
|
73
|
+
crashlytics-build.properties
|
|
74
|
+
fabric.properties
|
|
75
|
+
|
|
76
|
+
# Editor-based Rest Client
|
|
77
|
+
.idea/httpRequests
|
|
78
|
+
|
|
79
|
+
# Android studio 3.1+ serialized cache file
|
|
80
|
+
.idea/caches/build_file_checksums.ser
|
|
81
|
+
# Logs
|
|
82
|
+
logs
|
|
83
|
+
*.log
|
|
84
|
+
npm-debug.log*
|
|
85
|
+
yarn-debug.log*
|
|
86
|
+
yarn-error.log*
|
|
87
|
+
lerna-debug.log*
|
|
88
|
+
.pnpm-debug.log*
|
|
89
|
+
|
|
90
|
+
# Diagnostic reports (https://nodejs.org/api/report.html)
|
|
91
|
+
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
|
92
|
+
|
|
93
|
+
# Runtime data
|
|
94
|
+
pids
|
|
95
|
+
*.pid
|
|
96
|
+
*.seed
|
|
97
|
+
*.pid.lock
|
|
98
|
+
|
|
99
|
+
# Directory for instrumented libs generated by jscoverage/JSCover
|
|
100
|
+
lib-cov
|
|
101
|
+
|
|
102
|
+
# Coverage directory used by tools like istanbul
|
|
103
|
+
coverage
|
|
104
|
+
*.lcov
|
|
105
|
+
|
|
106
|
+
# nyc test coverage
|
|
107
|
+
.nyc_output
|
|
108
|
+
|
|
109
|
+
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
|
110
|
+
.grunt
|
|
111
|
+
|
|
112
|
+
# Bower dependency directory (https://bower.io/)
|
|
113
|
+
bower_components
|
|
114
|
+
|
|
115
|
+
# node-waf configuration
|
|
116
|
+
.lock-wscript
|
|
117
|
+
|
|
118
|
+
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
|
119
|
+
build/Release
|
|
120
|
+
|
|
121
|
+
# Dependency directories
|
|
122
|
+
node_modules/
|
|
123
|
+
jspm_packages/
|
|
124
|
+
|
|
125
|
+
# Snowpack dependency directory (https://snowpack.dev/)
|
|
126
|
+
web_modules/
|
|
127
|
+
|
|
128
|
+
# TypeScript cache
|
|
129
|
+
*.tsbuildinfo
|
|
130
|
+
|
|
131
|
+
# Optional npm cache directory
|
|
132
|
+
.npm
|
|
133
|
+
|
|
134
|
+
# Optional eslint cache
|
|
135
|
+
.eslintcache
|
|
136
|
+
|
|
137
|
+
# Microbundle cache
|
|
138
|
+
.rpt2_cache/
|
|
139
|
+
.rts2_cache_cjs/
|
|
140
|
+
.rts2_cache_es/
|
|
141
|
+
.rts2_cache_umd/
|
|
142
|
+
|
|
143
|
+
# Optional REPL history
|
|
144
|
+
.node_repl_history
|
|
145
|
+
|
|
146
|
+
# Output of 'npm pack'
|
|
147
|
+
*.tgz
|
|
148
|
+
|
|
149
|
+
# Yarn Integrity file
|
|
150
|
+
.yarn-integrity
|
|
151
|
+
|
|
152
|
+
# dotenv environment variables file
|
|
153
|
+
.env
|
|
154
|
+
.env.test
|
|
155
|
+
.env.production
|
|
156
|
+
|
|
157
|
+
# parcel-bundler cache (https://parceljs.org/)
|
|
158
|
+
.cache
|
|
159
|
+
.parcel-cache
|
|
160
|
+
|
|
161
|
+
# Next.js build output
|
|
162
|
+
.next
|
|
163
|
+
out
|
|
164
|
+
|
|
165
|
+
# Nuxt.js build / generate output
|
|
166
|
+
.nuxt
|
|
167
|
+
dist
|
|
168
|
+
|
|
169
|
+
# Gatsby files
|
|
170
|
+
.cache/
|
|
171
|
+
# Comment in the public line in if your project uses Gatsby and not Next.js
|
|
172
|
+
# https://nextjs.org/blog/next-9-1#public-directory-support
|
|
173
|
+
# public
|
|
174
|
+
|
|
175
|
+
# vuepress build output
|
|
176
|
+
.vuepress/dist
|
|
177
|
+
|
|
178
|
+
# Serverless directories
|
|
179
|
+
.serverless/
|
|
180
|
+
|
|
181
|
+
# FuseBox cache
|
|
182
|
+
.fusebox/
|
|
183
|
+
|
|
184
|
+
# DynamoDB Local files
|
|
185
|
+
.dynamodb/
|
|
186
|
+
|
|
187
|
+
# TernJS port file
|
|
188
|
+
.tern-port
|
|
189
|
+
|
|
190
|
+
# Stores VSCode versions used for testing VSCode extensions
|
|
191
|
+
.vscode-test
|
|
192
|
+
|
|
193
|
+
# yarn v2
|
|
194
|
+
.yarn/cache
|
|
195
|
+
.yarn/unplugged
|
|
196
|
+
.yarn/build-state.yml
|
|
197
|
+
.yarn/install-state.gz
|
|
198
|
+
.pnp.*
|
|
199
|
+
# Byte-compiled / optimized / DLL files
|
|
200
|
+
__pycache__/
|
|
201
|
+
*.py[cod]
|
|
202
|
+
*$py.class
|
|
203
|
+
|
|
204
|
+
# C extensions
|
|
205
|
+
*.so
|
|
206
|
+
|
|
207
|
+
# Distribution / packaging
|
|
208
|
+
.Python
|
|
209
|
+
build/
|
|
210
|
+
develop-eggs/
|
|
211
|
+
dist/
|
|
212
|
+
downloads/
|
|
213
|
+
eggs/
|
|
214
|
+
.eggs/
|
|
215
|
+
/lib/
|
|
216
|
+
lib64/
|
|
217
|
+
parts/
|
|
218
|
+
sdist/
|
|
219
|
+
var/
|
|
220
|
+
wheels/
|
|
221
|
+
share/python-wheels/
|
|
222
|
+
*.egg-info/
|
|
223
|
+
.installed.cfg
|
|
224
|
+
*.egg
|
|
225
|
+
MANIFEST
|
|
226
|
+
|
|
227
|
+
# PyInstaller
|
|
228
|
+
# Usually these files are written by a python script from a template
|
|
229
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
230
|
+
*.manifest
|
|
231
|
+
*.spec
|
|
232
|
+
|
|
233
|
+
# Installer logs
|
|
234
|
+
pip-log.txt
|
|
235
|
+
pip-delete-this-directory.txt
|
|
236
|
+
|
|
237
|
+
# Unit test / coverage reports
|
|
238
|
+
htmlcov/
|
|
239
|
+
.tox/
|
|
240
|
+
.nox/
|
|
241
|
+
.coverage
|
|
242
|
+
.coverage.*
|
|
243
|
+
.cache
|
|
244
|
+
nosetests.xml
|
|
245
|
+
coverage.xml
|
|
246
|
+
*.cover
|
|
247
|
+
*.py,cover
|
|
248
|
+
.hypothesis/
|
|
249
|
+
.pytest_cache/
|
|
250
|
+
cover/
|
|
251
|
+
|
|
252
|
+
# Translations
|
|
253
|
+
*.mo
|
|
254
|
+
*.pot
|
|
255
|
+
|
|
256
|
+
# Django stuff:
|
|
257
|
+
*.log
|
|
258
|
+
local_settings.py
|
|
259
|
+
db.sqlite3
|
|
260
|
+
db.sqlite3-journal
|
|
261
|
+
|
|
262
|
+
# Flask stuff:
|
|
263
|
+
instance/
|
|
264
|
+
.webassets-cache
|
|
265
|
+
|
|
266
|
+
# Scrapy stuff:
|
|
267
|
+
.scrapy
|
|
268
|
+
|
|
269
|
+
# Sphinx documentation
|
|
270
|
+
docs/_build/
|
|
271
|
+
|
|
272
|
+
# PyBuilder
|
|
273
|
+
.pybuilder/
|
|
274
|
+
target/
|
|
275
|
+
|
|
276
|
+
# Jupyter Notebook
|
|
277
|
+
.ipynb_checkpoints
|
|
278
|
+
|
|
279
|
+
# IPython
|
|
280
|
+
profile_default/
|
|
281
|
+
ipython_config.py
|
|
282
|
+
|
|
283
|
+
# pyenv
|
|
284
|
+
# For a library or package, you might want to ignore these files since the code is
|
|
285
|
+
# intended to run in multiple environments; otherwise, check them in:
|
|
286
|
+
.python-version
|
|
287
|
+
|
|
288
|
+
# pipenv
|
|
289
|
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
290
|
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
291
|
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
292
|
+
# install all needed dependencies.
|
|
293
|
+
#Pipfile.lock
|
|
294
|
+
|
|
295
|
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
|
|
296
|
+
__pypackages__/
|
|
297
|
+
|
|
298
|
+
# Celery stuff
|
|
299
|
+
celerybeat-schedule
|
|
300
|
+
celerybeat.pid
|
|
301
|
+
|
|
302
|
+
# SageMath parsed files
|
|
303
|
+
*.sage.py
|
|
304
|
+
|
|
305
|
+
# Environments
|
|
306
|
+
.env
|
|
307
|
+
.venv
|
|
308
|
+
env/
|
|
309
|
+
venv/
|
|
310
|
+
ENV/
|
|
311
|
+
env.bak/
|
|
312
|
+
venv.bak/
|
|
313
|
+
|
|
314
|
+
# Spyder project settings
|
|
315
|
+
.spyderproject
|
|
316
|
+
.spyproject
|
|
317
|
+
|
|
318
|
+
# Rope project settings
|
|
319
|
+
.ropeproject
|
|
320
|
+
|
|
321
|
+
# mkdocs documentation
|
|
322
|
+
/site
|
|
323
|
+
|
|
324
|
+
# mypy
|
|
325
|
+
.mypy_cache/
|
|
326
|
+
.dmypy.json
|
|
327
|
+
dmypy.json
|
|
328
|
+
|
|
329
|
+
# Pyre type checker
|
|
330
|
+
.pyre/
|
|
331
|
+
|
|
332
|
+
# pytype static type analyzer
|
|
333
|
+
.pytype/
|
|
334
|
+
|
|
335
|
+
# Cython debug symbols
|
|
336
|
+
cython_debug/
|
|
337
|
+
# bit components
|
|
338
|
+
.bit
|
|
339
|
+
|
|
340
|
+
# Unit test reporting used by CodeFresh
|
|
341
|
+
allure-results/
|
|
342
|
+
|
|
343
|
+
# Additional build directories
|
|
344
|
+
_build/
|
|
345
|
+
builds/
|
|
346
|
+
build-*
|
|
347
|
+
web
|
|
348
|
+
|
|
349
|
+
# DB and other data files
|
|
350
|
+
data/
|
|
351
|
+
|
|
352
|
+
# local environment settings
|
|
353
|
+
.env*.local
|
|
354
|
+
.env.dynamic
|
|
355
|
+
|
|
356
|
+
# Root tomlVersionUpdater as repo install puts it in place and keeps it updated
|
|
357
|
+
/tomlVersionUpdater.js
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
This is free and unencumbered software released into the public domain.
|
|
2
|
+
|
|
3
|
+
Anyone is free to copy, modify, publish, use, compile, sell, or
|
|
4
|
+
distribute this software, either in source code form or as a compiled
|
|
5
|
+
binary, for any purpose, commercial or non-commercial, and by any
|
|
6
|
+
means.
|
|
7
|
+
|
|
8
|
+
In jurisdictions that recognize copyright laws, the author or authors
|
|
9
|
+
of this software dedicate any and all copyright interest in the
|
|
10
|
+
software to the public domain. We make this dedication for the benefit
|
|
11
|
+
of the public at large and to the detriment of our heirs and
|
|
12
|
+
successors. We intend this dedication to be an overt act of
|
|
13
|
+
relinquishment in perpetuity of all present and future rights to this
|
|
14
|
+
software under copyright law.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
19
|
+
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
|
20
|
+
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
|
21
|
+
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
22
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
|
23
|
+
|
|
24
|
+
For more information, please refer to <https://unlicense.org>
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: dynamo-pydantic
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Summary: Pydantic base models for DynamoDB, with easy to use save/delete/query/get.
|
|
5
|
+
Project-URL: Repository, https://github.com/joshorr/dynamo-pydantic
|
|
6
|
+
Author-email: Josh Orr <josh@orr.blue>
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Classifier: License :: OSI Approved :: The Unlicense (Unlicense)
|
|
9
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
10
|
+
Requires-Python: <4,>=3.14
|
|
11
|
+
Requires-Dist: pydantic<3,>=2.9.2
|
|
12
|
+
Requires-Dist: xbool<2,>=1.1.0
|
|
13
|
+
Requires-Dist: xboto<2,>=1.1.1
|
|
14
|
+
Requires-Dist: xinject<2,>=1.4.0
|
|
15
|
+
Requires-Dist: xloop<2,>=1.0.1
|
|
16
|
+
Requires-Dist: xsentinels<2,>=1.2.1
|
|
17
|
+
Requires-Dist: xurls<2,>=1.2.1
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
|
|
20
|
+

|
|
21
|
+

|
|
22
|
+
|
|
23
|
+
(documentation below is a work in progress)
|
|
24
|
+
|
|
25
|
+
- [Quick Start](#quick-start)
|
|
26
|
+
- [Detail Docs](#detail-docs)
|
|
27
|
+
- [Overview](#overview)
|
|
28
|
+
* [Quick high-level overview of features](#quick-high-level-overview-of-features)
|
|
29
|
+
- [More Docs Soon To Come](#more-docs-soon-to-come)
|
|
30
|
+
|
|
31
|
+
# Quick Start
|
|
32
|
+
|
|
33
|
+
> [!WARNING]
|
|
34
|
+
> This is pre-release Beta software, based on another code base and
|
|
35
|
+
> the needed changes to make a final release version are not yet
|
|
36
|
+
> completed. Everything is subject to change!
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
```shell
|
|
40
|
+
uv add dynamo-pydantic
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
or
|
|
44
|
+
|
|
45
|
+
```shell
|
|
46
|
+
pip install dynamo-pydantic
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Very basic example:
|
|
50
|
+
|
|
51
|
+
```python
|
|
52
|
+
from dynamo_pydantic import DynamoModel, HashField, SortField
|
|
53
|
+
|
|
54
|
+
class MyModel(DynamoModel):
|
|
55
|
+
some_attr: HashField[str]
|
|
56
|
+
another_attr: str
|
|
57
|
+
|
|
58
|
+
obj = MyModel(some_attr='a-value', another_attr='b-value')
|
|
59
|
+
|
|
60
|
+
# Saves into a dynamo table called `myModel`.
|
|
61
|
+
# (See DynObjManager, accessed via DynamoModel.dyn_objs; for more docs around table naming options)
|
|
62
|
+
obj.dyn_save()
|
|
63
|
+
|
|
64
|
+
# Query for object
|
|
65
|
+
assert MyModel.dyn_objs.get_first({'some_attr': 'a-value'}).another_attr == 'b-value'
|
|
66
|
+
|
|
67
|
+
# Delete Object
|
|
68
|
+
obj.dyn_delete()
|
|
69
|
+
|
|
70
|
+
# Not There Anymore.
|
|
71
|
+
assert next(MyModel.dyn_objs.get({'some_attr': 'a-value'}), None) is None
|
|
72
|
+
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
# Detail Docs
|
|
77
|
+
|
|
78
|
+
**[📄 Detailed Documentation](https://joshorr.github.io/dynamo-pydantic/latest/)** | **[🐍 PyPi](https://pypi.org/project/dynamo-pydantic/)**
|
|
79
|
+
|
|
80
|
+
# Overview
|
|
81
|
+
|
|
82
|
+
This is a port of my old `xdynamo` library to use pydantic.
|
|
83
|
+
|
|
84
|
+
Allows easy use of Pydantic models with DynamoDB using a Django-like query syntax.
|
|
85
|
+
|
|
86
|
+
Right now you use a dict to communicate query filtering:
|
|
87
|
+
|
|
88
|
+
`MyModel.dyn_objs.get({'some_hash_field': 'some-value'})`
|
|
89
|
+
|
|
90
|
+
In the future, I'll have a simple QuerySet like object/class for filtering,
|
|
91
|
+
modeled somewhat on Django's QuerySet class.
|
|
92
|
+
|
|
93
|
+
But for now, I am starting with `.get(...)`, with the objective being you can
|
|
94
|
+
directly communicate url-query params into this get to grab desired objects.
|
|
95
|
+
|
|
96
|
+
The `dyn_objs` manager object will figure out the best way to query DynamoDB
|
|
97
|
+
based on the query attributes/values you provide. Sort of a much simplified
|
|
98
|
+
version of a relational-database query planner.
|
|
99
|
+
|
|
100
|
+
This allows for one to focus on querying your model and dynamo in various ways
|
|
101
|
+
without having to figure out exactly the best way in every possible case
|
|
102
|
+
when you have the potential for both simple and more complex queries.
|
|
103
|
+
|
|
104
|
+
Right now, secondary/global indexes are not supported.
|
|
105
|
+
They will be added in a future update.
|
|
106
|
+
When indexes get added, the plan is for the simplified query planner
|
|
107
|
+
to automatically use the index as needed.
|
|
108
|
+
|
|
109
|
+
The `get` method also by default won't do scans when given a query.
|
|
110
|
+
Unless you tell it via a parameter `allow_scan=True` to tell query-panner
|
|
111
|
+
if it's ok to automatically drop down into a scan if it's the only way
|
|
112
|
+
to do a query.
|
|
113
|
+
|
|
114
|
+
In addition to the general `get` method that does query-planning,
|
|
115
|
+
there are also a set of explicit methods for ensuring you always do a
|
|
116
|
+
query, scan, etc.; as other manager methods `.query(...)`, `.scan(...)`, etc.
|
|
117
|
+
|
|
118
|
+
You can bulk-save objects via `MyModel.dyn_objs.save([obj1, obj2, ...])`,
|
|
119
|
+
or single-save them via `my_obj.dyn_save()` or `MyModel.dyn_objs.save(my_obj)`.
|
|
120
|
+
|
|
121
|
+
## Quick high-level overview of features
|
|
122
|
+
|
|
123
|
+
- Supports multiple hash/sort fields
|
|
124
|
+
- Hash/Sort fields are defined on class, the hash/sort-key is defined on table.
|
|
125
|
+
- If there are multiple hash or sort fields, they are combined into their respective hash/sort key via a deliminator.
|
|
126
|
+
- The deliminator does not have to be unique/unused in field data because it won't need to be parsed later,
|
|
127
|
+
it is only used to make the key properly unique to object.
|
|
128
|
+
- By default, these key-fields are inherited, so you can add more hash/sort fields in subclasses,
|
|
129
|
+
and these will be combined with any defined in the parent-class.
|
|
130
|
+
- The individual hahs/sort fields are still stored separately into their own attribute in the dynamo table item.
|
|
131
|
+
- When querying for an item, provide a value for each hash field (and optionally any sort fields).
|
|
132
|
+
- They will automatically be combined and used for the final hash/sort key for table query.
|
|
133
|
+
|
|
134
|
+
- Use `dynamo_pydantic.UtcDateTime` type to force a datetime to always be and serialize into utc.
|
|
135
|
+
- You can use this with hash and/or sort keys with datetime in them, so they can reliably be queried for.
|
|
136
|
+
- Because we must use a string for a datetime, so if format and timezone are always the same it can be reliably sorted and queried for.
|
|
137
|
+
- Use `UtcDateTimeNow` to default value to now in utc.
|
|
138
|
+
- Example Field: `created_at: UtcDateTimeNow`
|
|
139
|
+
|
|
140
|
+
- Can Auto-create tables lazy, on first use if desired.
|
|
141
|
+
- By default, this won't happen.
|
|
142
|
+
- If you set `dynamo_pydantic.dyn_settings.create_tables_if_needed = True`, it will create the tables lazily.
|
|
143
|
+
|
|
144
|
+
# More Docs Soon To Come
|
|
145
|
+
|
|
146
|
+
I'll have more, detailed documentation soon, along with examples.
|
|
147
|
+
|
|
148
|
+
I need to rewrite my old docs from the old library for the new way of doing things as I took this opportunity
|
|
149
|
+
to simplify and rearranged things (compared to old library).
|
|
150
|
+
|
|
151
|
+
For now, I have a basic outline above, and some refrence documentation here:
|
|
152
|
+
|
|
153
|
+
**[📄 Detailed Documentation](https://joshorr.github.io/dynamo-pydantic/latest/)**
|
|
154
|
+
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+

|
|
2
|
+

|
|
3
|
+
|
|
4
|
+
(documentation below is a work in progress)
|
|
5
|
+
|
|
6
|
+
- [Quick Start](#quick-start)
|
|
7
|
+
- [Detail Docs](#detail-docs)
|
|
8
|
+
- [Overview](#overview)
|
|
9
|
+
* [Quick high-level overview of features](#quick-high-level-overview-of-features)
|
|
10
|
+
- [More Docs Soon To Come](#more-docs-soon-to-come)
|
|
11
|
+
|
|
12
|
+
# Quick Start
|
|
13
|
+
|
|
14
|
+
> [!WARNING]
|
|
15
|
+
> This is pre-release Beta software, based on another code base and
|
|
16
|
+
> the needed changes to make a final release version are not yet
|
|
17
|
+
> completed. Everything is subject to change!
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
```shell
|
|
21
|
+
uv add dynamo-pydantic
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
or
|
|
25
|
+
|
|
26
|
+
```shell
|
|
27
|
+
pip install dynamo-pydantic
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Very basic example:
|
|
31
|
+
|
|
32
|
+
```python
|
|
33
|
+
from dynamo_pydantic import DynamoModel, HashField, SortField
|
|
34
|
+
|
|
35
|
+
class MyModel(DynamoModel):
|
|
36
|
+
some_attr: HashField[str]
|
|
37
|
+
another_attr: str
|
|
38
|
+
|
|
39
|
+
obj = MyModel(some_attr='a-value', another_attr='b-value')
|
|
40
|
+
|
|
41
|
+
# Saves into a dynamo table called `myModel`.
|
|
42
|
+
# (See DynObjManager, accessed via DynamoModel.dyn_objs; for more docs around table naming options)
|
|
43
|
+
obj.dyn_save()
|
|
44
|
+
|
|
45
|
+
# Query for object
|
|
46
|
+
assert MyModel.dyn_objs.get_first({'some_attr': 'a-value'}).another_attr == 'b-value'
|
|
47
|
+
|
|
48
|
+
# Delete Object
|
|
49
|
+
obj.dyn_delete()
|
|
50
|
+
|
|
51
|
+
# Not There Anymore.
|
|
52
|
+
assert next(MyModel.dyn_objs.get({'some_attr': 'a-value'}), None) is None
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
# Detail Docs
|
|
58
|
+
|
|
59
|
+
**[📄 Detailed Documentation](https://joshorr.github.io/dynamo-pydantic/latest/)** | **[🐍 PyPi](https://pypi.org/project/dynamo-pydantic/)**
|
|
60
|
+
|
|
61
|
+
# Overview
|
|
62
|
+
|
|
63
|
+
This is a port of my old `xdynamo` library to use pydantic.
|
|
64
|
+
|
|
65
|
+
Allows easy use of Pydantic models with DynamoDB using a Django-like query syntax.
|
|
66
|
+
|
|
67
|
+
Right now you use a dict to communicate query filtering:
|
|
68
|
+
|
|
69
|
+
`MyModel.dyn_objs.get({'some_hash_field': 'some-value'})`
|
|
70
|
+
|
|
71
|
+
In the future, I'll have a simple QuerySet like object/class for filtering,
|
|
72
|
+
modeled somewhat on Django's QuerySet class.
|
|
73
|
+
|
|
74
|
+
But for now, I am starting with `.get(...)`, with the objective being you can
|
|
75
|
+
directly communicate url-query params into this get to grab desired objects.
|
|
76
|
+
|
|
77
|
+
The `dyn_objs` manager object will figure out the best way to query DynamoDB
|
|
78
|
+
based on the query attributes/values you provide. Sort of a much simplified
|
|
79
|
+
version of a relational-database query planner.
|
|
80
|
+
|
|
81
|
+
This allows for one to focus on querying your model and dynamo in various ways
|
|
82
|
+
without having to figure out exactly the best way in every possible case
|
|
83
|
+
when you have the potential for both simple and more complex queries.
|
|
84
|
+
|
|
85
|
+
Right now, secondary/global indexes are not supported.
|
|
86
|
+
They will be added in a future update.
|
|
87
|
+
When indexes get added, the plan is for the simplified query planner
|
|
88
|
+
to automatically use the index as needed.
|
|
89
|
+
|
|
90
|
+
The `get` method also by default won't do scans when given a query.
|
|
91
|
+
Unless you tell it via a parameter `allow_scan=True` to tell query-panner
|
|
92
|
+
if it's ok to automatically drop down into a scan if it's the only way
|
|
93
|
+
to do a query.
|
|
94
|
+
|
|
95
|
+
In addition to the general `get` method that does query-planning,
|
|
96
|
+
there are also a set of explicit methods for ensuring you always do a
|
|
97
|
+
query, scan, etc.; as other manager methods `.query(...)`, `.scan(...)`, etc.
|
|
98
|
+
|
|
99
|
+
You can bulk-save objects via `MyModel.dyn_objs.save([obj1, obj2, ...])`,
|
|
100
|
+
or single-save them via `my_obj.dyn_save()` or `MyModel.dyn_objs.save(my_obj)`.
|
|
101
|
+
|
|
102
|
+
## Quick high-level overview of features
|
|
103
|
+
|
|
104
|
+
- Supports multiple hash/sort fields
|
|
105
|
+
- Hash/Sort fields are defined on class, the hash/sort-key is defined on table.
|
|
106
|
+
- If there are multiple hash or sort fields, they are combined into their respective hash/sort key via a deliminator.
|
|
107
|
+
- The deliminator does not have to be unique/unused in field data because it won't need to be parsed later,
|
|
108
|
+
it is only used to make the key properly unique to object.
|
|
109
|
+
- By default, these key-fields are inherited, so you can add more hash/sort fields in subclasses,
|
|
110
|
+
and these will be combined with any defined in the parent-class.
|
|
111
|
+
- The individual hahs/sort fields are still stored separately into their own attribute in the dynamo table item.
|
|
112
|
+
- When querying for an item, provide a value for each hash field (and optionally any sort fields).
|
|
113
|
+
- They will automatically be combined and used for the final hash/sort key for table query.
|
|
114
|
+
|
|
115
|
+
- Use `dynamo_pydantic.UtcDateTime` type to force a datetime to always be and serialize into utc.
|
|
116
|
+
- You can use this with hash and/or sort keys with datetime in them, so they can reliably be queried for.
|
|
117
|
+
- Because we must use a string for a datetime, so if format and timezone are always the same it can be reliably sorted and queried for.
|
|
118
|
+
- Use `UtcDateTimeNow` to default value to now in utc.
|
|
119
|
+
- Example Field: `created_at: UtcDateTimeNow`
|
|
120
|
+
|
|
121
|
+
- Can Auto-create tables lazy, on first use if desired.
|
|
122
|
+
- By default, this won't happen.
|
|
123
|
+
- If you set `dynamo_pydantic.dyn_settings.create_tables_if_needed = True`, it will create the tables lazily.
|
|
124
|
+
|
|
125
|
+
# More Docs Soon To Come
|
|
126
|
+
|
|
127
|
+
I'll have more, detailed documentation soon, along with examples.
|
|
128
|
+
|
|
129
|
+
I need to rewrite my old docs from the old library for the new way of doing things as I took this opportunity
|
|
130
|
+
to simplify and rearranged things (compared to old library).
|
|
131
|
+
|
|
132
|
+
For now, I have a basic outline above, and some refrence documentation here:
|
|
133
|
+
|
|
134
|
+
**[📄 Detailed Documentation](https://joshorr.github.io/dynamo-pydantic/latest/)**
|
|
135
|
+
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
from .query_criteria import QueryCriteria, DynKey
|
|
2
|
+
from .internal_types import get_dynamo_type_from_python_type
|
|
3
|
+
from .dynamic_subclass import create_generic_submodel
|
|
4
|
+
from . import batching
|
|
5
|
+
from .pydantic_utils import serialize_dyn_field, serialize_dyn_field__from_model
|
|
6
|
+
from .client_subclass_mapping import get_client_for_model_type, set_client_for_model_type, get_or_create_client_for_model_type
|
|
7
|
+
from .find_annotated import find_annotated_metadata_for_iterative
|
|
8
|
+
from .batching import DynBatch
|