├── .editorconfig
├── .github
├── .stale.yml
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ ├── config.yml
│ ├── feature_request.md
│ └── question.md
├── PULL_REQUEST_TEMPLATE.md
├── dependabot.yml
├── release-drafter.yml
└── workflows
│ ├── build.yml
│ ├── publish-to-pypi.yml
│ └── release-drafter.yml
├── .gitignore
├── .pre-commit-config.yaml
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
├── Makefile
├── README.md
├── SECURITY.md
├── cookiecutter-config-file.yml
├── poetry.lock
├── pyproject.toml
├── pytest_fastapi_deps
└── __init__.py
├── setup.cfg
└── tests
├── conftest.py
├── examples
├── __init__.py
└── test_public_api.py
└── test_pytest_fastapi_deps.py
/.editorconfig:
--------------------------------------------------------------------------------
1 | # Check http://editorconfig.org for more information
2 | # This is the main config file for this project:
3 | root = true
4 |
5 | [*]
6 | charset = utf-8
7 | end_of_line = lf
8 | insert_final_newline = true
9 | indent_style = space
10 | indent_size = 2
11 | trim_trailing_whitespace = true
12 |
13 | [*.{py, pyi}]
14 | indent_style = space
15 | indent_size = 4
16 |
17 | [Makefile]
18 | indent_style = tab
19 |
20 | [*.md]
21 | trim_trailing_whitespace = false
22 |
23 | [*.{diff,patch}]
24 | trim_trailing_whitespace = false
25 |
--------------------------------------------------------------------------------
/.github/.stale.yml:
--------------------------------------------------------------------------------
1 | # Number of days of inactivity before an issue becomes stale
2 | daysUntilStale: 60
3 | # Number of days of inactivity before a stale issue is closed
4 | daysUntilClose: 7
5 | # Issues with these labels will never be considered stale
6 | exemptLabels:
7 | - pinned
8 | - security
9 | # Label to use when marking an issue as stale
10 | staleLabel: wontfix
11 | # Comment to post when marking an issue as stale. Set to `false` to disable
12 | markComment: >
13 | This issue has been automatically marked as stale because it has not had
14 | recent activity. It will be closed if no further activity occurs. Thank you
15 | for your contributions.
16 | # Comment to post when closing a stale issue. Set to `false` to disable
17 | closeComment: false
18 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: 🐛 Bug report
3 | about: If something isn't working 🔧
4 | title: ''
5 | labels: bug
6 | assignees:
7 | ---
8 |
9 | ## 🐛 Bug Report
10 |
11 |
12 |
13 | ## 🔬 How To Reproduce
14 |
15 | Steps to reproduce the behavior:
16 |
17 | 1. ...
18 |
19 | ### Code sample
20 |
21 |
22 |
23 | ### Environment
24 |
25 | * OS: [e.g. Linux / Windows / macOS]
26 | * Python version, get it with:
27 |
28 | ```bash
29 | python --version
30 | ```
31 |
32 | ### Screenshots
33 |
34 |
35 |
36 | ## 📈 Expected behavior
37 |
38 |
39 |
40 | ## 📎 Additional context
41 |
42 |
43 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/config.yml:
--------------------------------------------------------------------------------
1 | # Configuration: https://help.github.com/en/github/building-a-strong-community/configuring-issue-templates-for-your-repository
2 |
3 | blank_issues_enabled: false
4 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: 🚀 Feature request
3 | about: Suggest an idea for this project 🏖
4 | title: ''
5 | labels: enhancement
6 | assignees:
7 | ---
8 |
9 | ## 🚀 Feature Request
10 |
11 |
12 |
13 | ## 🔈 Motivation
14 |
15 |
16 |
17 | ## 🛰 Alternatives
18 |
19 |
20 |
21 | ## 📎 Additional context
22 |
23 |
24 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/question.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: ❓ Question
3 | about: Ask a question about this project 🎓
4 | title: ''
5 | labels: question
6 | assignees:
7 | ---
8 |
9 | ## Checklist
10 |
11 |
12 |
13 | - [ ] I've searched the project's [`issues`](https://github.com/pksol/pytest-fastapi-deps/issues?q=is%3Aissue).
14 |
15 | ## ❓ Question
16 |
17 |
18 |
19 | How can I [...]?
20 |
21 | Is it possible to [...]?
22 |
23 | ## 📎 Additional context
24 |
25 |
26 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | ## Description
2 |
3 |
4 |
5 | ## Related Issue
6 |
7 |
8 |
9 | ## Type of Change
10 |
11 |
12 |
13 | - [ ] 📚 Examples / docs / tutorials / dependencies update
14 | - [ ] 🔧 Bug fix (non-breaking change which fixes an issue)
15 | - [ ] 🥂 Improvement (non-breaking change which improves an existing feature)
16 | - [ ] 🚀 New feature (non-breaking change which adds functionality)
17 | - [ ] 💥 Breaking change (fix or feature that would cause existing functionality to change)
18 | - [ ] 🔐 Security fix
19 |
20 | ## Checklist
21 |
22 |
23 |
24 | - [ ] I've read the [`CODE_OF_CONDUCT.md`](https://github.com/pksol/pytest-fastapi-deps/blob/master/CODE_OF_CONDUCT.md) document.
25 | - [ ] I've read the [`CONTRIBUTING.md`](https://github.com/pksol/pytest-fastapi-deps/blob/master/CONTRIBUTING.md) guide.
26 | - [ ] I've updated the code style using `make codestyle`.
27 | - [ ] I've written tests for all new methods and classes that I created.
28 | - [ ] I've written the docstring in Google format for all the methods and classes that I used.
29 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | # Configuration: https://dependabot.com/docs/config-file/
2 | # Docs: https://docs.github.com/en/github/administering-a-repository/keeping-your-dependencies-updated-automatically
3 |
4 | version: 2
5 |
6 | updates:
7 | - package-ecosystem: "pip"
8 | directory: "/"
9 | schedule:
10 | interval: "monthly"
11 | allow:
12 | - dependency-type: "all"
13 | commit-message:
14 | prefix: ":arrow_up:"
15 | open-pull-requests-limit: 50
16 |
17 | - package-ecosystem: "github-actions"
18 | directory: "/"
19 | schedule:
20 | interval: "monthly"
21 | allow:
22 | - dependency-type: "all"
23 | commit-message:
24 | prefix: ":arrow_up:"
25 | open-pull-requests-limit: 50
26 |
--------------------------------------------------------------------------------
/.github/release-drafter.yml:
--------------------------------------------------------------------------------
1 | # Release drafter configuration https://github.com/release-drafter/release-drafter#configuration
2 | # Emojis were chosen to match the https://gitmoji.carloscuesta.me/
3 |
4 | name-template: "v$NEXT_PATCH_VERSION"
5 | tag-template: "v$NEXT_PATCH_VERSION"
6 |
7 | categories:
8 | - title: ":rocket: Features"
9 | labels: [enhancement, feature]
10 | - title: ":wrench: Fixes & Refactoring"
11 | labels: [bug, refactoring, bugfix, fix]
12 | - title: ":package: Build System & CI/CD"
13 | labels: [build, ci, testing]
14 | - title: ":boom: Breaking Changes"
15 | labels: [breaking]
16 | - title: ":pencil: Documentation"
17 | labels: [documentation]
18 | - title: ":arrow_up: Dependencies updates"
19 | labels: [dependencies]
20 |
21 | template: |
22 | ## What’s Changed
23 |
24 | $CHANGES
25 |
26 | ## :busts_in_silhouette: List of contributors
27 |
28 | $CONTRIBUTORS
29 |
--------------------------------------------------------------------------------
/.github/workflows/build.yml:
--------------------------------------------------------------------------------
1 | name: build
2 |
3 | on: [push, pull_request]
4 |
5 | jobs:
6 | build:
7 | runs-on: ubuntu-latest
8 | strategy:
9 | matrix:
10 | python-version: ["3.7", "3.8", "3.9", "3.10"]
11 |
12 | steps:
13 | - uses: actions/checkout@v3
14 | - name: Set up Python ${{ matrix.python-version }}
15 | uses: actions/setup-python@v4
16 | with:
17 | python-version: ${{ matrix.python-version }}
18 |
19 | - name: Install poetry
20 | run: make poetry-download
21 |
22 | - name: Set up cache
23 | uses: actions/cache@v3.0.8
24 | with:
25 | path: .venv
26 | key: venv-${{ matrix.python-version }}-${{ hashFiles('pyproject.toml') }}-${{ hashFiles('poetry.lock') }}
27 | - name: Install dependencies
28 | run: |
29 | poetry config virtualenvs.in-project true
30 | poetry install
31 |
32 | - name: Run style checks
33 | run: |
34 | make check-codestyle
35 |
36 | - name: Run tests
37 | run: |
38 | make test
39 |
40 | - name: Run safety checks
41 | run: |
42 | make check-safety
43 |
--------------------------------------------------------------------------------
/.github/workflows/publish-to-pypi.yml:
--------------------------------------------------------------------------------
1 | name: Publish python distribution to PyPI
2 | on: push
3 |
4 | jobs:
5 | build-and-publish-test:
6 | name: Build and publish python distribution to test PyPI
7 | runs-on: ubuntu-18.04
8 | if: "!(startsWith(github.event.ref, 'refs/tags') || github.ref == 'refs/heads/main')"
9 | continue-on-error: true
10 | steps:
11 | - name: Checkout Code
12 | uses: actions/checkout@v3
13 | - name: Set up Python 3.8
14 | uses: actions/setup-python@v4
15 | with:
16 | python-version: 3.8
17 | - name: Setup pip
18 | run: python -m pip install pip==21.0.1
19 | - name: Build and publish to pypi
20 | uses: JRubics/poetry-publish@v1.10
21 | with:
22 | python_version: '3.8.10'
23 | poetry_version: "==1.1.4"
24 | repository_name: 'pytest_fastapi_deps'
25 | repository_url: 'https://test.pypi.org/legacy/'
26 | pypi_token: ${{ secrets.test_pypi_password }}
27 | continue-on-error: true
28 | - name: Sleep to allow pypi index to update with the new version
29 | run: sleep 5m
30 | - name: Install poetry
31 | run: make poetry-download
32 | - name: Cleanup
33 | run: |
34 | rm -r pytest_fastapi_deps
35 | pip uninstall pytest-fastapi-deps
36 | - name: Perform System tests
37 | run: |
38 | poetry export --dev --without-hashes -f requirements.txt --output test-requirements.txt
39 | pip install -r test-requirements.txt
40 | pip install -i https://test.pypi.org/simple/ pytest-fastapi-deps
41 | python -m pytest -vvv -k "test_public_api"
42 | export INSTALLED=`pip freeze | grep pytest-fastapi-deps`
43 | echo "installed is: $INSTALLED, and we care about ${INSTALLED:21}"
44 | export EXPECTED=`poetry version --short`
45 | echo "expected is: $EXPECTED"
46 | if [ "${INSTALLED:21}" != "$EXPECTED" ]; then exit 1; fi
47 |
48 | build-and-publish-production:
49 | name: Build and publish python distribution to production PyPI
50 | runs-on: ubuntu-18.04
51 | if: startsWith(github.event.ref, 'refs/tags')
52 | steps:
53 | - name: Checkout Code
54 | uses: actions/checkout@v3
55 | - name: Set up Python 3.8
56 | uses: actions/setup-python@v4
57 | with:
58 | python-version: 3.8
59 | - name: Setup pip
60 | run: python -m pip install pip==21.0.1
61 | - name: Build and publish to pypi
62 | uses: JRubics/poetry-publish@v1.10
63 | with:
64 | python_version: '3.8.10'
65 | poetry_version: "==1.1.4"
66 | repository_name: 'pytest_fastapi_deps'
67 | pypi_token: ${{ secrets.prod_pypi_password }}
68 | continue-on-error: true
69 | - name: Sleep to allow pypi index to update with the new version
70 | run: sleep 5m
71 | - name: Install poetry
72 | run: make poetry-download
73 | - name: Cleanup
74 | run: |
75 | rm -r pytest_fastapi_deps
76 | pip uninstall pytest-fastapi-deps
77 | - name: Perform System tests
78 | run: |
79 | poetry export --dev --without-hashes -f requirements.txt --output test-requirements.txt
80 | pip install -r test-requirements.txt
81 | pip install pytest-fastapi-deps
82 | python -m pytest -vvv -k "test_public_api"
83 | export INSTALLED=`pip freeze | grep pytest-fastapi-deps`
84 | echo "installed is: $INSTALLED, and we care about ${INSTALLED:21}"
85 | export EXPECTED=`poetry version --short`
86 | echo "expected is: $EXPECTED"
87 | if [ "${INSTALLED:21}" != "$EXPECTED" ]; then exit 1; fi
88 |
--------------------------------------------------------------------------------
/.github/workflows/release-drafter.yml:
--------------------------------------------------------------------------------
1 | name: Release Drafter
2 |
3 | on:
4 | push:
5 | # branches to consider in the event; optional, defaults to all
6 | branches:
7 | - main
8 |
9 | jobs:
10 | update_release_draft:
11 | runs-on: ubuntu-latest
12 | steps:
13 | # Drafts your next Release notes as Pull Requests are merged into "master"
14 | - uses: release-drafter/release-drafter@v5.20.1
15 | env:
16 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
17 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | # Created by https://www.gitignore.io/api/osx,python,pycharm,windows,visualstudio,visualstudiocode
3 | # Edit at https://www.gitignore.io/?templates=osx,python,pycharm,windows,visualstudio,visualstudiocode
4 |
5 | ### OSX ###
6 | # General
7 | .DS_Store
8 | .AppleDouble
9 | .LSOverride
10 |
11 | # Icon must end with two \r
12 | Icon
13 |
14 | # Thumbnails
15 | ._*
16 |
17 | # Files that might appear in the root of a volume
18 | .DocumentRevisions-V100
19 | .fseventsd
20 | .Spotlight-V100
21 | .TemporaryItems
22 | .Trashes
23 | .VolumeIcon.icns
24 | .com.apple.timemachine.donotpresent
25 |
26 | # Directories potentially created on remote AFP share
27 | .AppleDB
28 | .AppleDesktop
29 | Network Trash Folder
30 | Temporary Items
31 | .apdisk
32 |
33 | ### PyCharm ###
34 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
35 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
36 |
37 | # Pycharm
38 | .idea/
39 |
40 | # User-specific stuff
41 | .idea/**/workspace.xml
42 | .idea/**/tasks.xml
43 | .idea/**/usage.statistics.xml
44 | .idea/**/dictionaries
45 | .idea/**/shelf
46 |
47 | # Generated files
48 | .idea/**/contentModel.xml
49 |
50 | # Sensitive or high-churn files
51 | .idea/**/dataSources/
52 | .idea/**/dataSources.ids
53 | .idea/**/dataSources.local.xml
54 | .idea/**/sqlDataSources.xml
55 | .idea/**/dynamic.xml
56 | .idea/**/uiDesigner.xml
57 | .idea/**/dbnavigator.xml
58 |
59 | # Gradle
60 | .idea/**/gradle.xml
61 | .idea/**/libraries
62 |
63 | # Gradle and Maven with auto-import
64 | # When using Gradle or Maven with auto-import, you should exclude module files,
65 | # since they will be recreated, and may cause churn. Uncomment if using
66 | # auto-import.
67 | # .idea/modules.xml
68 | # .idea/*.iml
69 | # .idea/modules
70 | # *.iml
71 | # *.ipr
72 |
73 | # CMake
74 | cmake-build-*/
75 |
76 | # Mongo Explorer plugin
77 | .idea/**/mongoSettings.xml
78 |
79 | # File-based project format
80 | *.iws
81 |
82 | # IntelliJ
83 | out/
84 |
85 | # mpeltonen/sbt-idea plugin
86 | .idea_modules/
87 |
88 | # JIRA plugin
89 | atlassian-ide-plugin.xml
90 |
91 | # Cursive Clojure plugin
92 | .idea/replstate.xml
93 |
94 | # Crashlytics plugin (for Android Studio and IntelliJ)
95 | com_crashlytics_export_strings.xml
96 | crashlytics.properties
97 | crashlytics-build.properties
98 | fabric.properties
99 |
100 | # Editor-based Rest Client
101 | .idea/httpRequests
102 |
103 | # Android studio 3.1+ serialized cache file
104 | .idea/caches/build_file_checksums.ser
105 |
106 | ### PyCharm Patch ###
107 | # Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
108 |
109 | # *.iml
110 | # modules.xml
111 | # .idea/misc.xml
112 | # *.ipr
113 |
114 | # Sonarlint plugin
115 | .idea/**/sonarlint/
116 |
117 | # SonarQube Plugin
118 | .idea/**/sonarIssues.xml
119 |
120 | # Markdown Navigator plugin
121 | .idea/**/markdown-navigator.xml
122 | .idea/**/markdown-navigator/
123 |
124 | ### Python ###
125 | # Byte-compiled / optimized / DLL files
126 | __pycache__/
127 | *.py[cod]
128 | *$py.class
129 | requirements.txt
130 |
131 | # C extensions
132 | *.so
133 |
134 | # Distribution / packaging
135 | .Python
136 | build/
137 | develop-eggs/
138 | dist/
139 | downloads/
140 | eggs/
141 | .eggs/
142 | lib/
143 | lib64/
144 | parts/
145 | sdist/
146 | var/
147 | wheels/
148 | pip-wheel-metadata/
149 | share/python-wheels/
150 | *.egg-info/
151 | .installed.cfg
152 | *.egg
153 | MANIFEST
154 |
155 | # PyInstaller
156 | # Usually these files are written by a python script from a template
157 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
158 | *.manifest
159 | *.spec
160 |
161 | # Installer logs
162 | pip-log.txt
163 | pip-delete-this-directory.txt
164 |
165 | # Unit test / coverage reports
166 | htmlcov/
167 | .tox/
168 | .nox/
169 | .coverage
170 | .coverage.*
171 | .cache
172 | nosetests.xml
173 | coverage.xml
174 | *.cover
175 | .hypothesis/
176 | .pytest_cache/
177 |
178 | # Translations
179 | *.mo
180 | *.pot
181 |
182 | # Scrapy stuff:
183 | .scrapy
184 |
185 | # Sphinx documentation
186 | docs/_build/
187 |
188 | # PyBuilder
189 | target/
190 |
191 | # pyenv
192 | .python-version
193 |
194 | # poetry
195 | .venv
196 |
197 | # pipenv
198 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
199 | # However, in case of collaboration, if having platform-specific dependencies or dependencies
200 | # having no cross-platform support, pipenv may install dependencies that don't work, or not
201 | # install all needed dependencies.
202 | #Pipfile.lock
203 |
204 | # celery beat schedule file
205 | celerybeat-schedule
206 |
207 | # SageMath parsed files
208 | *.sage.py
209 |
210 | # Spyder project settings
211 | .spyderproject
212 | .spyproject
213 |
214 | # Rope project settings
215 | .ropeproject
216 |
217 | # Mr Developer
218 | .mr.developer.cfg
219 | .project
220 | .pydevproject
221 |
222 | # mkdocs documentation
223 | /site
224 |
225 | # mypy
226 | .mypy_cache/
227 | .dmypy.json
228 | dmypy.json
229 |
230 | # Pyre type checker
231 | .pyre/
232 |
233 | # Plugins
234 | .secrets.baseline
235 |
236 | ### VisualStudioCode ###
237 | .vscode/*
238 | !.vscode/tasks.json
239 | !.vscode/launch.json
240 | !.vscode/extensions.json
241 |
242 | ### VisualStudioCode Patch ###
243 | # Ignore all local history of files
244 | .history
245 |
246 | ### Windows ###
247 | # Windows thumbnail cache files
248 | Thumbs.db
249 | Thumbs.db:encryptable
250 | ehthumbs.db
251 | ehthumbs_vista.db
252 |
253 | # Dump file
254 | *.stackdump
255 |
256 | # Folder config file
257 | [Dd]esktop.ini
258 |
259 | # Recycle Bin used on file shares
260 | $RECYCLE.BIN/
261 |
262 | # Windows Installer files
263 | *.cab
264 | *.msi
265 | *.msix
266 | *.msm
267 | *.msp
268 |
269 | # Windows shortcuts
270 | *.lnk
271 |
272 | ### VisualStudio ###
273 | ## Ignore Visual Studio temporary files, build results, and
274 | ## files generated by popular Visual Studio add-ons.
275 | ##
276 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
277 |
278 | # User-specific files
279 | *.rsuser
280 | *.suo
281 | *.user
282 | *.userosscache
283 | *.sln.docstates
284 |
285 | # User-specific files (MonoDevelop/Xamarin Studio)
286 | *.userprefs
287 |
288 | # Mono auto generated files
289 | mono_crash.*
290 |
291 | # Build results
292 | [Dd]ebug/
293 | [Dd]ebugPublic/
294 | [Rr]elease/
295 | [Rr]eleases/
296 | x64/
297 | x86/
298 | [Aa][Rr][Mm]/
299 | [Aa][Rr][Mm]64/
300 | bld/
301 | [Bb]in/
302 | [Oo]bj/
303 | [Ll]og/
304 |
305 | # Visual Studio 2015/2017 cache/options directory
306 | .vs/
307 | # Uncomment if you have tasks that create the project's static files in wwwroot
308 | #wwwroot/
309 |
310 | # Visual Studio 2017 auto generated files
311 | Generated\ Files/
312 |
313 | # MSTest test Results
314 | [Tt]est[Rr]esult*/
315 | [Bb]uild[Ll]og.*
316 |
317 | # NUnit
318 | *.VisualState.xml
319 | TestResult.xml
320 | nunit-*.xml
321 |
322 | # Build Results of an ATL Project
323 | [Dd]ebugPS/
324 | [Rr]eleasePS/
325 | dlldata.c
326 |
327 | # Benchmark Results
328 | BenchmarkDotNet.Artifacts/
329 |
330 | # .NET Core
331 | project.lock.json
332 | project.fragment.lock.json
333 | artifacts/
334 |
335 | # StyleCop
336 | StyleCopReport.xml
337 |
338 | # Files built by Visual Studio
339 | *_i.c
340 | *_p.c
341 | *_h.h
342 | *.ilk
343 | *.obj
344 | *.iobj
345 | *.pch
346 | *.pdb
347 | *.ipdb
348 | *.pgc
349 | *.pgd
350 | *.rsp
351 | *.sbr
352 | *.tlb
353 | *.tli
354 | *.tlh
355 | *.tmp
356 | *.tmp_proj
357 | *_wpftmp.csproj
358 | *.log
359 | *.vspscc
360 | *.vssscc
361 | .builds
362 | *.pidb
363 | *.svclog
364 | *.scc
365 |
366 | # Chutzpah Test files
367 | _Chutzpah*
368 |
369 | # Visual C++ cache files
370 | ipch/
371 | *.aps
372 | *.ncb
373 | *.opendb
374 | *.opensdf
375 | *.sdf
376 | *.cachefile
377 | *.VC.db
378 | *.VC.VC.opendb
379 |
380 | # Visual Studio profiler
381 | *.psess
382 | *.vsp
383 | *.vspx
384 | *.sap
385 |
386 | # Visual Studio Trace Files
387 | *.e2e
388 |
389 | # TFS 2012 Local Workspace
390 | $tf/
391 |
392 | # Guidance Automation Toolkit
393 | *.gpState
394 |
395 | # ReSharper is a .NET coding add-in
396 | _ReSharper*/
397 | *.[Rr]e[Ss]harper
398 | *.DotSettings.user
399 |
400 | # JustCode is a .NET coding add-in
401 | .JustCode
402 |
403 | # TeamCity is a build add-in
404 | _TeamCity*
405 |
406 | # DotCover is a Code Coverage Tool
407 | *.dotCover
408 |
409 | # AxoCover is a Code Coverage Tool
410 | .axoCover/*
411 | !.axoCover/settings.json
412 |
413 | # Visual Studio code coverage results
414 | *.coverage
415 | *.coveragexml
416 |
417 | # NCrunch
418 | _NCrunch_*
419 | .*crunch*.local.xml
420 | nCrunchTemp_*
421 |
422 | # MightyMoose
423 | *.mm.*
424 | AutoTest.Net/
425 |
426 | # Web workbench (sass)
427 | .sass-cache/
428 |
429 | # Installshield output folder
430 | [Ee]xpress/
431 |
432 | # DocProject is a documentation generator add-in
433 | DocProject/buildhelp/
434 | DocProject/Help/*.HxT
435 | DocProject/Help/*.HxC
436 | DocProject/Help/*.hhc
437 | DocProject/Help/*.hhk
438 | DocProject/Help/*.hhp
439 | DocProject/Help/Html2
440 | DocProject/Help/html
441 |
442 | # Click-Once directory
443 | publish/
444 |
445 | # Publish Web Output
446 | *.[Pp]ublish.xml
447 | *.azurePubxml
448 | # Note: Comment the next line if you want to checkin your web deploy settings,
449 | # but database connection strings (with potential passwords) will be unencrypted
450 | *.pubxml
451 | *.publishproj
452 |
453 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
454 | # checkin your Azure Web App publish settings, but sensitive information contained
455 | # in these scripts will be unencrypted
456 | PublishScripts/
457 |
458 | # NuGet Packages
459 | *.nupkg
460 | # NuGet Symbol Packages
461 | *.snupkg
462 | # The packages folder can be ignored because of Package Restore
463 | **/[Pp]ackages/*
464 | # except build/, which is used as an MSBuild target.
465 | !**/[Pp]ackages/build/
466 | # Uncomment if necessary however generally it will be regenerated when needed
467 | #!**/[Pp]ackages/repositories.config
468 | # NuGet v3's project.json files produces more ignorable files
469 | *.nuget.props
470 | *.nuget.targets
471 |
472 | # Microsoft Azure Build Output
473 | csx/
474 | *.build.csdef
475 |
476 | # Microsoft Azure Emulator
477 | ecf/
478 | rcf/
479 |
480 | # Windows Store app package directories and files
481 | AppPackages/
482 | BundleArtifacts/
483 | Package.StoreAssociation.xml
484 | _pkginfo.txt
485 | *.appx
486 | *.appxbundle
487 | *.appxupload
488 |
489 | # Visual Studio cache files
490 | # files ending in .cache can be ignored
491 | *.[Cc]ache
492 | # but keep track of directories ending in .cache
493 | !?*.[Cc]ache/
494 |
495 | # Others
496 | ClientBin/
497 | ~$*
498 | *~
499 | *.dbmdl
500 | *.dbproj.schemaview
501 | *.jfm
502 | *.pfx
503 | *.publishsettings
504 | orleans.codegen.cs
505 |
506 | # Including strong name files can present a security risk
507 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
508 | #*.snk
509 |
510 | # Since there are multiple workflows, uncomment next line to ignore bower_components
511 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
512 | #bower_components/
513 |
514 | # RIA/Silverlight projects
515 | Generated_Code/
516 |
517 | # Backup & report files from converting an old project file
518 | # to a newer Visual Studio version. Backup files are not needed,
519 | # because we have git ;-)
520 | _UpgradeReport_Files/
521 | Backup*/
522 | UpgradeLog*.XML
523 | UpgradeLog*.htm
524 | ServiceFabricBackup/
525 | *.rptproj.bak
526 |
527 | # SQL Server files
528 | *.mdf
529 | *.ldf
530 | *.ndf
531 |
532 | # Business Intelligence projects
533 | *.rdl.data
534 | *.bim.layout
535 | *.bim_*.settings
536 | *.rptproj.rsuser
537 | *- [Bb]ackup.rdl
538 | *- [Bb]ackup ([0-9]).rdl
539 | *- [Bb]ackup ([0-9][0-9]).rdl
540 |
541 | # Microsoft Fakes
542 | FakesAssemblies/
543 |
544 | # GhostDoc plugin setting file
545 | *.GhostDoc.xml
546 |
547 | # Node.js Tools for Visual Studio
548 | .ntvs_analysis.dat
549 | node_modules/
550 |
551 | # Visual Studio 6 build log
552 | *.plg
553 |
554 | # Visual Studio 6 workspace options file
555 | *.opt
556 |
557 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
558 | *.vbw
559 |
560 | # Visual Studio LightSwitch build output
561 | **/*.HTMLClient/GeneratedArtifacts
562 | **/*.DesktopClient/GeneratedArtifacts
563 | **/*.DesktopClient/ModelManifest.xml
564 | **/*.Server/GeneratedArtifacts
565 | **/*.Server/ModelManifest.xml
566 | _Pvt_Extensions
567 |
568 | # Paket dependency manager
569 | .paket/paket.exe
570 | paket-files/
571 |
572 | # FAKE - F# Make
573 | .fake/
574 |
575 | # CodeRush personal settings
576 | .cr/personal
577 |
578 | # Python Tools for Visual Studio (PTVS)
579 | *.pyc
580 |
581 | # Cake - Uncomment if you are using it
582 | # tools/**
583 | # !tools/packages.config
584 |
585 | # Tabs Studio
586 | *.tss
587 |
588 | # Telerik's JustMock configuration file
589 | *.jmconfig
590 |
591 | # BizTalk build output
592 | *.btp.cs
593 | *.btm.cs
594 | *.odx.cs
595 | *.xsd.cs
596 |
597 | # OpenCover UI analysis results
598 | OpenCover/
599 |
600 | # Azure Stream Analytics local run output
601 | ASALocalRun/
602 |
603 | # MSBuild Binary and Structured Log
604 | *.binlog
605 |
606 | # NVidia Nsight GPU debugger configuration file
607 | *.nvuser
608 |
609 | # MFractors (Xamarin productivity tool) working folder
610 | .mfractor/
611 |
612 | # Local History for Visual Studio
613 | .localhistory/
614 |
615 | # BeatPulse healthcheck temp database
616 | healthchecksdb
617 |
618 | # Backup folder for Package Reference Convert tool in Visual Studio 2017
619 | MigrationBackup/
620 |
621 | # End of https://www.gitignore.io/api/osx,python,pycharm,windows,visualstudio,visualstudiocode
622 |
--------------------------------------------------------------------------------
/.pre-commit-config.yaml:
--------------------------------------------------------------------------------
1 | default_language_version:
2 | python: python3.7
3 |
4 | default_stages: [commit, push]
5 |
6 | repos:
7 | - repo: https://github.com/pre-commit/pre-commit-hooks
8 | rev: v2.5.0
9 | hooks:
10 | - id: check-yaml
11 | - id: end-of-file-fixer
12 | exclude: LICENSE
13 |
14 | - repo: local
15 | hooks:
16 | - id: pyupgrade
17 | name: pyupgrade
18 | entry: poetry run pyupgrade --py37-plus
19 | types: [python]
20 | language: system
21 |
22 | - repo: local
23 | hooks:
24 | - id: isort
25 | name: isort
26 | entry: poetry run isort --settings-path pyproject.toml
27 | types: [python]
28 | language: system
29 |
30 | - repo: local
31 | hooks:
32 | - id: black
33 | name: black
34 | entry: poetry run black --config pyproject.toml
35 | types: [python]
36 | language: system
37 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | In the interest of fostering an open and welcoming environment, we as
6 | contributors and maintainers pledge to making participation in our project and
7 | our community a harassment-free experience for everyone, regardless of age, body
8 | size, disability, ethnicity, sex characteristics, gender identity and expression,
9 | level of experience, education, socio-economic status, nationality, personal
10 | appearance, race, religion, or sexual identity and orientation.
11 |
12 | ## Our Standards
13 |
14 | Examples of behavior that contributes to creating a positive environment
15 | include:
16 |
17 | * Using welcoming and inclusive language
18 | * Being respectful of differing viewpoints and experiences
19 | * Gracefully accepting constructive criticism
20 | * Focusing on what is best for the community
21 | * Showing empathy towards other community members
22 |
23 | Examples of unacceptable behavior by participants include:
24 |
25 | * The use of sexualized language or imagery and unwelcome sexual attention or
26 | advances
27 | * Trolling, insulting/derogatory comments, and personal or political attacks
28 | * Public or private harassment
29 | * Publishing others' private information, such as a physical or electronic
30 | address, without explicit permission
31 | * Other conduct which could reasonably be considered inappropriate in a
32 | professional setting
33 |
34 | ## Our Responsibilities
35 |
36 | Project maintainers are responsible for clarifying the standards of acceptable
37 | behavior and are expected to take appropriate and fair corrective action in
38 | response to any instances of unacceptable behavior.
39 |
40 | Project maintainers have the right and responsibility to remove, edit, or
41 | reject comments, commits, code, wiki edits, issues, and other contributions
42 | that are not aligned to this Code of Conduct, or to ban temporarily or
43 | permanently any contributor for other behaviors that they deem inappropriate,
44 | threatening, offensive, or harmful.
45 |
46 | ## Scope
47 |
48 | This Code of Conduct applies both within project spaces and in public spaces
49 | when an individual is representing the project or its community. Examples of
50 | representing a project or community include using an official project e-mail
51 | address, posting via an official social media account, or acting as an appointed
52 | representative at an online or offline event. Representation of a project may be
53 | further defined and clarified by project maintainers.
54 |
55 | ## Enforcement
56 |
57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
58 | reported by contacting the project team at kogan.peter@gmail.com. All
59 | complaints will be reviewed and investigated and will result in a response that
60 | is deemed necessary and appropriate to the circumstances. The project team is
61 | obligated to maintain confidentiality with regard to the reporter of an incident.
62 | Further details of specific enforcement policies may be posted separately.
63 |
64 | Project maintainers who do not follow or enforce the Code of Conduct in good
65 | faith may face temporary or permanent repercussions as determined by other
66 | members of the project's leadership.
67 |
68 | ## Attribution
69 |
70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
72 |
73 | [homepage]: https://www.contributor-covenant.org
74 |
75 | For answers to common questions about this code of conduct, see
76 | https://www.contributor-covenant.org/faq
77 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # How to contribute
2 |
3 | ## Dependencies
4 |
5 | We use `poetry` to manage the [dependencies](https://github.com/python-poetry/poetry).
6 | If you don't have `poetry`, you should install with `make poetry-download`.
7 |
8 | To install dependencies and prepare [`pre-commit`](https://pre-commit.com/) hooks you would need to run `install` command:
9 |
10 | ```bash
11 | make install
12 | make pre-commit-install
13 | ```
14 |
15 | To activate your `virtualenv` run `poetry shell`.
16 |
17 | ## Codestyle
18 |
19 | After installation you may execute code formatting.
20 |
21 | ```bash
22 | make codestyle
23 | ```
24 |
25 | ### Checks
26 |
27 | Many checks are configured for this project. Command `make check-codestyle` will check black, isort and darglint.
28 | The `make check-safety` command will look at the security of your code.
29 |
30 | Command `make lint` applies all checks.
31 |
32 | ### Before submitting
33 |
34 | Before submitting your code please do the following steps:
35 |
36 | 1. Add any changes you want
37 | 1. Add tests for the new changes
38 | 1. Edit documentation if you have changed something significant
39 | 1. Run `make codestyle` to format your changes.
40 | 1. Run `make lint` to ensure that types, security and docstrings are okay.
41 |
42 |
43 |
44 | ### Makefile usage
45 |
46 | [`Makefile`](https://github.com/pksol/pytest-fastapi-deps/blob/master/Makefile) contains a lot of functions for faster development.
47 |
48 |
49 | 1. Download and remove Poetry
50 |
51 |
52 | To download and install Poetry run:
53 |
54 | ```bash
55 | make poetry-download
56 | ```
57 |
58 | To uninstall
59 |
60 | ```bash
61 | make poetry-remove
62 | ```
63 |
64 |
65 |
66 |
67 |
68 | 2. Install all dependencies and pre-commit hooks
69 |
70 |
71 | Install requirements:
72 |
73 | ```bash
74 | make install
75 | ```
76 |
77 | Pre-commit hooks could be installed after `git init` via
78 |
79 | ```bash
80 | make pre-commit-install
81 | ```
82 |
83 |
84 |
85 |
86 |
87 | 3. Codestyle
88 |
89 |
90 | Automatic formatting uses `pyupgrade`, `isort` and `black`.
91 |
92 | ```bash
93 | make codestyle
94 |
95 | # or use synonym
96 | make formatting
97 | ```
98 |
99 | Codestyle checks only, without rewriting files:
100 |
101 | ```bash
102 | make check-codestyle
103 | ```
104 |
105 | > Note: `check-codestyle` uses `isort`, `black` and `darglint` library
106 |
107 | Update all dev libraries to the latest version using one command
108 |
109 | ```bash
110 | make update-dev-deps
111 | ```
112 |
113 |
114 |
115 |
116 |
117 | 4. Code security
118 |
119 |
120 | ```bash
121 | make check-safety
122 | ```
123 |
124 | This command launches `Poetry` integrity checks as well as identifies security issues with `Safety` and `Bandit`.
125 |
126 | ```bash
127 | make check-safety
128 | ```
129 |
130 |
131 |
132 |
133 |
134 | 5. Type checks
135 |
136 |
137 | Run `mypy` static type checker
138 |
139 | ```bash
140 | make mypy
141 | ```
142 |
143 |
144 |
145 |
146 |
147 | 6. Tests with coverage badges
148 |
149 |
150 | Run `pytest`
151 |
152 | ```bash
153 | make test
154 | ```
155 |
156 |
157 |
158 |
159 |
160 | 7. All linters
161 |
162 |
163 | Of course there is a command to ~~rule~~ run all linters in one:
164 |
165 | ```bash
166 | make lint
167 | ```
168 |
169 | the same as:
170 |
171 | ```bash
172 | make test && make check-codestyle && make mypy && make check-safety
173 | ```
174 |
175 |
176 |
177 |
178 |
179 | 8. Cleanup
180 |
181 | Delete pycache files
182 |
183 | ```bash
184 | make pycache-remove
185 | ```
186 |
187 | Remove package build
188 |
189 | ```bash
190 | make build-remove
191 | ```
192 |
193 | Delete .DS_STORE files
194 |
195 | ```bash
196 | make dsstore-remove
197 | ```
198 |
199 | Remove .mypycache
200 |
201 | ```bash
202 | make mypycache-remove
203 | ```
204 |
205 | Or to remove all above run:
206 |
207 | ```bash
208 | make cleanup
209 | ```
210 |
211 |
212 |
213 |
214 | ## Other help
215 |
216 | You can contribute by spreading a word about this library.
217 | It would also be a huge contribution to write
218 | a short article on how you are using this project.
219 | You can also share your best practices with us.
220 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 | Copyright (c) 2022 Peter Kogan
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining a copy
5 | of this software and associated documentation files (the "Software"), to deal
6 | in the Software without restriction, including without limitation the rights
7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | copies of the Software, and to permit persons to whom the Software is
9 | furnished to do so, subject to the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be included in all
12 | copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 | OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
20 | OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | #* Variables
2 | SHELL := /usr/bin/env bash
3 | PYTHON := python
4 | PYTHONPATH := `pwd`
5 |
6 | #* Poetry
7 | .PHONY: poetry-download
8 | poetry-download:
9 | curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/install-poetry.py | $(PYTHON) -
10 |
11 | .PHONY: poetry-remove
12 | poetry-remove:
13 | curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/install-poetry.py | $(PYTHON) - --uninstall
14 |
15 | #* Installation
16 | .PHONY: install
17 | install:
18 | poetry lock -n && poetry export --without-hashes > requirements.txt
19 | poetry install -n
20 | -poetry run mypy --install-types --non-interactive ./
21 |
22 | .PHONY: pre-commit-install
23 | pre-commit-install:
24 | poetry run pre-commit install
25 |
26 | #* Formatters
27 | .PHONY: codestyle
28 | codestyle:
29 | poetry run pyupgrade --exit-zero-even-if-changed --py37-plus **/*.py
30 | poetry run isort --settings-path pyproject.toml ./
31 | poetry run black --config pyproject.toml ./
32 |
33 | .PHONY: formatting
34 | formatting: codestyle
35 |
36 | #* Linting
37 | .PHONY: test
38 | test:
39 | PYTHONPATH=$(PYTHONPATH) poetry run pytest
40 |
41 | .PHONY: check-codestyle
42 | check-codestyle:
43 | poetry run isort --diff --check-only --settings-path pyproject.toml ./
44 | poetry run black --diff --check --config pyproject.toml ./
45 | poetry run darglint --verbosity 2 pytest_fastapi_deps tests
46 |
47 | .PHONY: mypy
48 | mypy:
49 | poetry run mypy --config-file pyproject.toml ./
50 |
51 | .PHONY: check-safety
52 | check-safety:
53 | poetry check
54 | poetry run safety check --full-report
55 | poetry run bandit -ll --recursive pytest_fastapi_deps tests
56 |
57 | .PHONY: lint
58 | lint: test check-codestyle mypy check-safety
59 |
60 | .PHONY: update-dev-deps
61 | update-dev-deps:
62 | poetry add -D bandit@latest darglint@latest "isort[colors]@latest" mypy@latest pre-commit@latest pydocstyle@latest pylint@latest pytest@latest pyupgrade@latest safety@latest coverage@latest coverage-badge@latest pytest-html@latest pytest-cov@latest
63 | poetry add -D --allow-prereleases black@latest
64 |
65 | #* Cleaning
66 | .PHONY: pycache-remove
67 | pycache-remove:
68 | find . | grep -E "(__pycache__|\.pyc|\.pyo$$)" | xargs rm -rf
69 |
70 | .PHONY: dsstore-remove
71 | dsstore-remove:
72 | find . | grep -E ".DS_Store" | xargs rm -rf
73 |
74 | .PHONY: mypycache-remove
75 | mypycache-remove:
76 | find . | grep -E ".mypy_cache" | xargs rm -rf
77 |
78 | .PHONY: ipynbcheckpoints-remove
79 | ipynbcheckpoints-remove:
80 | find . | grep -E ".ipynb_checkpoints" | xargs rm -rf
81 |
82 | .PHONY: pytestcache-remove
83 | pytestcache-remove:
84 | find . | grep -E ".pytest_cache" | xargs rm -rf
85 |
86 | .PHONY: build-remove
87 | build-remove:
88 | rm -rf build/
89 |
90 | .PHONY: cleanup
91 | cleanup: pycache-remove dsstore-remove mypycache-remove ipynbcheckpoints-remove pytestcache-remove
92 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # pytest-fastapi-deps
2 |
3 |
4 |
5 | [](https://github.com/pksol/pytest-fastapi-deps/actions?query=workflow%3Abuild)
6 | [](https://pypi.org/project/pytest-fastapi-deps/)
7 | [](https://github.com/pksol/pytest-fastapi-deps/pulls?utf8=%E2%9C%93&q=is%3Apr%20author%3Aapp%2Fdependabot)
8 |
9 | [](https://github.com/psf/black)
10 | [](https://github.com/PyCQA/bandit)
11 | [](https://github.com/pksol/pytest-fastapi-deps/blob/master/.pre-commit-config.yaml)
12 | [](https://github.com/pksol/pytest-fastapi-deps/releases)
13 | [](https://github.com/pksol/pytest-fastapi-deps/blob/master/LICENSE)
14 |
15 | A fixture which allows easy replacement of fastapi dependencies for testing
16 |
17 |
18 |
19 | ## Installation
20 |
21 | ```bash
22 | pip install pytest-fastapi-deps
23 | ```
24 |
25 | or install with `Poetry`
26 |
27 | ```bash
28 | poetry add pytest-fastapi-deps
29 | ```
30 |
31 | ## Use case
32 | Suppose that you have this fastapi endpoint which has a couple of dependencies:
33 | ```python
34 | from fastapi import Depends, FastAPI
35 |
36 | app = FastAPI()
37 |
38 |
39 | async def first_dep():
40 | return {"skip": 0, "limit": 100}
41 |
42 |
43 | def second_dep():
44 | return {"skip": 20, "limit": 50}
45 |
46 |
47 | @app.get("/depends/")
48 | async def get_depends(
49 | first_dep: dict = Depends(first_dep), second_dep: dict = Depends(second_dep)
50 | ):
51 | return {"first_dep": first_dep, "second_dep": second_dep}
52 | ```
53 |
54 | For simplicity, this example holds static dictionaries, but in reality these
55 | dependencies can be anything: dynamic configuration, database information, the
56 | current user's information, etc.
57 |
58 | If you want to test your fastapi endpoint you might wish to mock or replace these
59 | dependencies with your test code.
60 |
61 | This is where the `fastapi_dep` fixture comes to play.
62 |
63 | ## Usage
64 | The most basic usage is to replace a dependency with a context manager:
65 |
66 | ```python
67 | from my_project.main import app, first_dep, second_dep
68 | from fastapi.testclient import TestClient
69 |
70 | client = TestClient(app)
71 |
72 | def my_second_override():
73 | return {"another": "override"}
74 |
75 |
76 | def test_get_override_two_dep(fastapi_dep):
77 | with fastapi_dep(app).override(
78 | {
79 | first_dep: "plain_override_object",
80 | second_dep: my_second_override,
81 | }
82 | ):
83 | response = client.get("/depends")
84 | assert response.status_code == 200
85 | assert response.json() == {
86 | "first_dep": "plain_override_object",
87 | "second_dep": {"another": "override"},
88 | }
89 | ```
90 |
91 | Note how easy it is: you add the `fastapi_dep` fixture, initialize it with the fastapi
92 | `app` and send a dictionary of overrides: the keys are the original functions while the
93 | values are plain objects that would be returned or replacement functions that would be
94 | called.
95 |
96 | If your use case is to replace the dependencies for the entire duration of your test,
97 | you can use pytest [indirect parameters](https://docs.pytest.org/en/latest/example/parametrize.html#indirect-parametrization) to simplify the body of your test:
98 |
99 | ```python
100 | import pytest
101 |
102 | from my_project.main import app, first_dep, second_dep
103 | from fastapi.testclient import TestClient
104 |
105 | client = TestClient(app)
106 |
107 | @pytest.mark.parametrize(
108 | "fastapi_dep",
109 | [
110 | (
111 | app,
112 | {first_dep: lambda: {"my": "override"}},
113 | )
114 | ],
115 | indirect=True,
116 | )
117 | def test_get_override_indirect_dep_param(fastapi_dep):
118 | response = client.get("/depends")
119 | assert response.status_code == 200
120 | assert response.json() == {
121 | "first_dep": {"my": "override"},
122 | "second_dep": {"skip": 20, "limit": 50},
123 | }
124 | ```
125 | You must use `indirect=True` and pass a tuple where the first item is the `app` and the
126 | second item is the dictionary with replacement functions.
127 |
128 | You can do more fancy stuff and utilize the nature of nested python context managers:
129 |
130 | ```python
131 | from my_project.main import app, first_dep, second_dep
132 | from fastapi.testclient import TestClient
133 |
134 | client = TestClient(app)
135 |
136 |
137 | def test_get_override_dep_inner_context(fastapi_dep):
138 | with fastapi_dep(app).override({first_dep: lambda: {"my": "override"}}):
139 | response = client.get("/depends")
140 | assert response.status_code == 200
141 | assert response.json() == {
142 | "first_dep": {"my": "override"}, # overridden
143 | "second_dep": {"skip": 20, "limit": 50}, # stayed the same
144 | }
145 |
146 | # add another override
147 | with fastapi_dep(app).override({second_dep: lambda: {"another": "override"}}):
148 | response = client.get("/depends")
149 | assert response.status_code == 200
150 | assert response.json() == {
151 | "first_dep": {"my": "override"}, # overridden
152 | "second_dep": {"another": "override"}, # overridden
153 | }
154 |
155 | # second override is gone - expect that only the first is overridden
156 | response = client.get("/depends")
157 | assert response.status_code == 200
158 | assert response.json() == {
159 | "first_dep": {"my": "override"}, # overridden
160 | "second_dep": {"skip": 20, "limit": 50}, # returned to normal behaviour
161 | }
162 |
163 | # back to normal behaviour
164 | response = client.get("/depends")
165 | assert response.status_code == 200
166 | assert response.json() == {
167 | "first_dep": {"skip": 0, "limit": 100},
168 | "second_dep": {"skip": 20, "limit": 50},
169 | }
170 | ```
171 |
172 | ## 📈 Releases
173 |
174 | You can see the list of available releases on the [GitHub Releases](https://github.com/pksol/pytest-fastapi-deps/releases) page.
175 |
176 | We follow [Semantic Versions](https://semver.org/) specification.
177 |
178 | ## 🛡 License
179 |
180 | [](https://github.com/pksol/pytest-fastapi-deps/blob/master/LICENSE)
181 |
182 | This project is licensed under the terms of the `MIT` license. See [LICENSE](https://github.com/pksol/pytest-fastapi-deps/blob/master/LICENSE) for more details.
183 |
184 | ## 📃 Citation
185 |
186 | ```bibtex
187 | @misc{pytest-fastapi-deps,
188 | author = {Peter Kogan},
189 | title = {A fixture which allows easy replacement of fastapi dependencies for testing},
190 | year = {2022},
191 | publisher = {GitHub},
192 | journal = {GitHub repository},
193 | howpublished = {\url{https://github.com/pksol/pytest-fastapi-deps}}
194 | }
195 | ```
196 |
197 | ## Credits [](https://github.com/TezRomacH/python-package-template)
198 |
199 | This project was generated with [`python-package-template`](https://github.com/TezRomacH/python-package-template)
200 |
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 | # Security
2 |
3 | ## 🔐 Reporting Security Issues
4 |
5 | > Do not open issues that might have security implications!
6 | > It is critical that security related issues are reported privately so we have time to address them before they become public knowledge.
7 |
8 | Vulnerabilities can be reported by emailing core members:
9 |
10 | - Peter Kogan [kogan.peter@gmail.com](mailto:kogan.peter@gmail.com)
11 |
12 | Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue:
13 |
14 | - Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
15 | - Full paths of source file(s) related to the manifestation of the issue
16 | - The location of the affected source code (tag/branch/commit or direct URL)
17 | - Any special configuration required to reproduce the issue
18 | - Environment (e.g. Linux / Windows / macOS)
19 | - Step-by-step instructions to reproduce the issue
20 | - Proof-of-concept or exploit code (if possible)
21 | - Impact of the issue, including how an attacker might exploit the issue
22 |
23 | This information will help us triage your report more quickly.
24 |
25 | ## Preferred Languages
26 |
27 | We prefer all communications to be in English.
28 |
--------------------------------------------------------------------------------
/cookiecutter-config-file.yml:
--------------------------------------------------------------------------------
1 | # This file contains values from Cookiecutter
2 |
3 | default_context:
4 | project_name: "pytest-fastapi-deps"
5 | project_description: "A fixture which allows easy replacement of fastapi dependencies for testing"
6 | organization: "Peter Kogan"
7 | license: "MIT"
8 | minimal_python_version: 3.7
9 | github_name: "pksol"
10 | email: "kogan.peter@gmail.com"
11 | version: "0.1.0"
12 | line_length: "88"
13 | create_example_template: "none"
14 |
--------------------------------------------------------------------------------
/poetry.lock:
--------------------------------------------------------------------------------
1 | [[package]]
2 | name = "anyio"
3 | version = "3.6.1"
4 | description = "High level compatibility layer for multiple asynchronous event loop implementations"
5 | category = "main"
6 | optional = false
7 | python-versions = ">=3.6.2"
8 |
9 | [package.dependencies]
10 | idna = ">=2.8"
11 | sniffio = ">=1.1"
12 | typing-extensions = {version = "*", markers = "python_version < \"3.8\""}
13 |
14 | [package.extras]
15 | doc = ["packaging", "sphinx-rtd-theme", "sphinx-autodoc-typehints (>=1.2.0)"]
16 | test = ["coverage[toml] (>=4.5)", "hypothesis (>=4.0)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "contextlib2", "uvloop (<0.15)", "mock (>=4)", "uvloop (>=0.15)"]
17 | trio = ["trio (>=0.16)"]
18 |
19 | [[package]]
20 | name = "astroid"
21 | version = "2.11.7"
22 | description = "An abstract syntax tree for Python with inference support."
23 | category = "dev"
24 | optional = false
25 | python-versions = ">=3.6.2"
26 |
27 | [package.dependencies]
28 | lazy-object-proxy = ">=1.4.0"
29 | typed-ast = {version = ">=1.4.0,<2.0", markers = "implementation_name == \"cpython\" and python_version < \"3.8\""}
30 | typing-extensions = {version = ">=3.10", markers = "python_version < \"3.10\""}
31 | wrapt = ">=1.11,<2"
32 |
33 | [[package]]
34 | name = "atomicwrites"
35 | version = "1.4.1"
36 | description = "Atomic file writes."
37 | category = "main"
38 | optional = false
39 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
40 |
41 | [[package]]
42 | name = "attrs"
43 | version = "22.1.0"
44 | description = "Classes Without Boilerplate"
45 | category = "main"
46 | optional = false
47 | python-versions = ">=3.5"
48 |
49 | [package.extras]
50 | dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "mypy (>=0.900,!=0.940)", "pytest-mypy-plugins", "zope.interface", "furo", "sphinx", "sphinx-notfound-page", "pre-commit", "cloudpickle"]
51 | docs = ["furo", "sphinx", "zope.interface", "sphinx-notfound-page"]
52 | tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "mypy (>=0.900,!=0.940)", "pytest-mypy-plugins", "zope.interface", "cloudpickle"]
53 | tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "mypy (>=0.900,!=0.940)", "pytest-mypy-plugins", "cloudpickle"]
54 |
55 | [[package]]
56 | name = "bandit"
57 | version = "1.7.4"
58 | description = "Security oriented static analyser for python code."
59 | category = "dev"
60 | optional = false
61 | python-versions = ">=3.7"
62 |
63 | [package.dependencies]
64 | colorama = {version = ">=0.3.9", markers = "platform_system == \"Windows\""}
65 | GitPython = ">=1.0.1"
66 | PyYAML = ">=5.3.1"
67 | stevedore = ">=1.20.0"
68 |
69 | [package.extras]
70 | test = ["coverage (>=4.5.4)", "fixtures (>=3.0.0)", "flake8 (>=4.0.0)", "stestr (>=2.5.0)", "testscenarios (>=0.5.0)", "testtools (>=2.3.0)", "toml", "beautifulsoup4 (>=4.8.0)", "pylint (==1.9.4)"]
71 | toml = ["toml"]
72 | yaml = ["pyyaml"]
73 |
74 | [[package]]
75 | name = "black"
76 | version = "22.6.0"
77 | description = "The uncompromising code formatter."
78 | category = "dev"
79 | optional = false
80 | python-versions = ">=3.6.2"
81 |
82 | [package.dependencies]
83 | click = ">=8.0.0"
84 | mypy-extensions = ">=0.4.3"
85 | pathspec = ">=0.9.0"
86 | platformdirs = ">=2"
87 | tomli = {version = ">=1.1.0", markers = "python_full_version < \"3.11.0a7\""}
88 | typed-ast = {version = ">=1.4.2", markers = "python_version < \"3.8\" and implementation_name == \"cpython\""}
89 | typing-extensions = {version = ">=3.10.0.0", markers = "python_version < \"3.10\""}
90 |
91 | [package.extras]
92 | colorama = ["colorama (>=0.4.3)"]
93 | d = ["aiohttp (>=3.7.4)"]
94 | jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"]
95 | uvloop = ["uvloop (>=0.15.2)"]
96 |
97 | [[package]]
98 | name = "certifi"
99 | version = "2022.6.15"
100 | description = "Python package for providing Mozilla's CA Bundle."
101 | category = "dev"
102 | optional = false
103 | python-versions = ">=3.6"
104 |
105 | [[package]]
106 | name = "cfgv"
107 | version = "3.3.1"
108 | description = "Validate configuration and produce human readable error messages."
109 | category = "dev"
110 | optional = false
111 | python-versions = ">=3.6.1"
112 |
113 | [[package]]
114 | name = "charset-normalizer"
115 | version = "2.1.0"
116 | description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
117 | category = "dev"
118 | optional = false
119 | python-versions = ">=3.6.0"
120 |
121 | [package.extras]
122 | unicode_backport = ["unicodedata2"]
123 |
124 | [[package]]
125 | name = "click"
126 | version = "8.1.3"
127 | description = "Composable command line interface toolkit"
128 | category = "dev"
129 | optional = false
130 | python-versions = ">=3.7"
131 |
132 | [package.dependencies]
133 | colorama = {version = "*", markers = "platform_system == \"Windows\""}
134 | importlib-metadata = {version = "*", markers = "python_version < \"3.8\""}
135 |
136 | [[package]]
137 | name = "colorama"
138 | version = "0.4.5"
139 | description = "Cross-platform colored terminal text."
140 | category = "main"
141 | optional = false
142 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
143 |
144 | [[package]]
145 | name = "coverage"
146 | version = "6.4.2"
147 | description = "Code coverage measurement for Python"
148 | category = "dev"
149 | optional = false
150 | python-versions = ">=3.7"
151 |
152 | [package.dependencies]
153 | tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.11.0a6\" and extra == \"toml\""}
154 |
155 | [package.extras]
156 | toml = ["tomli"]
157 |
158 | [[package]]
159 | name = "coverage-badge"
160 | version = "1.1.0"
161 | description = "Generate coverage badges for Coverage.py."
162 | category = "dev"
163 | optional = false
164 | python-versions = "*"
165 |
166 | [package.dependencies]
167 | coverage = "*"
168 |
169 | [[package]]
170 | name = "darglint"
171 | version = "1.8.1"
172 | description = "A utility for ensuring Google-style docstrings stay up to date with the source code."
173 | category = "dev"
174 | optional = false
175 | python-versions = ">=3.6,<4.0"
176 |
177 | [[package]]
178 | name = "dill"
179 | version = "0.3.5.1"
180 | description = "serialize all of python"
181 | category = "dev"
182 | optional = false
183 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*"
184 |
185 | [package.extras]
186 | graph = ["objgraph (>=1.7.2)"]
187 |
188 | [[package]]
189 | name = "distlib"
190 | version = "0.3.5"
191 | description = "Distribution utilities"
192 | category = "dev"
193 | optional = false
194 | python-versions = "*"
195 |
196 | [[package]]
197 | name = "dparse"
198 | version = "0.5.1"
199 | description = "A parser for Python dependency files"
200 | category = "dev"
201 | optional = false
202 | python-versions = ">=3.5"
203 |
204 | [package.dependencies]
205 | packaging = "*"
206 | pyyaml = "*"
207 | toml = "*"
208 |
209 | [package.extras]
210 | pipenv = ["pipenv"]
211 |
212 | [[package]]
213 | name = "fastapi"
214 | version = "0.79.0"
215 | description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production"
216 | category = "main"
217 | optional = false
218 | python-versions = ">=3.6.1"
219 |
220 | [package.dependencies]
221 | pydantic = ">=1.6.2,<1.7 || >1.7,<1.7.1 || >1.7.1,<1.7.2 || >1.7.2,<1.7.3 || >1.7.3,<1.8 || >1.8,<1.8.1 || >1.8.1,<2.0.0"
222 | starlette = "0.19.1"
223 |
224 | [package.extras]
225 | all = ["requests (>=2.24.0,<3.0.0)", "jinja2 (>=2.11.2,<4.0.0)", "python-multipart (>=0.0.5,<0.0.6)", "itsdangerous (>=1.1.0,<3.0.0)", "pyyaml (>=5.3.1,<7.0.0)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0,<6.0.0)", "orjson (>=3.2.1,<4.0.0)", "email_validator (>=1.1.1,<2.0.0)", "uvicorn[standard] (>=0.12.0,<0.18.0)"]
226 | dev = ["python-jose[cryptography] (>=3.3.0,<4.0.0)", "passlib[bcrypt] (>=1.7.2,<2.0.0)", "autoflake (>=1.4.0,<2.0.0)", "flake8 (>=3.8.3,<4.0.0)", "uvicorn[standard] (>=0.12.0,<0.18.0)", "pre-commit (>=2.17.0,<3.0.0)"]
227 | doc = ["mkdocs (>=1.1.2,<2.0.0)", "mkdocs-material (>=8.1.4,<9.0.0)", "mdx-include (>=1.4.1,<2.0.0)", "mkdocs-markdownextradata-plugin (>=0.1.7,<0.3.0)", "typer (>=0.4.1,<0.5.0)", "pyyaml (>=5.3.1,<7.0.0)"]
228 | test = ["pytest (>=6.2.4,<7.0.0)", "pytest-cov (>=2.12.0,<4.0.0)", "mypy (==0.910)", "flake8 (>=3.8.3,<4.0.0)", "black (==22.3.0)", "isort (>=5.0.6,<6.0.0)", "requests (>=2.24.0,<3.0.0)", "httpx (>=0.14.0,<0.19.0)", "email_validator (>=1.1.1,<2.0.0)", "sqlalchemy (>=1.3.18,<1.5.0)", "peewee (>=3.13.3,<4.0.0)", "databases[sqlite] (>=0.3.2,<0.6.0)", "orjson (>=3.2.1,<4.0.0)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0,<6.0.0)", "python-multipart (>=0.0.5,<0.0.6)", "flask (>=1.1.2,<3.0.0)", "anyio[trio] (>=3.2.1,<4.0.0)", "types-ujson (==4.2.1)", "types-orjson (==3.6.2)", "types-dataclasses (==0.6.5)"]
229 |
230 | [[package]]
231 | name = "filelock"
232 | version = "3.7.1"
233 | description = "A platform independent file lock."
234 | category = "dev"
235 | optional = false
236 | python-versions = ">=3.7"
237 |
238 | [package.extras]
239 | docs = ["furo (>=2021.8.17b43)", "sphinx (>=4.1)", "sphinx-autodoc-typehints (>=1.12)"]
240 | testing = ["covdefaults (>=1.2.0)", "coverage (>=4)", "pytest (>=4)", "pytest-cov", "pytest-timeout (>=1.4.2)"]
241 |
242 | [[package]]
243 | name = "gitdb"
244 | version = "4.0.9"
245 | description = "Git Object Database"
246 | category = "dev"
247 | optional = false
248 | python-versions = ">=3.6"
249 |
250 | [package.dependencies]
251 | smmap = ">=3.0.1,<6"
252 |
253 | [[package]]
254 | name = "gitpython"
255 | version = "3.1.27"
256 | description = "GitPython is a python library used to interact with Git repositories"
257 | category = "dev"
258 | optional = false
259 | python-versions = ">=3.7"
260 |
261 | [package.dependencies]
262 | gitdb = ">=4.0.1,<5"
263 | typing-extensions = {version = ">=3.7.4.3", markers = "python_version < \"3.8\""}
264 |
265 | [[package]]
266 | name = "identify"
267 | version = "2.5.2"
268 | description = "File identification library for Python"
269 | category = "dev"
270 | optional = false
271 | python-versions = ">=3.7"
272 |
273 | [package.extras]
274 | license = ["ukkonen"]
275 |
276 | [[package]]
277 | name = "idna"
278 | version = "3.3"
279 | description = "Internationalized Domain Names in Applications (IDNA)"
280 | category = "main"
281 | optional = false
282 | python-versions = ">=3.5"
283 |
284 | [[package]]
285 | name = "importlib-metadata"
286 | version = "4.12.0"
287 | description = "Read metadata from Python packages"
288 | category = "main"
289 | optional = false
290 | python-versions = ">=3.7"
291 |
292 | [package.dependencies]
293 | typing-extensions = {version = ">=3.6.4", markers = "python_version < \"3.8\""}
294 | zipp = ">=0.5"
295 |
296 | [package.extras]
297 | docs = ["sphinx", "jaraco.packaging (>=9)", "rst.linker (>=1.9)"]
298 | perf = ["ipython"]
299 | testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.3)", "packaging", "pyfakefs", "flufl.flake8", "pytest-perf (>=0.9.2)", "pytest-black (>=0.3.7)", "pytest-mypy (>=0.9.1)", "importlib-resources (>=1.3)"]
300 |
301 | [[package]]
302 | name = "iniconfig"
303 | version = "1.1.1"
304 | description = "iniconfig: brain-dead simple config-ini parsing"
305 | category = "main"
306 | optional = false
307 | python-versions = "*"
308 |
309 | [[package]]
310 | name = "isort"
311 | version = "5.10.1"
312 | description = "A Python utility / library to sort Python imports."
313 | category = "dev"
314 | optional = false
315 | python-versions = ">=3.6.1,<4.0"
316 |
317 | [package.dependencies]
318 | colorama = {version = ">=0.4.3,<0.5.0", optional = true, markers = "extra == \"colors\""}
319 |
320 | [package.extras]
321 | pipfile_deprecated_finder = ["pipreqs", "requirementslib"]
322 | requirements_deprecated_finder = ["pipreqs", "pip-api"]
323 | colors = ["colorama (>=0.4.3,<0.5.0)"]
324 | plugins = ["setuptools"]
325 |
326 | [[package]]
327 | name = "lazy-object-proxy"
328 | version = "1.7.1"
329 | description = "A fast and thorough lazy object proxy."
330 | category = "dev"
331 | optional = false
332 | python-versions = ">=3.6"
333 |
334 | [[package]]
335 | name = "mccabe"
336 | version = "0.7.0"
337 | description = "McCabe checker, plugin for flake8"
338 | category = "dev"
339 | optional = false
340 | python-versions = ">=3.6"
341 |
342 | [[package]]
343 | name = "mypy"
344 | version = "0.961"
345 | description = "Optional static typing for Python"
346 | category = "dev"
347 | optional = false
348 | python-versions = ">=3.6"
349 |
350 | [package.dependencies]
351 | mypy-extensions = ">=0.4.3"
352 | tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""}
353 | typed-ast = {version = ">=1.4.0,<2", markers = "python_version < \"3.8\""}
354 | typing-extensions = ">=3.10"
355 |
356 | [package.extras]
357 | dmypy = ["psutil (>=4.0)"]
358 | python2 = ["typed-ast (>=1.4.0,<2)"]
359 | reports = ["lxml"]
360 |
361 | [[package]]
362 | name = "mypy-extensions"
363 | version = "0.4.3"
364 | description = "Experimental type system extensions for programs checked with the mypy typechecker."
365 | category = "dev"
366 | optional = false
367 | python-versions = "*"
368 |
369 | [[package]]
370 | name = "nodeenv"
371 | version = "1.7.0"
372 | description = "Node.js virtual environment builder"
373 | category = "dev"
374 | optional = false
375 | python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*"
376 |
377 | [[package]]
378 | name = "packaging"
379 | version = "21.3"
380 | description = "Core utilities for Python packages"
381 | category = "main"
382 | optional = false
383 | python-versions = ">=3.6"
384 |
385 | [package.dependencies]
386 | pyparsing = ">=2.0.2,<3.0.5 || >3.0.5"
387 |
388 | [[package]]
389 | name = "pathspec"
390 | version = "0.9.0"
391 | description = "Utility library for gitignore style pattern matching of file paths."
392 | category = "dev"
393 | optional = false
394 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7"
395 |
396 | [[package]]
397 | name = "pbr"
398 | version = "5.9.0"
399 | description = "Python Build Reasonableness"
400 | category = "dev"
401 | optional = false
402 | python-versions = ">=2.6"
403 |
404 | [[package]]
405 | name = "platformdirs"
406 | version = "2.5.2"
407 | description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
408 | category = "dev"
409 | optional = false
410 | python-versions = ">=3.7"
411 |
412 | [package.extras]
413 | docs = ["furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx-autodoc-typehints (>=1.12)", "sphinx (>=4)"]
414 | test = ["appdirs (==1.4.4)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)", "pytest (>=6)"]
415 |
416 | [[package]]
417 | name = "pluggy"
418 | version = "1.0.0"
419 | description = "plugin and hook calling mechanisms for python"
420 | category = "main"
421 | optional = false
422 | python-versions = ">=3.6"
423 |
424 | [package.dependencies]
425 | importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""}
426 |
427 | [package.extras]
428 | dev = ["pre-commit", "tox"]
429 | testing = ["pytest", "pytest-benchmark"]
430 |
431 | [[package]]
432 | name = "pre-commit"
433 | version = "2.20.0"
434 | description = "A framework for managing and maintaining multi-language pre-commit hooks."
435 | category = "dev"
436 | optional = false
437 | python-versions = ">=3.7"
438 |
439 | [package.dependencies]
440 | cfgv = ">=2.0.0"
441 | identify = ">=1.0.0"
442 | importlib-metadata = {version = "*", markers = "python_version < \"3.8\""}
443 | nodeenv = ">=0.11.1"
444 | pyyaml = ">=5.1"
445 | toml = "*"
446 | virtualenv = ">=20.0.8"
447 |
448 | [[package]]
449 | name = "py"
450 | version = "1.11.0"
451 | description = "library with cross-python path, ini-parsing, io, code, log facilities"
452 | category = "main"
453 | optional = false
454 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
455 |
456 | [[package]]
457 | name = "pydantic"
458 | version = "1.9.1"
459 | description = "Data validation and settings management using python type hints"
460 | category = "main"
461 | optional = false
462 | python-versions = ">=3.6.1"
463 |
464 | [package.dependencies]
465 | typing-extensions = ">=3.7.4.3"
466 |
467 | [package.extras]
468 | dotenv = ["python-dotenv (>=0.10.4)"]
469 | email = ["email-validator (>=1.0.3)"]
470 |
471 | [[package]]
472 | name = "pydocstyle"
473 | version = "6.1.1"
474 | description = "Python docstring style checker"
475 | category = "dev"
476 | optional = false
477 | python-versions = ">=3.6"
478 |
479 | [package.dependencies]
480 | snowballstemmer = "*"
481 |
482 | [package.extras]
483 | toml = ["toml"]
484 |
485 | [[package]]
486 | name = "pylint"
487 | version = "2.13.9"
488 | description = "python code static checker"
489 | category = "dev"
490 | optional = false
491 | python-versions = ">=3.6.2"
492 |
493 | [package.dependencies]
494 | astroid = ">=2.11.5,<=2.12.0-dev0"
495 | colorama = {version = "*", markers = "sys_platform == \"win32\""}
496 | dill = ">=0.2"
497 | isort = ">=4.2.5,<6"
498 | mccabe = ">=0.6,<0.8"
499 | platformdirs = ">=2.2.0"
500 | tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""}
501 | typing-extensions = {version = ">=3.10.0", markers = "python_version < \"3.10\""}
502 |
503 | [package.extras]
504 | testutil = ["gitpython (>3)"]
505 |
506 | [[package]]
507 | name = "pyparsing"
508 | version = "3.0.9"
509 | description = "pyparsing module - Classes and methods to define and execute parsing grammars"
510 | category = "main"
511 | optional = false
512 | python-versions = ">=3.6.8"
513 |
514 | [package.extras]
515 | diagrams = ["railroad-diagrams", "jinja2"]
516 |
517 | [[package]]
518 | name = "pytest"
519 | version = "7.1.2"
520 | description = "pytest: simple powerful testing with Python"
521 | category = "main"
522 | optional = false
523 | python-versions = ">=3.7"
524 |
525 | [package.dependencies]
526 | atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""}
527 | attrs = ">=19.2.0"
528 | colorama = {version = "*", markers = "sys_platform == \"win32\""}
529 | importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""}
530 | iniconfig = "*"
531 | packaging = "*"
532 | pluggy = ">=0.12,<2.0"
533 | py = ">=1.8.2"
534 | tomli = ">=1.0.0"
535 |
536 | [package.extras]
537 | testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"]
538 |
539 | [[package]]
540 | name = "pytest-cov"
541 | version = "3.0.0"
542 | description = "Pytest plugin for measuring coverage."
543 | category = "dev"
544 | optional = false
545 | python-versions = ">=3.6"
546 |
547 | [package.dependencies]
548 | coverage = {version = ">=5.2.1", extras = ["toml"]}
549 | pytest = ">=4.6"
550 |
551 | [package.extras]
552 | testing = ["fields", "hunter", "process-tests", "six", "pytest-xdist", "virtualenv"]
553 |
554 | [[package]]
555 | name = "pytest-html"
556 | version = "3.1.1"
557 | description = "pytest plugin for generating HTML reports"
558 | category = "dev"
559 | optional = false
560 | python-versions = ">=3.6"
561 |
562 | [package.dependencies]
563 | pytest = ">=5.0,<6.0.0 || >6.0.0"
564 | pytest-metadata = "*"
565 |
566 | [[package]]
567 | name = "pytest-metadata"
568 | version = "2.0.2"
569 | description = "pytest plugin for test session metadata"
570 | category = "dev"
571 | optional = false
572 | python-versions = ">=3.7,<4.0"
573 |
574 | [package.dependencies]
575 | pytest = ">=3.0.0,<8.0.0"
576 |
577 | [[package]]
578 | name = "pyupgrade"
579 | version = "2.37.3"
580 | description = "A tool to automatically upgrade syntax for newer versions."
581 | category = "dev"
582 | optional = false
583 | python-versions = ">=3.7"
584 |
585 | [package.dependencies]
586 | tokenize-rt = ">=3.2.0"
587 |
588 | [[package]]
589 | name = "pyyaml"
590 | version = "6.0"
591 | description = "YAML parser and emitter for Python"
592 | category = "dev"
593 | optional = false
594 | python-versions = ">=3.6"
595 |
596 | [[package]]
597 | name = "requests"
598 | version = "2.28.1"
599 | description = "Python HTTP for Humans."
600 | category = "dev"
601 | optional = false
602 | python-versions = ">=3.7, <4"
603 |
604 | [package.dependencies]
605 | certifi = ">=2017.4.17"
606 | charset-normalizer = ">=2,<3"
607 | idna = ">=2.5,<4"
608 | urllib3 = ">=1.21.1,<1.27"
609 |
610 | [package.extras]
611 | socks = ["PySocks (>=1.5.6,!=1.5.7)"]
612 | use_chardet_on_py3 = ["chardet (>=3.0.2,<6)"]
613 |
614 | [[package]]
615 | name = "ruamel.yaml"
616 | version = "0.17.21"
617 | description = "ruamel.yaml is a YAML parser/emitter that supports roundtrip preservation of comments, seq/map flow style, and map key order"
618 | category = "dev"
619 | optional = false
620 | python-versions = ">=3"
621 |
622 | [package.dependencies]
623 | "ruamel.yaml.clib" = {version = ">=0.2.6", markers = "platform_python_implementation == \"CPython\" and python_version < \"3.11\""}
624 |
625 | [package.extras]
626 | docs = ["ryd"]
627 | jinja2 = ["ruamel.yaml.jinja2 (>=0.2)"]
628 |
629 | [[package]]
630 | name = "ruamel.yaml.clib"
631 | version = "0.2.6"
632 | description = "C version of reader, parser and emitter for ruamel.yaml derived from libyaml"
633 | category = "dev"
634 | optional = false
635 | python-versions = ">=3.5"
636 |
637 | [[package]]
638 | name = "safety"
639 | version = "2.1.1"
640 | description = "Checks installed dependencies for known vulnerabilities and licenses."
641 | category = "dev"
642 | optional = false
643 | python-versions = "*"
644 |
645 | [package.dependencies]
646 | Click = ">=8.0.2"
647 | dparse = ">=0.5.1"
648 | packaging = ">=21.0"
649 | requests = "*"
650 | "ruamel.yaml" = ">=0.17.21"
651 |
652 | [[package]]
653 | name = "smmap"
654 | version = "5.0.0"
655 | description = "A pure Python implementation of a sliding window memory map manager"
656 | category = "dev"
657 | optional = false
658 | python-versions = ">=3.6"
659 |
660 | [[package]]
661 | name = "sniffio"
662 | version = "1.2.0"
663 | description = "Sniff out which async library your code is running under"
664 | category = "main"
665 | optional = false
666 | python-versions = ">=3.5"
667 |
668 | [[package]]
669 | name = "snowballstemmer"
670 | version = "2.2.0"
671 | description = "This package provides 29 stemmers for 28 languages generated from Snowball algorithms."
672 | category = "dev"
673 | optional = false
674 | python-versions = "*"
675 |
676 | [[package]]
677 | name = "starlette"
678 | version = "0.19.1"
679 | description = "The little ASGI library that shines."
680 | category = "main"
681 | optional = false
682 | python-versions = ">=3.6"
683 |
684 | [package.dependencies]
685 | anyio = ">=3.4.0,<5"
686 | typing-extensions = {version = ">=3.10.0", markers = "python_version < \"3.10\""}
687 |
688 | [package.extras]
689 | full = ["itsdangerous", "jinja2", "python-multipart", "pyyaml", "requests"]
690 |
691 | [[package]]
692 | name = "stevedore"
693 | version = "3.5.0"
694 | description = "Manage dynamic plugins for Python applications"
695 | category = "dev"
696 | optional = false
697 | python-versions = ">=3.6"
698 |
699 | [package.dependencies]
700 | importlib-metadata = {version = ">=1.7.0", markers = "python_version < \"3.8\""}
701 | pbr = ">=2.0.0,<2.1.0 || >2.1.0"
702 |
703 | [[package]]
704 | name = "tokenize-rt"
705 | version = "4.2.1"
706 | description = "A wrapper around the stdlib `tokenize` which roundtrips."
707 | category = "dev"
708 | optional = false
709 | python-versions = ">=3.6.1"
710 |
711 | [[package]]
712 | name = "toml"
713 | version = "0.10.2"
714 | description = "Python Library for Tom's Obvious, Minimal Language"
715 | category = "dev"
716 | optional = false
717 | python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
718 |
719 | [[package]]
720 | name = "tomli"
721 | version = "2.0.1"
722 | description = "A lil' TOML parser"
723 | category = "main"
724 | optional = false
725 | python-versions = ">=3.7"
726 |
727 | [[package]]
728 | name = "typed-ast"
729 | version = "1.5.4"
730 | description = "a fork of Python 2 and 3 ast modules with type comment support"
731 | category = "dev"
732 | optional = false
733 | python-versions = ">=3.6"
734 |
735 | [[package]]
736 | name = "typing-extensions"
737 | version = "4.3.0"
738 | description = "Backported and Experimental Type Hints for Python 3.7+"
739 | category = "main"
740 | optional = false
741 | python-versions = ">=3.7"
742 |
743 | [[package]]
744 | name = "urllib3"
745 | version = "1.26.11"
746 | description = "HTTP library with thread-safe connection pooling, file post, and more."
747 | category = "dev"
748 | optional = false
749 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, <4"
750 |
751 | [package.extras]
752 | brotli = ["brotlicffi (>=0.8.0)", "brotli (>=1.0.9)", "brotlipy (>=0.6.0)"]
753 | secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "ipaddress"]
754 | socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"]
755 |
756 | [[package]]
757 | name = "virtualenv"
758 | version = "20.16.2"
759 | description = "Virtual Python Environment builder"
760 | category = "dev"
761 | optional = false
762 | python-versions = ">=3.6"
763 |
764 | [package.dependencies]
765 | distlib = ">=0.3.1,<1"
766 | filelock = ">=3.2,<4"
767 | importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""}
768 | platformdirs = ">=2,<3"
769 |
770 | [package.extras]
771 | docs = ["proselint (>=0.10.2)", "sphinx (>=3)", "sphinx-argparse (>=0.2.5)", "sphinx-rtd-theme (>=0.4.3)", "towncrier (>=21.3)"]
772 | testing = ["coverage (>=4)", "coverage-enable-subprocess (>=1)", "flaky (>=3)", "packaging (>=20.0)", "pytest (>=4)", "pytest-env (>=0.6.2)", "pytest-freezegun (>=0.4.1)", "pytest-mock (>=2)", "pytest-randomly (>=1)", "pytest-timeout (>=1)"]
773 |
774 | [[package]]
775 | name = "wrapt"
776 | version = "1.14.1"
777 | description = "Module for decorators, wrappers and monkey patching."
778 | category = "dev"
779 | optional = false
780 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7"
781 |
782 | [[package]]
783 | name = "zipp"
784 | version = "3.8.1"
785 | description = "Backport of pathlib-compatible object wrapper for zip files"
786 | category = "main"
787 | optional = false
788 | python-versions = ">=3.7"
789 |
790 | [package.extras]
791 | docs = ["sphinx", "jaraco.packaging (>=9)", "rst.linker (>=1.9)", "jaraco.tidelift (>=1.4)"]
792 | testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.3)", "jaraco.itertools", "func-timeout", "pytest-black (>=0.3.7)", "pytest-mypy (>=0.9.1)"]
793 |
794 | [metadata]
795 | lock-version = "1.1"
796 | python-versions = "^3.7"
797 | content-hash = "22647b38d68a8c359af8cf8e2f9a049b36151f26930abe8817189ddc435f3515"
798 |
799 | [metadata.files]
800 | anyio = [
801 | {file = "anyio-3.6.1-py3-none-any.whl", hash = "sha256:cb29b9c70620506a9a8f87a309591713446953302d7d995344d0d7c6c0c9a7be"},
802 | {file = "anyio-3.6.1.tar.gz", hash = "sha256:413adf95f93886e442aea925f3ee43baa5a765a64a0f52c6081894f9992fdd0b"},
803 | ]
804 | astroid = []
805 | atomicwrites = []
806 | attrs = []
807 | bandit = [
808 | {file = "bandit-1.7.4-py3-none-any.whl", hash = "sha256:412d3f259dab4077d0e7f0c11f50f650cc7d10db905d98f6520a95a18049658a"},
809 | {file = "bandit-1.7.4.tar.gz", hash = "sha256:2d63a8c573417bae338962d4b9b06fbc6080f74ecd955a092849e1e65c717bd2"},
810 | ]
811 | black = [
812 | {file = "black-22.6.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f586c26118bc6e714ec58c09df0157fe2d9ee195c764f630eb0d8e7ccce72e69"},
813 | {file = "black-22.6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b270a168d69edb8b7ed32c193ef10fd27844e5c60852039599f9184460ce0807"},
814 | {file = "black-22.6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6797f58943fceb1c461fb572edbe828d811e719c24e03375fd25170ada53825e"},
815 | {file = "black-22.6.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c85928b9d5f83b23cee7d0efcb310172412fbf7cb9d9ce963bd67fd141781def"},
816 | {file = "black-22.6.0-cp310-cp310-win_amd64.whl", hash = "sha256:f6fe02afde060bbeef044af7996f335fbe90b039ccf3f5eb8f16df8b20f77666"},
817 | {file = "black-22.6.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:cfaf3895a9634e882bf9d2363fed5af8888802d670f58b279b0bece00e9a872d"},
818 | {file = "black-22.6.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94783f636bca89f11eb5d50437e8e17fbc6a929a628d82304c80fa9cd945f256"},
819 | {file = "black-22.6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:2ea29072e954a4d55a2ff58971b83365eba5d3d357352a07a7a4df0d95f51c78"},
820 | {file = "black-22.6.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:e439798f819d49ba1c0bd9664427a05aab79bfba777a6db94fd4e56fae0cb849"},
821 | {file = "black-22.6.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:187d96c5e713f441a5829e77120c269b6514418f4513a390b0499b0987f2ff1c"},
822 | {file = "black-22.6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:074458dc2f6e0d3dab7928d4417bb6957bb834434516f21514138437accdbe90"},
823 | {file = "black-22.6.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:a218d7e5856f91d20f04e931b6f16d15356db1c846ee55f01bac297a705ca24f"},
824 | {file = "black-22.6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:568ac3c465b1c8b34b61cd7a4e349e93f91abf0f9371eda1cf87194663ab684e"},
825 | {file = "black-22.6.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:6c1734ab264b8f7929cef8ae5f900b85d579e6cbfde09d7387da8f04771b51c6"},
826 | {file = "black-22.6.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c9a3ac16efe9ec7d7381ddebcc022119794872abce99475345c5a61aa18c45ad"},
827 | {file = "black-22.6.0-cp38-cp38-win_amd64.whl", hash = "sha256:b9fd45787ba8aa3f5e0a0a98920c1012c884622c6c920dbe98dbd05bc7c70fbf"},
828 | {file = "black-22.6.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7ba9be198ecca5031cd78745780d65a3f75a34b2ff9be5837045dce55db83d1c"},
829 | {file = "black-22.6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a3db5b6409b96d9bd543323b23ef32a1a2b06416d525d27e0f67e74f1446c8f2"},
830 | {file = "black-22.6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:560558527e52ce8afba936fcce93a7411ab40c7d5fe8c2463e279e843c0328ee"},
831 | {file = "black-22.6.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b154e6bbde1e79ea3260c4b40c0b7b3109ffcdf7bc4ebf8859169a6af72cd70b"},
832 | {file = "black-22.6.0-cp39-cp39-win_amd64.whl", hash = "sha256:4af5bc0e1f96be5ae9bd7aaec219c901a94d6caa2484c21983d043371c733fc4"},
833 | {file = "black-22.6.0-py3-none-any.whl", hash = "sha256:ac609cf8ef5e7115ddd07d85d988d074ed00e10fbc3445aee393e70164a2219c"},
834 | {file = "black-22.6.0.tar.gz", hash = "sha256:6c6d39e28aed379aec40da1c65434c77d75e65bb59a1e1c283de545fb4e7c6c9"},
835 | ]
836 | certifi = [
837 | {file = "certifi-2022.6.15-py3-none-any.whl", hash = "sha256:fe86415d55e84719d75f8b69414f6438ac3547d2078ab91b67e779ef69378412"},
838 | {file = "certifi-2022.6.15.tar.gz", hash = "sha256:84c85a9078b11105f04f3036a9482ae10e4621616db313fe045dd24743a0820d"},
839 | ]
840 | cfgv = [
841 | {file = "cfgv-3.3.1-py2.py3-none-any.whl", hash = "sha256:c6a0883f3917a037485059700b9e75da2464e6c27051014ad85ba6aaa5884426"},
842 | {file = "cfgv-3.3.1.tar.gz", hash = "sha256:f5a830efb9ce7a445376bb66ec94c638a9787422f96264c98edc6bdeed8ab736"},
843 | ]
844 | charset-normalizer = [
845 | {file = "charset-normalizer-2.1.0.tar.gz", hash = "sha256:575e708016ff3a5e3681541cb9d79312c416835686d054a23accb873b254f413"},
846 | {file = "charset_normalizer-2.1.0-py3-none-any.whl", hash = "sha256:5189b6f22b01957427f35b6a08d9a0bc45b46d3788ef5a92e978433c7a35f8a5"},
847 | ]
848 | click = [
849 | {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"},
850 | {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"},
851 | ]
852 | colorama = [
853 | {file = "colorama-0.4.5-py2.py3-none-any.whl", hash = "sha256:854bf444933e37f5824ae7bfc1e98d5bce2ebe4160d46b5edf346a89358e99da"},
854 | {file = "colorama-0.4.5.tar.gz", hash = "sha256:e6c6b4334fc50988a639d9b98aa429a0b57da6e17b9a44f0451f930b6967b7a4"},
855 | ]
856 | coverage = []
857 | coverage-badge = [
858 | {file = "coverage-badge-1.1.0.tar.gz", hash = "sha256:c824a106503e981c02821e7d32f008fb3984b2338aa8c3800ec9357e33345b78"},
859 | {file = "coverage_badge-1.1.0-py2.py3-none-any.whl", hash = "sha256:e365d56e5202e923d1b237f82defd628a02d1d645a147f867ac85c58c81d7997"},
860 | ]
861 | darglint = [
862 | {file = "darglint-1.8.1-py3-none-any.whl", hash = "sha256:5ae11c259c17b0701618a20c3da343a3eb98b3bc4b5a83d31cdd94f5ebdced8d"},
863 | {file = "darglint-1.8.1.tar.gz", hash = "sha256:080d5106df149b199822e7ee7deb9c012b49891538f14a11be681044f0bb20da"},
864 | ]
865 | dill = [
866 | {file = "dill-0.3.5.1-py2.py3-none-any.whl", hash = "sha256:33501d03270bbe410c72639b350e941882a8b0fd55357580fbc873fba0c59302"},
867 | {file = "dill-0.3.5.1.tar.gz", hash = "sha256:d75e41f3eff1eee599d738e76ba8f4ad98ea229db8b085318aa2b3333a208c86"},
868 | ]
869 | distlib = []
870 | dparse = [
871 | {file = "dparse-0.5.1-py3-none-any.whl", hash = "sha256:e953a25e44ebb60a5c6efc2add4420c177f1d8404509da88da9729202f306994"},
872 | {file = "dparse-0.5.1.tar.gz", hash = "sha256:a1b5f169102e1c894f9a7d5ccf6f9402a836a5d24be80a986c7ce9eaed78f367"},
873 | ]
874 | fastapi = []
875 | filelock = [
876 | {file = "filelock-3.7.1-py3-none-any.whl", hash = "sha256:37def7b658813cda163b56fc564cdc75e86d338246458c4c28ae84cabefa2404"},
877 | {file = "filelock-3.7.1.tar.gz", hash = "sha256:3a0fd85166ad9dbab54c9aec96737b744106dc5f15c0b09a6744a445299fcf04"},
878 | ]
879 | gitdb = [
880 | {file = "gitdb-4.0.9-py3-none-any.whl", hash = "sha256:8033ad4e853066ba6ca92050b9df2f89301b8fc8bf7e9324d412a63f8bf1a8fd"},
881 | {file = "gitdb-4.0.9.tar.gz", hash = "sha256:bac2fd45c0a1c9cf619e63a90d62bdc63892ef92387424b855792a6cabe789aa"},
882 | ]
883 | gitpython = [
884 | {file = "GitPython-3.1.27-py3-none-any.whl", hash = "sha256:5b68b000463593e05ff2b261acff0ff0972df8ab1b70d3cdbd41b546c8b8fc3d"},
885 | {file = "GitPython-3.1.27.tar.gz", hash = "sha256:1c885ce809e8ba2d88a29befeb385fcea06338d3640712b59ca623c220bb5704"},
886 | ]
887 | identify = []
888 | idna = [
889 | {file = "idna-3.3-py3-none-any.whl", hash = "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff"},
890 | {file = "idna-3.3.tar.gz", hash = "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"},
891 | ]
892 | importlib-metadata = [
893 | {file = "importlib_metadata-4.12.0-py3-none-any.whl", hash = "sha256:7401a975809ea1fdc658c3aa4f78cc2195a0e019c5cbc4c06122884e9ae80c23"},
894 | {file = "importlib_metadata-4.12.0.tar.gz", hash = "sha256:637245b8bab2b6502fcbc752cc4b7a6f6243bb02b31c5c26156ad103d3d45670"},
895 | ]
896 | iniconfig = [
897 | {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"},
898 | {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"},
899 | ]
900 | isort = [
901 | {file = "isort-5.10.1-py3-none-any.whl", hash = "sha256:6f62d78e2f89b4500b080fe3a81690850cd254227f27f75c3a0c491a1f351ba7"},
902 | {file = "isort-5.10.1.tar.gz", hash = "sha256:e8443a5e7a020e9d7f97f1d7d9cd17c88bcb3bc7e218bf9cf5095fe550be2951"},
903 | ]
904 | lazy-object-proxy = [
905 | {file = "lazy-object-proxy-1.7.1.tar.gz", hash = "sha256:d609c75b986def706743cdebe5e47553f4a5a1da9c5ff66d76013ef396b5a8a4"},
906 | {file = "lazy_object_proxy-1.7.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bb8c5fd1684d60a9902c60ebe276da1f2281a318ca16c1d0a96db28f62e9166b"},
907 | {file = "lazy_object_proxy-1.7.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a57d51ed2997e97f3b8e3500c984db50a554bb5db56c50b5dab1b41339b37e36"},
908 | {file = "lazy_object_proxy-1.7.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd45683c3caddf83abbb1249b653a266e7069a09f486daa8863fb0e7496a9fdb"},
909 | {file = "lazy_object_proxy-1.7.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:8561da8b3dd22d696244d6d0d5330618c993a215070f473b699e00cf1f3f6443"},
910 | {file = "lazy_object_proxy-1.7.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fccdf7c2c5821a8cbd0a9440a456f5050492f2270bd54e94360cac663398739b"},
911 | {file = "lazy_object_proxy-1.7.1-cp310-cp310-win32.whl", hash = "sha256:898322f8d078f2654d275124a8dd19b079080ae977033b713f677afcfc88e2b9"},
912 | {file = "lazy_object_proxy-1.7.1-cp310-cp310-win_amd64.whl", hash = "sha256:85b232e791f2229a4f55840ed54706110c80c0a210d076eee093f2b2e33e1bfd"},
913 | {file = "lazy_object_proxy-1.7.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:46ff647e76f106bb444b4533bb4153c7370cdf52efc62ccfc1a28bdb3cc95442"},
914 | {file = "lazy_object_proxy-1.7.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:12f3bb77efe1367b2515f8cb4790a11cffae889148ad33adad07b9b55e0ab22c"},
915 | {file = "lazy_object_proxy-1.7.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c19814163728941bb871240d45c4c30d33b8a2e85972c44d4e63dd7107faba44"},
916 | {file = "lazy_object_proxy-1.7.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:e40f2013d96d30217a51eeb1db28c9ac41e9d0ee915ef9d00da639c5b63f01a1"},
917 | {file = "lazy_object_proxy-1.7.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:2052837718516a94940867e16b1bb10edb069ab475c3ad84fd1e1a6dd2c0fcfc"},
918 | {file = "lazy_object_proxy-1.7.1-cp36-cp36m-win32.whl", hash = "sha256:6a24357267aa976abab660b1d47a34aaf07259a0c3859a34e536f1ee6e76b5bb"},
919 | {file = "lazy_object_proxy-1.7.1-cp36-cp36m-win_amd64.whl", hash = "sha256:6aff3fe5de0831867092e017cf67e2750c6a1c7d88d84d2481bd84a2e019ec35"},
920 | {file = "lazy_object_proxy-1.7.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:6a6e94c7b02641d1311228a102607ecd576f70734dc3d5e22610111aeacba8a0"},
921 | {file = "lazy_object_proxy-1.7.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c4ce15276a1a14549d7e81c243b887293904ad2d94ad767f42df91e75fd7b5b6"},
922 | {file = "lazy_object_proxy-1.7.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e368b7f7eac182a59ff1f81d5f3802161932a41dc1b1cc45c1f757dc876b5d2c"},
923 | {file = "lazy_object_proxy-1.7.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:6ecbb350991d6434e1388bee761ece3260e5228952b1f0c46ffc800eb313ff42"},
924 | {file = "lazy_object_proxy-1.7.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:553b0f0d8dbf21890dd66edd771f9b1b5f51bd912fa5f26de4449bfc5af5e029"},
925 | {file = "lazy_object_proxy-1.7.1-cp37-cp37m-win32.whl", hash = "sha256:c7a683c37a8a24f6428c28c561c80d5f4fd316ddcf0c7cab999b15ab3f5c5c69"},
926 | {file = "lazy_object_proxy-1.7.1-cp37-cp37m-win_amd64.whl", hash = "sha256:df2631f9d67259dc9620d831384ed7732a198eb434eadf69aea95ad18c587a28"},
927 | {file = "lazy_object_proxy-1.7.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:07fa44286cda977bd4803b656ffc1c9b7e3bc7dff7d34263446aec8f8c96f88a"},
928 | {file = "lazy_object_proxy-1.7.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4dca6244e4121c74cc20542c2ca39e5c4a5027c81d112bfb893cf0790f96f57e"},
929 | {file = "lazy_object_proxy-1.7.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:91ba172fc5b03978764d1df5144b4ba4ab13290d7bab7a50f12d8117f8630c38"},
930 | {file = "lazy_object_proxy-1.7.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:043651b6cb706eee4f91854da4a089816a6606c1428fd391573ef8cb642ae4f7"},
931 | {file = "lazy_object_proxy-1.7.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b9e89b87c707dd769c4ea91f7a31538888aad05c116a59820f28d59b3ebfe25a"},
932 | {file = "lazy_object_proxy-1.7.1-cp38-cp38-win32.whl", hash = "sha256:9d166602b525bf54ac994cf833c385bfcc341b364e3ee71e3bf5a1336e677b55"},
933 | {file = "lazy_object_proxy-1.7.1-cp38-cp38-win_amd64.whl", hash = "sha256:8f3953eb575b45480db6568306893f0bd9d8dfeeebd46812aa09ca9579595148"},
934 | {file = "lazy_object_proxy-1.7.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:dd7ed7429dbb6c494aa9bc4e09d94b778a3579be699f9d67da7e6804c422d3de"},
935 | {file = "lazy_object_proxy-1.7.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:70ed0c2b380eb6248abdef3cd425fc52f0abd92d2b07ce26359fcbc399f636ad"},
936 | {file = "lazy_object_proxy-1.7.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7096a5e0c1115ec82641afbdd70451a144558ea5cf564a896294e346eb611be1"},
937 | {file = "lazy_object_proxy-1.7.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f769457a639403073968d118bc70110e7dce294688009f5c24ab78800ae56dc8"},
938 | {file = "lazy_object_proxy-1.7.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:39b0e26725c5023757fc1ab2a89ef9d7ab23b84f9251e28f9cc114d5b59c1b09"},
939 | {file = "lazy_object_proxy-1.7.1-cp39-cp39-win32.whl", hash = "sha256:2130db8ed69a48a3440103d4a520b89d8a9405f1b06e2cc81640509e8bf6548f"},
940 | {file = "lazy_object_proxy-1.7.1-cp39-cp39-win_amd64.whl", hash = "sha256:677ea950bef409b47e51e733283544ac3d660b709cfce7b187f5ace137960d61"},
941 | {file = "lazy_object_proxy-1.7.1-pp37.pp38-none-any.whl", hash = "sha256:d66906d5785da8e0be7360912e99c9188b70f52c422f9fc18223347235691a84"},
942 | ]
943 | mccabe = [
944 | {file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"},
945 | {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"},
946 | ]
947 | mypy = [
948 | {file = "mypy-0.961-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:697540876638ce349b01b6786bc6094ccdaba88af446a9abb967293ce6eaa2b0"},
949 | {file = "mypy-0.961-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b117650592e1782819829605a193360a08aa99f1fc23d1d71e1a75a142dc7e15"},
950 | {file = "mypy-0.961-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:bdd5ca340beffb8c44cb9dc26697628d1b88c6bddf5c2f6eb308c46f269bb6f3"},
951 | {file = "mypy-0.961-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3e09f1f983a71d0672bbc97ae33ee3709d10c779beb613febc36805a6e28bb4e"},
952 | {file = "mypy-0.961-cp310-cp310-win_amd64.whl", hash = "sha256:e999229b9f3198c0c880d5e269f9f8129c8862451ce53a011326cad38b9ccd24"},
953 | {file = "mypy-0.961-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:b24be97351084b11582fef18d79004b3e4db572219deee0212078f7cf6352723"},
954 | {file = "mypy-0.961-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f4a21d01fc0ba4e31d82f0fff195682e29f9401a8bdb7173891070eb260aeb3b"},
955 | {file = "mypy-0.961-cp36-cp36m-win_amd64.whl", hash = "sha256:439c726a3b3da7ca84a0199a8ab444cd8896d95012c4a6c4a0d808e3147abf5d"},
956 | {file = "mypy-0.961-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:5a0b53747f713f490affdceef835d8f0cb7285187a6a44c33821b6d1f46ed813"},
957 | {file = "mypy-0.961-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:0e9f70df36405c25cc530a86eeda1e0867863d9471fe76d1273c783df3d35c2e"},
958 | {file = "mypy-0.961-cp37-cp37m-win_amd64.whl", hash = "sha256:b88f784e9e35dcaa075519096dc947a388319cb86811b6af621e3523980f1c8a"},
959 | {file = "mypy-0.961-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:d5aaf1edaa7692490f72bdb9fbd941fbf2e201713523bdb3f4038be0af8846c6"},
960 | {file = "mypy-0.961-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9f5f5a74085d9a81a1f9c78081d60a0040c3efb3f28e5c9912b900adf59a16e6"},
961 | {file = "mypy-0.961-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f4b794db44168a4fc886e3450201365c9526a522c46ba089b55e1f11c163750d"},
962 | {file = "mypy-0.961-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:64759a273d590040a592e0f4186539858c948302c653c2eac840c7a3cd29e51b"},
963 | {file = "mypy-0.961-cp38-cp38-win_amd64.whl", hash = "sha256:63e85a03770ebf403291ec50097954cc5caf2a9205c888ce3a61bd3f82e17569"},
964 | {file = "mypy-0.961-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:5f1332964963d4832a94bebc10f13d3279be3ce8f6c64da563d6ee6e2eeda932"},
965 | {file = "mypy-0.961-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:006be38474216b833eca29ff6b73e143386f352e10e9c2fbe76aa8549e5554f5"},
966 | {file = "mypy-0.961-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9940e6916ed9371809b35b2154baf1f684acba935cd09928952310fbddaba648"},
967 | {file = "mypy-0.961-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:a5ea0875a049de1b63b972456542f04643daf320d27dc592d7c3d9cd5d9bf950"},
968 | {file = "mypy-0.961-cp39-cp39-win_amd64.whl", hash = "sha256:1ece702f29270ec6af25db8cf6185c04c02311c6bb21a69f423d40e527b75c56"},
969 | {file = "mypy-0.961-py3-none-any.whl", hash = "sha256:03c6cc893e7563e7b2949b969e63f02c000b32502a1b4d1314cabe391aa87d66"},
970 | {file = "mypy-0.961.tar.gz", hash = "sha256:f730d56cb924d371c26b8eaddeea3cc07d78ff51c521c6d04899ac6904b75492"},
971 | ]
972 | mypy-extensions = [
973 | {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"},
974 | {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"},
975 | ]
976 | nodeenv = [
977 | {file = "nodeenv-1.7.0-py2.py3-none-any.whl", hash = "sha256:27083a7b96a25f2f5e1d8cb4b6317ee8aeda3bdd121394e5ac54e498028a042e"},
978 | {file = "nodeenv-1.7.0.tar.gz", hash = "sha256:e0e7f7dfb85fc5394c6fe1e8fa98131a2473e04311a45afb6508f7cf1836fa2b"},
979 | ]
980 | packaging = [
981 | {file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"},
982 | {file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"},
983 | ]
984 | pathspec = [
985 | {file = "pathspec-0.9.0-py2.py3-none-any.whl", hash = "sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a"},
986 | {file = "pathspec-0.9.0.tar.gz", hash = "sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1"},
987 | ]
988 | pbr = [
989 | {file = "pbr-5.9.0-py2.py3-none-any.whl", hash = "sha256:e547125940bcc052856ded43be8e101f63828c2d94239ffbe2b327ba3d5ccf0a"},
990 | {file = "pbr-5.9.0.tar.gz", hash = "sha256:e8dca2f4b43560edef58813969f52a56cef023146cbb8931626db80e6c1c4308"},
991 | ]
992 | platformdirs = [
993 | {file = "platformdirs-2.5.2-py3-none-any.whl", hash = "sha256:027d8e83a2d7de06bbac4e5ef7e023c02b863d7ea5d079477e722bb41ab25788"},
994 | {file = "platformdirs-2.5.2.tar.gz", hash = "sha256:58c8abb07dcb441e6ee4b11d8df0ac856038f944ab98b7be6b27b2a3c7feef19"},
995 | ]
996 | pluggy = [
997 | {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"},
998 | {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"},
999 | ]
1000 | pre-commit = []
1001 | py = [
1002 | {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"},
1003 | {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"},
1004 | ]
1005 | pydantic = [
1006 | {file = "pydantic-1.9.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c8098a724c2784bf03e8070993f6d46aa2eeca031f8d8a048dff277703e6e193"},
1007 | {file = "pydantic-1.9.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c320c64dd876e45254bdd350f0179da737463eea41c43bacbee9d8c9d1021f11"},
1008 | {file = "pydantic-1.9.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18f3e912f9ad1bdec27fb06b8198a2ccc32f201e24174cec1b3424dda605a310"},
1009 | {file = "pydantic-1.9.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c11951b404e08b01b151222a1cb1a9f0a860a8153ce8334149ab9199cd198131"},
1010 | {file = "pydantic-1.9.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:8bc541a405423ce0e51c19f637050acdbdf8feca34150e0d17f675e72d119580"},
1011 | {file = "pydantic-1.9.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:e565a785233c2d03724c4dc55464559639b1ba9ecf091288dd47ad9c629433bd"},
1012 | {file = "pydantic-1.9.1-cp310-cp310-win_amd64.whl", hash = "sha256:a4a88dcd6ff8fd47c18b3a3709a89adb39a6373f4482e04c1b765045c7e282fd"},
1013 | {file = "pydantic-1.9.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:447d5521575f18e18240906beadc58551e97ec98142266e521c34968c76c8761"},
1014 | {file = "pydantic-1.9.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:985ceb5d0a86fcaa61e45781e567a59baa0da292d5ed2e490d612d0de5796918"},
1015 | {file = "pydantic-1.9.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:059b6c1795170809103a1538255883e1983e5b831faea6558ef873d4955b4a74"},
1016 | {file = "pydantic-1.9.1-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:d12f96b5b64bec3f43c8e82b4aab7599d0157f11c798c9f9c528a72b9e0b339a"},
1017 | {file = "pydantic-1.9.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:ae72f8098acb368d877b210ebe02ba12585e77bd0db78ac04a1ee9b9f5dd2166"},
1018 | {file = "pydantic-1.9.1-cp36-cp36m-win_amd64.whl", hash = "sha256:79b485767c13788ee314669008d01f9ef3bc05db9ea3298f6a50d3ef596a154b"},
1019 | {file = "pydantic-1.9.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:494f7c8537f0c02b740c229af4cb47c0d39840b829ecdcfc93d91dcbb0779892"},
1020 | {file = "pydantic-1.9.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f0f047e11febe5c3198ed346b507e1d010330d56ad615a7e0a89fae604065a0e"},
1021 | {file = "pydantic-1.9.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:969dd06110cb780da01336b281f53e2e7eb3a482831df441fb65dd30403f4608"},
1022 | {file = "pydantic-1.9.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:177071dfc0df6248fd22b43036f936cfe2508077a72af0933d0c1fa269b18537"},
1023 | {file = "pydantic-1.9.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:9bcf8b6e011be08fb729d110f3e22e654a50f8a826b0575c7196616780683380"},
1024 | {file = "pydantic-1.9.1-cp37-cp37m-win_amd64.whl", hash = "sha256:a955260d47f03df08acf45689bd163ed9df82c0e0124beb4251b1290fa7ae728"},
1025 | {file = "pydantic-1.9.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9ce157d979f742a915b75f792dbd6aa63b8eccaf46a1005ba03aa8a986bde34a"},
1026 | {file = "pydantic-1.9.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:0bf07cab5b279859c253d26a9194a8906e6f4a210063b84b433cf90a569de0c1"},
1027 | {file = "pydantic-1.9.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d93d4e95eacd313d2c765ebe40d49ca9dd2ed90e5b37d0d421c597af830c195"},
1028 | {file = "pydantic-1.9.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1542636a39c4892c4f4fa6270696902acb186a9aaeac6f6cf92ce6ae2e88564b"},
1029 | {file = "pydantic-1.9.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a9af62e9b5b9bc67b2a195ebc2c2662fdf498a822d62f902bf27cccb52dbbf49"},
1030 | {file = "pydantic-1.9.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:fe4670cb32ea98ffbf5a1262f14c3e102cccd92b1869df3bb09538158ba90fe6"},
1031 | {file = "pydantic-1.9.1-cp38-cp38-win_amd64.whl", hash = "sha256:9f659a5ee95c8baa2436d392267988fd0f43eb774e5eb8739252e5a7e9cf07e0"},
1032 | {file = "pydantic-1.9.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b83ba3825bc91dfa989d4eed76865e71aea3a6ca1388b59fc801ee04c4d8d0d6"},
1033 | {file = "pydantic-1.9.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1dd8fecbad028cd89d04a46688d2fcc14423e8a196d5b0a5c65105664901f810"},
1034 | {file = "pydantic-1.9.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:02eefd7087268b711a3ff4db528e9916ac9aa18616da7bca69c1871d0b7a091f"},
1035 | {file = "pydantic-1.9.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7eb57ba90929bac0b6cc2af2373893d80ac559adda6933e562dcfb375029acee"},
1036 | {file = "pydantic-1.9.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:4ce9ae9e91f46c344bec3b03d6ee9612802682c1551aaf627ad24045ce090761"},
1037 | {file = "pydantic-1.9.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:72ccb318bf0c9ab97fc04c10c37683d9eea952ed526707fabf9ac5ae59b701fd"},
1038 | {file = "pydantic-1.9.1-cp39-cp39-win_amd64.whl", hash = "sha256:61b6760b08b7c395975d893e0b814a11cf011ebb24f7d869e7118f5a339a82e1"},
1039 | {file = "pydantic-1.9.1-py3-none-any.whl", hash = "sha256:4988c0f13c42bfa9ddd2fe2f569c9d54646ce84adc5de84228cfe83396f3bd58"},
1040 | {file = "pydantic-1.9.1.tar.gz", hash = "sha256:1ed987c3ff29fff7fd8c3ea3a3ea877ad310aae2ef9889a119e22d3f2db0691a"},
1041 | ]
1042 | pydocstyle = [
1043 | {file = "pydocstyle-6.1.1-py3-none-any.whl", hash = "sha256:6987826d6775056839940041beef5c08cc7e3d71d63149b48e36727f70144dc4"},
1044 | {file = "pydocstyle-6.1.1.tar.gz", hash = "sha256:1d41b7c459ba0ee6c345f2eb9ae827cab14a7533a88c5c6f7e94923f72df92dc"},
1045 | ]
1046 | pylint = [
1047 | {file = "pylint-2.13.9-py3-none-any.whl", hash = "sha256:705c620d388035bdd9ff8b44c5bcdd235bfb49d276d488dd2c8ff1736aa42526"},
1048 | {file = "pylint-2.13.9.tar.gz", hash = "sha256:095567c96e19e6f57b5b907e67d265ff535e588fe26b12b5ebe1fc5645b2c731"},
1049 | ]
1050 | pyparsing = [
1051 | {file = "pyparsing-3.0.9-py3-none-any.whl", hash = "sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc"},
1052 | {file = "pyparsing-3.0.9.tar.gz", hash = "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb"},
1053 | ]
1054 | pytest = [
1055 | {file = "pytest-7.1.2-py3-none-any.whl", hash = "sha256:13d0e3ccfc2b6e26be000cb6568c832ba67ba32e719443bfe725814d3c42433c"},
1056 | {file = "pytest-7.1.2.tar.gz", hash = "sha256:a06a0425453864a270bc45e71f783330a7428defb4230fb5e6a731fde06ecd45"},
1057 | ]
1058 | pytest-cov = [
1059 | {file = "pytest-cov-3.0.0.tar.gz", hash = "sha256:e7f0f5b1617d2210a2cabc266dfe2f4c75a8d32fb89eafb7ad9d06f6d076d470"},
1060 | {file = "pytest_cov-3.0.0-py3-none-any.whl", hash = "sha256:578d5d15ac4a25e5f961c938b85a05b09fdaae9deef3bb6de9a6e766622ca7a6"},
1061 | ]
1062 | pytest-html = [
1063 | {file = "pytest-html-3.1.1.tar.gz", hash = "sha256:3ee1cf319c913d19fe53aeb0bc400e7b0bc2dbeb477553733db1dad12eb75ee3"},
1064 | {file = "pytest_html-3.1.1-py3-none-any.whl", hash = "sha256:b7f82f123936a3f4d2950bc993c2c1ca09ce262c9ae12f9ac763a2401380b455"},
1065 | ]
1066 | pytest-metadata = []
1067 | pyupgrade = []
1068 | pyyaml = [
1069 | {file = "PyYAML-6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53"},
1070 | {file = "PyYAML-6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c"},
1071 | {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc"},
1072 | {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b"},
1073 | {file = "PyYAML-6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5"},
1074 | {file = "PyYAML-6.0-cp310-cp310-win32.whl", hash = "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513"},
1075 | {file = "PyYAML-6.0-cp310-cp310-win_amd64.whl", hash = "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a"},
1076 | {file = "PyYAML-6.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86"},
1077 | {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f"},
1078 | {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92"},
1079 | {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4"},
1080 | {file = "PyYAML-6.0-cp36-cp36m-win32.whl", hash = "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293"},
1081 | {file = "PyYAML-6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57"},
1082 | {file = "PyYAML-6.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c"},
1083 | {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0"},
1084 | {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4"},
1085 | {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9"},
1086 | {file = "PyYAML-6.0-cp37-cp37m-win32.whl", hash = "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737"},
1087 | {file = "PyYAML-6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d"},
1088 | {file = "PyYAML-6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b"},
1089 | {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba"},
1090 | {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34"},
1091 | {file = "PyYAML-6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287"},
1092 | {file = "PyYAML-6.0-cp38-cp38-win32.whl", hash = "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78"},
1093 | {file = "PyYAML-6.0-cp38-cp38-win_amd64.whl", hash = "sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07"},
1094 | {file = "PyYAML-6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b"},
1095 | {file = "PyYAML-6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174"},
1096 | {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803"},
1097 | {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3"},
1098 | {file = "PyYAML-6.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0"},
1099 | {file = "PyYAML-6.0-cp39-cp39-win32.whl", hash = "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb"},
1100 | {file = "PyYAML-6.0-cp39-cp39-win_amd64.whl", hash = "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c"},
1101 | {file = "PyYAML-6.0.tar.gz", hash = "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2"},
1102 | ]
1103 | requests = [
1104 | {file = "requests-2.28.1-py3-none-any.whl", hash = "sha256:8fefa2a1a1365bf5520aac41836fbee479da67864514bdb821f31ce07ce65349"},
1105 | {file = "requests-2.28.1.tar.gz", hash = "sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983"},
1106 | ]
1107 | "ruamel.yaml" = [
1108 | {file = "ruamel.yaml-0.17.21-py3-none-any.whl", hash = "sha256:742b35d3d665023981bd6d16b3d24248ce5df75fdb4e2924e93a05c1f8b61ca7"},
1109 | {file = "ruamel.yaml-0.17.21.tar.gz", hash = "sha256:8b7ce697a2f212752a35c1ac414471dc16c424c9573be4926b56ff3f5d23b7af"},
1110 | ]
1111 | "ruamel.yaml.clib" = [
1112 | {file = "ruamel.yaml.clib-0.2.6-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:6e7be2c5bcb297f5b82fee9c665eb2eb7001d1050deaba8471842979293a80b0"},
1113 | {file = "ruamel.yaml.clib-0.2.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:221eca6f35076c6ae472a531afa1c223b9c29377e62936f61bc8e6e8bdc5f9e7"},
1114 | {file = "ruamel.yaml.clib-0.2.6-cp310-cp310-win32.whl", hash = "sha256:1070ba9dd7f9370d0513d649420c3b362ac2d687fe78c6e888f5b12bf8bc7bee"},
1115 | {file = "ruamel.yaml.clib-0.2.6-cp310-cp310-win_amd64.whl", hash = "sha256:77df077d32921ad46f34816a9a16e6356d8100374579bc35e15bab5d4e9377de"},
1116 | {file = "ruamel.yaml.clib-0.2.6-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:cfdb9389d888c5b74af297e51ce357b800dd844898af9d4a547ffc143fa56751"},
1117 | {file = "ruamel.yaml.clib-0.2.6-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:7b2927e92feb51d830f531de4ccb11b320255ee95e791022555971c466af4527"},
1118 | {file = "ruamel.yaml.clib-0.2.6-cp35-cp35m-win32.whl", hash = "sha256:ada3f400d9923a190ea8b59c8f60680c4ef8a4b0dfae134d2f2ff68429adfab5"},
1119 | {file = "ruamel.yaml.clib-0.2.6-cp35-cp35m-win_amd64.whl", hash = "sha256:de9c6b8a1ba52919ae919f3ae96abb72b994dd0350226e28f3686cb4f142165c"},
1120 | {file = "ruamel.yaml.clib-0.2.6-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:d67f273097c368265a7b81e152e07fb90ed395df6e552b9fa858c6d2c9f42502"},
1121 | {file = "ruamel.yaml.clib-0.2.6-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:72a2b8b2ff0a627496aad76f37a652bcef400fd861721744201ef1b45199ab78"},
1122 | {file = "ruamel.yaml.clib-0.2.6-cp36-cp36m-win32.whl", hash = "sha256:9efef4aab5353387b07f6b22ace0867032b900d8e91674b5d8ea9150db5cae94"},
1123 | {file = "ruamel.yaml.clib-0.2.6-cp36-cp36m-win_amd64.whl", hash = "sha256:846fc8336443106fe23f9b6d6b8c14a53d38cef9a375149d61f99d78782ea468"},
1124 | {file = "ruamel.yaml.clib-0.2.6-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0847201b767447fc33b9c235780d3aa90357d20dd6108b92be544427bea197dd"},
1125 | {file = "ruamel.yaml.clib-0.2.6-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:78988ed190206672da0f5d50c61afef8f67daa718d614377dcd5e3ed85ab4a99"},
1126 | {file = "ruamel.yaml.clib-0.2.6-cp37-cp37m-win32.whl", hash = "sha256:a49e0161897901d1ac9c4a79984b8410f450565bbad64dbfcbf76152743a0cdb"},
1127 | {file = "ruamel.yaml.clib-0.2.6-cp37-cp37m-win_amd64.whl", hash = "sha256:bf75d28fa071645c529b5474a550a44686821decebdd00e21127ef1fd566eabe"},
1128 | {file = "ruamel.yaml.clib-0.2.6-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a32f8d81ea0c6173ab1b3da956869114cae53ba1e9f72374032e33ba3118c233"},
1129 | {file = "ruamel.yaml.clib-0.2.6-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7f7ecb53ae6848f959db6ae93bdff1740e651809780822270eab111500842a84"},
1130 | {file = "ruamel.yaml.clib-0.2.6-cp38-cp38-win32.whl", hash = "sha256:89221ec6d6026f8ae859c09b9718799fea22c0e8da8b766b0b2c9a9ba2db326b"},
1131 | {file = "ruamel.yaml.clib-0.2.6-cp38-cp38-win_amd64.whl", hash = "sha256:31ea73e564a7b5fbbe8188ab8b334393e06d997914a4e184975348f204790277"},
1132 | {file = "ruamel.yaml.clib-0.2.6-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:dc6a613d6c74eef5a14a214d433d06291526145431c3b964f5e16529b1842bed"},
1133 | {file = "ruamel.yaml.clib-0.2.6-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:1866cf2c284a03b9524a5cc00daca56d80057c5ce3cdc86a52020f4c720856f0"},
1134 | {file = "ruamel.yaml.clib-0.2.6-cp39-cp39-win32.whl", hash = "sha256:3fb9575a5acd13031c57a62cc7823e5d2ff8bc3835ba4d94b921b4e6ee664104"},
1135 | {file = "ruamel.yaml.clib-0.2.6-cp39-cp39-win_amd64.whl", hash = "sha256:825d5fccef6da42f3c8eccd4281af399f21c02b32d98e113dbc631ea6a6ecbc7"},
1136 | {file = "ruamel.yaml.clib-0.2.6.tar.gz", hash = "sha256:4ff604ce439abb20794f05613c374759ce10e3595d1867764dd1ae675b85acbd"},
1137 | ]
1138 | safety = []
1139 | smmap = [
1140 | {file = "smmap-5.0.0-py3-none-any.whl", hash = "sha256:2aba19d6a040e78d8b09de5c57e96207b09ed71d8e55ce0959eeee6c8e190d94"},
1141 | {file = "smmap-5.0.0.tar.gz", hash = "sha256:c840e62059cd3be204b0c9c9f74be2c09d5648eddd4580d9314c3ecde0b30936"},
1142 | ]
1143 | sniffio = [
1144 | {file = "sniffio-1.2.0-py3-none-any.whl", hash = "sha256:471b71698eac1c2112a40ce2752bb2f4a4814c22a54a3eed3676bc0f5ca9f663"},
1145 | {file = "sniffio-1.2.0.tar.gz", hash = "sha256:c4666eecec1d3f50960c6bdf61ab7bc350648da6c126e3cf6898d8cd4ddcd3de"},
1146 | ]
1147 | snowballstemmer = [
1148 | {file = "snowballstemmer-2.2.0-py2.py3-none-any.whl", hash = "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a"},
1149 | {file = "snowballstemmer-2.2.0.tar.gz", hash = "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1"},
1150 | ]
1151 | starlette = [
1152 | {file = "starlette-0.19.1-py3-none-any.whl", hash = "sha256:5a60c5c2d051f3a8eb546136aa0c9399773a689595e099e0877704d5888279bf"},
1153 | {file = "starlette-0.19.1.tar.gz", hash = "sha256:c6d21096774ecb9639acad41b86b7706e52ba3bf1dc13ea4ed9ad593d47e24c7"},
1154 | ]
1155 | stevedore = [
1156 | {file = "stevedore-3.5.0-py3-none-any.whl", hash = "sha256:a547de73308fd7e90075bb4d301405bebf705292fa90a90fc3bcf9133f58616c"},
1157 | {file = "stevedore-3.5.0.tar.gz", hash = "sha256:f40253887d8712eaa2bb0ea3830374416736dc8ec0e22f5a65092c1174c44335"},
1158 | ]
1159 | tokenize-rt = [
1160 | {file = "tokenize_rt-4.2.1-py2.py3-none-any.whl", hash = "sha256:08a27fa032a81cf45e8858d0ac706004fcd523e8463415ddf1442be38e204ea8"},
1161 | {file = "tokenize_rt-4.2.1.tar.gz", hash = "sha256:0d4f69026fed520f8a1e0103aa36c406ef4661417f20ca643f913e33531b3b94"},
1162 | ]
1163 | toml = [
1164 | {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"},
1165 | {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"},
1166 | ]
1167 | tomli = [
1168 | {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"},
1169 | {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"},
1170 | ]
1171 | typed-ast = [
1172 | {file = "typed_ast-1.5.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:669dd0c4167f6f2cd9f57041e03c3c2ebf9063d0757dc89f79ba1daa2bfca9d4"},
1173 | {file = "typed_ast-1.5.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:211260621ab1cd7324e0798d6be953d00b74e0428382991adfddb352252f1d62"},
1174 | {file = "typed_ast-1.5.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:267e3f78697a6c00c689c03db4876dd1efdfea2f251a5ad6555e82a26847b4ac"},
1175 | {file = "typed_ast-1.5.4-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:c542eeda69212fa10a7ada75e668876fdec5f856cd3d06829e6aa64ad17c8dfe"},
1176 | {file = "typed_ast-1.5.4-cp310-cp310-win_amd64.whl", hash = "sha256:a9916d2bb8865f973824fb47436fa45e1ebf2efd920f2b9f99342cb7fab93f72"},
1177 | {file = "typed_ast-1.5.4-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:79b1e0869db7c830ba6a981d58711c88b6677506e648496b1f64ac7d15633aec"},
1178 | {file = "typed_ast-1.5.4-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a94d55d142c9265f4ea46fab70977a1944ecae359ae867397757d836ea5a3f47"},
1179 | {file = "typed_ast-1.5.4-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:183afdf0ec5b1b211724dfef3d2cad2d767cbefac291f24d69b00546c1837fb6"},
1180 | {file = "typed_ast-1.5.4-cp36-cp36m-win_amd64.whl", hash = "sha256:639c5f0b21776605dd6c9dbe592d5228f021404dafd377e2b7ac046b0349b1a1"},
1181 | {file = "typed_ast-1.5.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:cf4afcfac006ece570e32d6fa90ab74a17245b83dfd6655a6f68568098345ff6"},
1182 | {file = "typed_ast-1.5.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ed855bbe3eb3715fca349c80174cfcfd699c2f9de574d40527b8429acae23a66"},
1183 | {file = "typed_ast-1.5.4-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:6778e1b2f81dfc7bc58e4b259363b83d2e509a65198e85d5700dfae4c6c8ff1c"},
1184 | {file = "typed_ast-1.5.4-cp37-cp37m-win_amd64.whl", hash = "sha256:0261195c2062caf107831e92a76764c81227dae162c4f75192c0d489faf751a2"},
1185 | {file = "typed_ast-1.5.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2efae9db7a8c05ad5547d522e7dbe62c83d838d3906a3716d1478b6c1d61388d"},
1186 | {file = "typed_ast-1.5.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7d5d014b7daa8b0bf2eaef684295acae12b036d79f54178b92a2b6a56f92278f"},
1187 | {file = "typed_ast-1.5.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:370788a63915e82fd6f212865a596a0fefcbb7d408bbbb13dea723d971ed8bdc"},
1188 | {file = "typed_ast-1.5.4-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:4e964b4ff86550a7a7d56345c7864b18f403f5bd7380edf44a3c1fb4ee7ac6c6"},
1189 | {file = "typed_ast-1.5.4-cp38-cp38-win_amd64.whl", hash = "sha256:683407d92dc953c8a7347119596f0b0e6c55eb98ebebd9b23437501b28dcbb8e"},
1190 | {file = "typed_ast-1.5.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4879da6c9b73443f97e731b617184a596ac1235fe91f98d279a7af36c796da35"},
1191 | {file = "typed_ast-1.5.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3e123d878ba170397916557d31c8f589951e353cc95fb7f24f6bb69adc1a8a97"},
1192 | {file = "typed_ast-1.5.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ebd9d7f80ccf7a82ac5f88c521115cc55d84e35bf8b446fcd7836eb6b98929a3"},
1193 | {file = "typed_ast-1.5.4-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98f80dee3c03455e92796b58b98ff6ca0b2a6f652120c263efdba4d6c5e58f72"},
1194 | {file = "typed_ast-1.5.4-cp39-cp39-win_amd64.whl", hash = "sha256:0fdbcf2fef0ca421a3f5912555804296f0b0960f0418c440f5d6d3abb549f3e1"},
1195 | {file = "typed_ast-1.5.4.tar.gz", hash = "sha256:39e21ceb7388e4bb37f4c679d72707ed46c2fbf2a5609b8b8ebc4b067d977df2"},
1196 | ]
1197 | typing-extensions = [
1198 | {file = "typing_extensions-4.3.0-py3-none-any.whl", hash = "sha256:25642c956049920a5aa49edcdd6ab1e06d7e5d467fc00e0506c44ac86fbfca02"},
1199 | {file = "typing_extensions-4.3.0.tar.gz", hash = "sha256:e6d2677a32f47fc7eb2795db1dd15c1f34eff616bcaf2cfb5e997f854fa1c4a6"},
1200 | ]
1201 | urllib3 = []
1202 | virtualenv = []
1203 | wrapt = [
1204 | {file = "wrapt-1.14.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:1b376b3f4896e7930f1f772ac4b064ac12598d1c38d04907e696cc4d794b43d3"},
1205 | {file = "wrapt-1.14.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:903500616422a40a98a5a3c4ff4ed9d0066f3b4c951fa286018ecdf0750194ef"},
1206 | {file = "wrapt-1.14.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:5a9a0d155deafd9448baff28c08e150d9b24ff010e899311ddd63c45c2445e28"},
1207 | {file = "wrapt-1.14.1-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:ddaea91abf8b0d13443f6dac52e89051a5063c7d014710dcb4d4abb2ff811a59"},
1208 | {file = "wrapt-1.14.1-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:36f582d0c6bc99d5f39cd3ac2a9062e57f3cf606ade29a0a0d6b323462f4dd87"},
1209 | {file = "wrapt-1.14.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:7ef58fb89674095bfc57c4069e95d7a31cfdc0939e2a579882ac7d55aadfd2a1"},
1210 | {file = "wrapt-1.14.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:e2f83e18fe2f4c9e7db597e988f72712c0c3676d337d8b101f6758107c42425b"},
1211 | {file = "wrapt-1.14.1-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:ee2b1b1769f6707a8a445162ea16dddf74285c3964f605877a20e38545c3c462"},
1212 | {file = "wrapt-1.14.1-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:833b58d5d0b7e5b9832869f039203389ac7cbf01765639c7309fd50ef619e0b1"},
1213 | {file = "wrapt-1.14.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:80bb5c256f1415f747011dc3604b59bc1f91c6e7150bd7db03b19170ee06b320"},
1214 | {file = "wrapt-1.14.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:07f7a7d0f388028b2df1d916e94bbb40624c59b48ecc6cbc232546706fac74c2"},
1215 | {file = "wrapt-1.14.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:02b41b633c6261feff8ddd8d11c711df6842aba629fdd3da10249a53211a72c4"},
1216 | {file = "wrapt-1.14.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2fe803deacd09a233e4762a1adcea5db5d31e6be577a43352936179d14d90069"},
1217 | {file = "wrapt-1.14.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:257fd78c513e0fb5cdbe058c27a0624c9884e735bbd131935fd49e9fe719d310"},
1218 | {file = "wrapt-1.14.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4fcc4649dc762cddacd193e6b55bc02edca674067f5f98166d7713b193932b7f"},
1219 | {file = "wrapt-1.14.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:11871514607b15cfeb87c547a49bca19fde402f32e2b1c24a632506c0a756656"},
1220 | {file = "wrapt-1.14.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8ad85f7f4e20964db4daadcab70b47ab05c7c1cf2a7c1e51087bfaa83831854c"},
1221 | {file = "wrapt-1.14.1-cp310-cp310-win32.whl", hash = "sha256:a9a52172be0b5aae932bef82a79ec0a0ce87288c7d132946d645eba03f0ad8a8"},
1222 | {file = "wrapt-1.14.1-cp310-cp310-win_amd64.whl", hash = "sha256:6d323e1554b3d22cfc03cd3243b5bb815a51f5249fdcbb86fda4bf62bab9e164"},
1223 | {file = "wrapt-1.14.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:43ca3bbbe97af00f49efb06e352eae40434ca9d915906f77def219b88e85d907"},
1224 | {file = "wrapt-1.14.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:6b1a564e6cb69922c7fe3a678b9f9a3c54e72b469875aa8018f18b4d1dd1adf3"},
1225 | {file = "wrapt-1.14.1-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:00b6d4ea20a906c0ca56d84f93065b398ab74b927a7a3dbd470f6fc503f95dc3"},
1226 | {file = "wrapt-1.14.1-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:a85d2b46be66a71bedde836d9e41859879cc54a2a04fad1191eb50c2066f6e9d"},
1227 | {file = "wrapt-1.14.1-cp35-cp35m-win32.whl", hash = "sha256:dbcda74c67263139358f4d188ae5faae95c30929281bc6866d00573783c422b7"},
1228 | {file = "wrapt-1.14.1-cp35-cp35m-win_amd64.whl", hash = "sha256:b21bb4c09ffabfa0e85e3a6b623e19b80e7acd709b9f91452b8297ace2a8ab00"},
1229 | {file = "wrapt-1.14.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:9e0fd32e0148dd5dea6af5fee42beb949098564cc23211a88d799e434255a1f4"},
1230 | {file = "wrapt-1.14.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9736af4641846491aedb3c3f56b9bc5568d92b0692303b5a305301a95dfd38b1"},
1231 | {file = "wrapt-1.14.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5b02d65b9ccf0ef6c34cba6cf5bf2aab1bb2f49c6090bafeecc9cd81ad4ea1c1"},
1232 | {file = "wrapt-1.14.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21ac0156c4b089b330b7666db40feee30a5d52634cc4560e1905d6529a3897ff"},
1233 | {file = "wrapt-1.14.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:9f3e6f9e05148ff90002b884fbc2a86bd303ae847e472f44ecc06c2cd2fcdb2d"},
1234 | {file = "wrapt-1.14.1-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:6e743de5e9c3d1b7185870f480587b75b1cb604832e380d64f9504a0535912d1"},
1235 | {file = "wrapt-1.14.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:d79d7d5dc8a32b7093e81e97dad755127ff77bcc899e845f41bf71747af0c569"},
1236 | {file = "wrapt-1.14.1-cp36-cp36m-win32.whl", hash = "sha256:81b19725065dcb43df02b37e03278c011a09e49757287dca60c5aecdd5a0b8ed"},
1237 | {file = "wrapt-1.14.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b014c23646a467558be7da3d6b9fa409b2c567d2110599b7cf9a0c5992b3b471"},
1238 | {file = "wrapt-1.14.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:88bd7b6bd70a5b6803c1abf6bca012f7ed963e58c68d76ee20b9d751c74a3248"},
1239 | {file = "wrapt-1.14.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b5901a312f4d14c59918c221323068fad0540e34324925c8475263841dbdfe68"},
1240 | {file = "wrapt-1.14.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d77c85fedff92cf788face9bfa3ebaa364448ebb1d765302e9af11bf449ca36d"},
1241 | {file = "wrapt-1.14.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d649d616e5c6a678b26d15ece345354f7c2286acd6db868e65fcc5ff7c24a77"},
1242 | {file = "wrapt-1.14.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:7d2872609603cb35ca513d7404a94d6d608fc13211563571117046c9d2bcc3d7"},
1243 | {file = "wrapt-1.14.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:ee6acae74a2b91865910eef5e7de37dc6895ad96fa23603d1d27ea69df545015"},
1244 | {file = "wrapt-1.14.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:2b39d38039a1fdad98c87279b48bc5dce2c0ca0d73483b12cb72aa9609278e8a"},
1245 | {file = "wrapt-1.14.1-cp37-cp37m-win32.whl", hash = "sha256:60db23fa423575eeb65ea430cee741acb7c26a1365d103f7b0f6ec412b893853"},
1246 | {file = "wrapt-1.14.1-cp37-cp37m-win_amd64.whl", hash = "sha256:709fe01086a55cf79d20f741f39325018f4df051ef39fe921b1ebe780a66184c"},
1247 | {file = "wrapt-1.14.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8c0ce1e99116d5ab21355d8ebe53d9460366704ea38ae4d9f6933188f327b456"},
1248 | {file = "wrapt-1.14.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:e3fb1677c720409d5f671e39bac6c9e0e422584e5f518bfd50aa4cbbea02433f"},
1249 | {file = "wrapt-1.14.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:642c2e7a804fcf18c222e1060df25fc210b9c58db7c91416fb055897fc27e8cc"},
1250 | {file = "wrapt-1.14.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7b7c050ae976e286906dd3f26009e117eb000fb2cf3533398c5ad9ccc86867b1"},
1251 | {file = "wrapt-1.14.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ef3f72c9666bba2bab70d2a8b79f2c6d2c1a42a7f7e2b0ec83bb2f9e383950af"},
1252 | {file = "wrapt-1.14.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:01c205616a89d09827986bc4e859bcabd64f5a0662a7fe95e0d359424e0e071b"},
1253 | {file = "wrapt-1.14.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:5a0f54ce2c092aaf439813735584b9537cad479575a09892b8352fea5e988dc0"},
1254 | {file = "wrapt-1.14.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2cf71233a0ed05ccdabe209c606fe0bac7379fdcf687f39b944420d2a09fdb57"},
1255 | {file = "wrapt-1.14.1-cp38-cp38-win32.whl", hash = "sha256:aa31fdcc33fef9eb2552cbcbfee7773d5a6792c137b359e82879c101e98584c5"},
1256 | {file = "wrapt-1.14.1-cp38-cp38-win_amd64.whl", hash = "sha256:d1967f46ea8f2db647c786e78d8cc7e4313dbd1b0aca360592d8027b8508e24d"},
1257 | {file = "wrapt-1.14.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3232822c7d98d23895ccc443bbdf57c7412c5a65996c30442ebe6ed3df335383"},
1258 | {file = "wrapt-1.14.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:988635d122aaf2bdcef9e795435662bcd65b02f4f4c1ae37fbee7401c440b3a7"},
1259 | {file = "wrapt-1.14.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cca3c2cdadb362116235fdbd411735de4328c61425b0aa9f872fd76d02c4e86"},
1260 | {file = "wrapt-1.14.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d52a25136894c63de15a35bc0bdc5adb4b0e173b9c0d07a2be9d3ca64a332735"},
1261 | {file = "wrapt-1.14.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40e7bc81c9e2b2734ea4bc1aceb8a8f0ceaac7c5299bc5d69e37c44d9081d43b"},
1262 | {file = "wrapt-1.14.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b9b7a708dd92306328117d8c4b62e2194d00c365f18eff11a9b53c6f923b01e3"},
1263 | {file = "wrapt-1.14.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:6a9a25751acb379b466ff6be78a315e2b439d4c94c1e99cb7266d40a537995d3"},
1264 | {file = "wrapt-1.14.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:34aa51c45f28ba7f12accd624225e2b1e5a3a45206aa191f6f9aac931d9d56fe"},
1265 | {file = "wrapt-1.14.1-cp39-cp39-win32.whl", hash = "sha256:dee0ce50c6a2dd9056c20db781e9c1cfd33e77d2d569f5d1d9321c641bb903d5"},
1266 | {file = "wrapt-1.14.1-cp39-cp39-win_amd64.whl", hash = "sha256:dee60e1de1898bde3b238f18340eec6148986da0455d8ba7848d50470a7a32fb"},
1267 | {file = "wrapt-1.14.1.tar.gz", hash = "sha256:380a85cf89e0e69b7cfbe2ea9f765f004ff419f34194018a6827ac0e3edfed4d"},
1268 | ]
1269 | zipp = []
1270 |
--------------------------------------------------------------------------------
/pyproject.toml:
--------------------------------------------------------------------------------
1 | # Poetry pyproject.toml: https://python-poetry.org/docs/pyproject/
2 | [build-system]
3 | requires = ["poetry_core>=1.0.0"]
4 | build-backend = "poetry.core.masonry.api"
5 |
6 | [tool.poetry]
7 | name = "pytest-fastapi-deps"
8 | version = "0.2.3"
9 | description = "A fixture which allows easy replacement of fastapi dependencies for testing"
10 | readme = "README.md"
11 | authors = ["Peter Kogan "]
12 | license = "MIT"
13 | repository = "https://github.com/pksol/pytest-fastapi-deps"
14 | homepage = "https://github.com/pksol/pytest-fastapi-deps"
15 |
16 | # Keywords description https://python-poetry.org/docs/pyproject/#keywords
17 | keywords = [
18 | "pytest",
19 | "fastapi",
20 | "dependencies",
21 | "testing",
22 | "fixtures",
23 | ]
24 |
25 | # Pypi classifiers: https://pypi.org/classifiers/
26 | classifiers = [
27 | "Programming Language :: Python",
28 | "Programming Language :: Python :: 3",
29 | "Programming Language :: Python :: 3.7",
30 | "Programming Language :: Python :: 3.8",
31 | "Programming Language :: Python :: 3.9",
32 | "Programming Language :: Python :: 3.10",
33 | "Topic :: Software Development :: Testing",
34 | "Framework :: Pytest",
35 | "License :: OSI Approved :: MIT License",
36 | "Development Status :: 5 - Production/Stable",
37 | "Intended Audience :: Developers",
38 | "Operating System :: OS Independent",
39 | ]
40 |
41 | [tool.poetry.plugins.pytest11]
42 | pytest_fastapi_deps = "pytest_fastapi_deps"
43 |
44 | [tool.poetry.dependencies]
45 | python = "^3.7"
46 | importlib_metadata = {version = "^4.5.0", python = "<3.8"}
47 | fastapi = "*"
48 | pytest = "*"
49 |
50 | [tool.poetry.dev-dependencies]
51 | bandit = "^1.7.1"
52 | black = {version = "^22.6", allow-prereleases = true}
53 | darglint = "^1.8.1"
54 | isort = {extras = ["colors"], version = "^5.10.1"}
55 | mypy = "^0.961"
56 | mypy-extensions = "^0.4.3"
57 | pre-commit = "^2.15.0"
58 | pydocstyle = "^6.1.1"
59 | pylint = "^2.13.9"
60 | pytest = "^7.1.2"
61 | pyupgrade = "^2.29.1"
62 | safety = "^2.0.0"
63 | coverage = "^6.4"
64 | coverage-badge = "^1.1.0"
65 | pytest-html = "^3.1.1"
66 | pytest-cov = "^3.0.0"
67 |
68 | [tool.black]
69 | # https://github.com/psf/black
70 | target-version = ["py37"]
71 | line-length = 88
72 | color = true
73 |
74 | exclude = '''
75 | /(
76 | \.git
77 | | \.hg
78 | | \.mypy_cache
79 | | \.tox
80 | | \.venv
81 | | _build
82 | | buck-out
83 | | build
84 | | dist
85 | | env
86 | | venv
87 | )/
88 | '''
89 |
90 | [tool.isort]
91 | # https://github.com/timothycrosley/isort/
92 | py_version = 37
93 | line_length = 88
94 |
95 | known_typing = ["typing", "types", "typing_extensions", "mypy", "mypy_extensions"]
96 | sections = ["FUTURE", "TYPING", "STDLIB", "THIRDPARTY", "FIRSTPARTY", "LOCALFOLDER"]
97 | include_trailing_comma = true
98 | profile = "black"
99 | multi_line_output = 3
100 | indent = 4
101 | color_output = true
102 |
103 | [tool.mypy]
104 | # https://mypy.readthedocs.io/en/latest/config_file.html#using-a-pyproject-toml-file
105 | python_version = 3.7
106 | pretty = true
107 | show_traceback = true
108 | color_output = true
109 |
110 | allow_redefinition = false
111 | check_untyped_defs = true
112 | disallow_any_generics = true
113 | disallow_incomplete_defs = true
114 | ignore_missing_imports = true
115 | implicit_reexport = false
116 | no_implicit_optional = true
117 | show_column_numbers = true
118 | show_error_codes = true
119 | show_error_context = true
120 | strict_equality = true
121 | strict_optional = true
122 | warn_no_return = true
123 | warn_redundant_casts = true
124 | warn_return_any = true
125 | warn_unreachable = true
126 | warn_unused_configs = true
127 | warn_unused_ignores = true
128 |
129 |
130 | [tool.pytest.ini_options]
131 | # https://docs.pytest.org/en/6.2.x/customize.html#pyproject-toml
132 | # Directories that are not visited by pytest collector:
133 | norecursedirs =["hooks", "*.egg", ".eggs", "dist", "build", "docs", ".tox", ".git", "__pycache__"]
134 | doctest_optionflags = ["NUMBER", "NORMALIZE_WHITESPACE", "IGNORE_EXCEPTION_DETAIL"]
135 | pytester_example_dir = "tests/examples"
136 |
137 | # Extra options:
138 | addopts = [
139 | "--strict-markers",
140 | "--tb=short",
141 | "--doctest-modules",
142 | "--doctest-continue-on-failure",
143 | ]
144 |
145 | [tool.coverage.run]
146 | source = ["tests"]
147 |
148 | [coverage.paths]
149 | source = "pytest-fastapi-deps"
150 |
151 | [coverage.run]
152 | branch = true
153 |
154 | [coverage.report]
155 | fail_under = 50
156 | show_missing = true
157 |
--------------------------------------------------------------------------------
/pytest_fastapi_deps/__init__.py:
--------------------------------------------------------------------------------
1 | # type: ignore[attr-defined]
2 | """A fixture which allows easy replacement of fastapi dependencies for testing"""
3 |
4 | import typing
5 |
6 | import contextlib
7 | import sys
8 |
9 | import pytest as pytest
10 | from fastapi import FastAPI
11 |
12 | if sys.version_info >= (3, 8):
13 | from importlib import metadata as importlib_metadata
14 | else:
15 | import importlib_metadata
16 |
17 |
18 | def get_version() -> str:
19 | try:
20 | return importlib_metadata.version(__name__)
21 | except importlib_metadata.PackageNotFoundError: # pragma: no cover
22 | return "unknown"
23 |
24 |
25 | version: str = get_version()
26 |
27 |
28 | class DependencyOverrider:
29 | """
30 | Allows to override the fastapi dependencies inside a cleanable context.
31 |
32 |
33 | Taken from https://stackoverflow.com/a/68687967/3800552 by
34 | https://stackoverflow.com/users/8944325/mat-win .
35 |
36 | Args:
37 | app: the fastapi app
38 | overrides: a dictionary of the override mappings where the key is the
39 | original function and the value is the replacement function.
40 | """
41 |
42 | def __init__(
43 | self, app: FastAPI, overrides: typing.Mapping[typing.Callable, typing.Callable]
44 | ) -> None:
45 | self.overrides = overrides
46 | self._app = app
47 | self._old_overrides = {}
48 |
49 | def __enter__(self):
50 | for dep, new_dep in self.overrides.items():
51 | if dep in self._app.dependency_overrides:
52 | # Save existing overrides
53 | self._old_overrides[dep] = self._app.dependency_overrides[dep]
54 | self._app.dependency_overrides[dep] = self._callable_replacement(new_dep)
55 | return self
56 |
57 | @staticmethod
58 | def _callable_replacement(new_dep):
59 | return new_dep if callable(new_dep) else lambda: new_dep
60 |
61 | def __exit__(self, *args: typing.Any) -> None:
62 | for dep in self.overrides.keys():
63 | if dep in self._old_overrides:
64 | # Restore previous overrides
65 | self._app.dependency_overrides[dep] = self._old_overrides.pop(dep)
66 | else:
67 | # Just delete the entry
68 | del self._app.dependency_overrides[dep]
69 |
70 |
71 | class FixtureDependencyOverrider:
72 | def __init__(self, app: FastAPI):
73 | self.app = app
74 |
75 | def override(self, overrides: typing.Mapping[typing.Callable, typing.Callable]):
76 | return DependencyOverrider(self.app, overrides)
77 |
78 |
79 | @pytest.fixture
80 | def fastapi_dep(request):
81 | parametrized = getattr(request, "param", None)
82 | context = (
83 | contextlib.nullcontext()
84 | if not parametrized
85 | else FixtureDependencyOverrider(parametrized[0]).override(parametrized[1])
86 | )
87 | with context:
88 | yield FixtureDependencyOverrider
89 |
--------------------------------------------------------------------------------
/setup.cfg:
--------------------------------------------------------------------------------
1 | [darglint]
2 | # https://github.com/terrencepreilly/darglint
3 | strictness = long
4 | docstring_style = google
5 |
--------------------------------------------------------------------------------
/tests/conftest.py:
--------------------------------------------------------------------------------
1 | pytest_plugins = "pytester"
2 |
--------------------------------------------------------------------------------
/tests/examples/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pksol/pytest-fastapi-deps/25a92f681e371fc0c03caaedf12b86c5b0ba84a7/tests/examples/__init__.py
--------------------------------------------------------------------------------
/tests/examples/test_public_api.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | from fastapi import Depends, FastAPI
3 | from fastapi.testclient import TestClient
4 |
5 | app = FastAPI()
6 |
7 |
8 | async def first_dep():
9 | return {"skip": 0, "limit": 100}
10 |
11 |
12 | def second_dep():
13 | return {"skip": 20, "limit": 50}
14 |
15 |
16 | @app.get("/depends/")
17 | async def get_depends(
18 | first_dep: dict = Depends(first_dep), second_dep: dict = Depends(second_dep)
19 | ):
20 | return {"first_dep": first_dep, "second_dep": second_dep}
21 |
22 |
23 | client = TestClient(app)
24 |
25 |
26 | def test_get_default_dep():
27 | response = client.get("/depends")
28 | assert response.status_code == 200
29 | assert response.json() == {
30 | "first_dep": {"skip": 0, "limit": 100},
31 | "second_dep": {"skip": 20, "limit": 50},
32 | }
33 |
34 |
35 | def test_get_override_single_dep(fastapi_dep):
36 | with fastapi_dep(app).override({first_dep: lambda: {"my": "override"}}):
37 | response = client.get("/depends")
38 | assert response.status_code == 200
39 | assert response.json() == {
40 | "first_dep": {"my": "override"},
41 | "second_dep": {"skip": 20, "limit": 50},
42 | }
43 |
44 |
45 | def test_get_override_single_dep_plain_object(fastapi_dep):
46 | with fastapi_dep(app).override({first_dep: "override"}):
47 | response = client.get("/depends")
48 | assert response.status_code == 200
49 | assert response.json() == {
50 | "first_dep": "override",
51 | "second_dep": {"skip": 20, "limit": 50},
52 | }
53 |
54 |
55 | def test_get_override_unrelated_dep(fastapi_dep):
56 | with fastapi_dep(app).override(
57 | {
58 | first_dep: lambda: {"my": "override"},
59 | test_get_override_unrelated_dep: lambda: {"another": "override"},
60 | }
61 | ):
62 | response = client.get("/depends")
63 | assert response.status_code == 200
64 | assert response.json() == {
65 | "first_dep": {"my": "override"},
66 | "second_dep": {"skip": 20, "limit": 50},
67 | }
68 |
69 |
70 | def my_second_override():
71 | return {"another": "override"}
72 |
73 |
74 | def test_get_override_two_dep(fastapi_dep):
75 | with fastapi_dep(app).override(
76 | {
77 | first_dep: lambda: {"my": "override"},
78 | second_dep: my_second_override,
79 | }
80 | ):
81 | response = client.get("/depends")
82 | assert response.status_code == 200
83 | assert response.json() == {
84 | "first_dep": {"my": "override"},
85 | "second_dep": {"another": "override"},
86 | }
87 |
88 |
89 | def test_get_override_dep_inner_context(fastapi_dep):
90 | with fastapi_dep(app).override({first_dep: lambda: {"my": "override"}}):
91 | response = client.get("/depends")
92 | assert response.status_code == 200
93 | assert response.json() == {
94 | "first_dep": {"my": "override"},
95 | "second_dep": {"skip": 20, "limit": 50},
96 | }
97 |
98 | # add another override
99 | with fastapi_dep(app).override({second_dep: lambda: {"another": "override"}}):
100 | response = client.get("/depends")
101 | assert response.status_code == 200
102 | assert response.json() == {
103 | "first_dep": {"my": "override"},
104 | "second_dep": {"another": "override"},
105 | }
106 |
107 | # second override is gone - expect that only the first is overridden
108 | response = client.get("/depends")
109 | assert response.status_code == 200
110 | assert response.json() == {
111 | "first_dep": {"my": "override"},
112 | "second_dep": {"skip": 20, "limit": 50},
113 | }
114 |
115 | # back to normal behaviour
116 | response = client.get("/depends")
117 | assert response.status_code == 200
118 | assert response.json() == {
119 | "first_dep": {"skip": 0, "limit": 100},
120 | "second_dep": {"skip": 20, "limit": 50},
121 | }
122 |
123 |
124 | @pytest.mark.parametrize(
125 | "fastapi_dep",
126 | [
127 | (
128 | app,
129 | {first_dep: lambda: {"my": "override"}},
130 | )
131 | ],
132 | indirect=True,
133 | )
134 | def test_get_override_indirect_dep_param(fastapi_dep):
135 | response = client.get("/depends")
136 | assert response.status_code == 200
137 | assert response.json() == {
138 | "first_dep": {"my": "override"},
139 | "second_dep": {"skip": 20, "limit": 50},
140 | }
141 |
--------------------------------------------------------------------------------
/tests/test_pytest_fastapi_deps.py:
--------------------------------------------------------------------------------
1 | def pytest_run_verify(testdir, test_functions):
2 | # run pytest with the following cmd args
3 | result = testdir.runpytest("-v")
4 |
5 | if test_functions:
6 | test_functions = (
7 | test_functions if isinstance(test_functions, list) else [test_functions]
8 | )
9 | # fnmatch_lines does an assertion internally
10 | result.stdout.fnmatch_lines(
11 | [f"*::{test_function} PASSED*" for test_function in test_functions]
12 | )
13 |
14 | # make sure that that we get a '0' exit code for the testsuite
15 | assert result.ret == 0
16 |
17 |
18 | def test_fastapi_dep_fixture_exists(testdir):
19 | """Make sure that pytest accepts our fixture."""
20 |
21 | # create a temporary pytest test module
22 | testdir.makepyfile(
23 | """
24 | def test_sth(fastapi_dep):
25 | assert fastapi_dep
26 | """
27 | )
28 |
29 | pytest_run_verify(testdir, "test_sth")
30 |
31 |
32 | def test_public_api(testdir):
33 | testdir.copy_example("test_public_api.py")
34 | testdir.runpytest()
35 | pytest_run_verify(testdir, [])
36 |
--------------------------------------------------------------------------------