pax_global_header00006660000000000000000000000064147213102250014507gustar00rootroot0000000000000052 comment=029058005ff9681f5b9f3e2adf2030dfb40d21d5 python-polyfactory-2.18.1/000077500000000000000000000000001472131022500154725ustar00rootroot00000000000000python-polyfactory-2.18.1/.all-contributorsrc000066400000000000000000000262651472131022500213360ustar00rootroot00000000000000{ "files": [ "README.md" ], "imageSize": 100, "commit": false, "commitConvention": "angular", "contributors": [ { "login": "Goldziher", "name": "Na'aman Hirschfeld", "avatar_url": "https://avatars.githubusercontent.com/u/30733348?v=4", "profile": "https://github.com/Goldziher", "contributions": [ "maintenance", "infra", "test", "code", "doc" ] }, { "login": "JacobCoffee", "name": "Jacob Coffee", "avatar_url": "https://avatars.githubusercontent.com/u/45884264?v=4", "profile": "https://scriptr.dev/", "contributions": [ "maintenance", "doc", "test" ] }, { "login": "provinzkraut", "name": "Janek Nouvertné", "avatar_url": "https://avatars.githubusercontent.com/u/25355197?v=4", "profile": "https://github.com/provinzkraut", "contributions": [ "maintenance", "doc", "test", "code" ] }, { "login": "peterschutt", "name": "Peter Schutt", "avatar_url": "https://avatars.githubusercontent.com/u/20659309?v=4", "profile": "https://schutt.io", "contributions": [ "maintenance", "test", "code", "doc" ] }, { "login": "mdczaplicki", "name": "Marek Czaplicki", "avatar_url": "https://avatars.githubusercontent.com/u/9108586?v=4", "profile": "https://czaplicki.it/", "contributions": [ "code", "test" ] }, { "login": "przybylop", "name": "Piotr Przybyło", "avatar_url": "https://avatars.githubusercontent.com/u/82805821?v=4", "profile": "https://github.com/przybylop", "contributions": [ "code" ] }, { "login": "sygutss", "name": "sygutss", "avatar_url": "https://avatars.githubusercontent.com/u/48909366?v=4", "profile": "https://github.com/sygutss", "contributions": [ "bug", "code" ] }, { "login": "chrisbeardy", "name": "chrisbeardy", "avatar_url": "https://avatars.githubusercontent.com/u/20585410?v=4", "profile": "https://github.com/chrisbeardy", "contributions": [ "doc" ] }, { "login": "guacs", "name": "guacs", "avatar_url": "https://avatars.githubusercontent.com/u/126393040?v=4", "profile": "https://github.com/guacs", "contributions": [ "code", "infra", "doc", "test", "maintenance" ] }, { "login": "VSHUMILIN97", "name": "Vadim", "avatar_url": "https://avatars.githubusercontent.com/u/27234763?v=4", "profile": "https://github.com/VSHUMILIN97", "contributions": [ "code" ] }, { "login": "Simske", "name": "Simske", "avatar_url": "https://avatars.githubusercontent.com/u/2445660?v=4", "profile": "https://github.com/Simske", "contributions": [ "code" ] }, { "login": "sondrelg", "name": "Sondre Lillebø Gundersen", "avatar_url": "https://avatars.githubusercontent.com/u/25310870?v=4", "profile": "https://github.com/sondrelg", "contributions": [ "code" ] }, { "login": "mciszczon", "name": "Mateusz Ciszczoń", "avatar_url": "https://avatars.githubusercontent.com/u/1078369?v=4", "profile": "https://mciszczon.pl/", "contributions": [ "code" ] }, { "login": "phbernardes", "name": "Pedro Bernardes", "avatar_url": "https://avatars.githubusercontent.com/u/18899993?v=4", "profile": "https://www.linkedin.com/in/pedro-bernardes/", "contributions": [ "code" ] }, { "login": "lindycoder", "name": "Martin Roy", "avatar_url": "https://avatars.githubusercontent.com/u/12926519?v=4", "profile": "https://github.com/lindycoder", "contributions": [ "code" ] }, { "login": "Butch78", "name": "Matthew Aylward ", "avatar_url": "https://avatars.githubusercontent.com/u/19205392?v=4", "profile": "http://matthewtyleraylward.com", "contributions": [ "code" ] }, { "login": "EltonChou", "name": "Elton H.Y. Chou", "avatar_url": "https://avatars.githubusercontent.com/u/12560310?v=4", "profile": "https://github.com/EltonChou", "contributions": [ "code" ] }, { "login": "nguyent", "name": "Thang", "avatar_url": "https://avatars.githubusercontent.com/u/576848?v=4", "profile": "https://github.com/nguyent", "contributions": [ "code" ] }, { "login": "DaanRademaker", "name": "Daan", "avatar_url": "https://avatars.githubusercontent.com/u/29598493?v=4", "profile": "https://github.com/DaanRademaker", "contributions": [ "code" ] }, { "login": "lyz-code", "name": "Lyz", "avatar_url": "https://avatars.githubusercontent.com/u/24810987?v=4", "profile": "https://lyz-code.github.io/blue-book/", "contributions": [ "code" ] }, { "login": "thorin-schiffer", "name": "Thorin Schiffer", "avatar_url": "https://avatars.githubusercontent.com/u/3502492?v=4", "profile": "https://portfolio.schiffer.pro/", "contributions": [ "code" ] }, { "login": "Iipin", "name": "Iipin", "avatar_url": "https://avatars.githubusercontent.com/u/52832022?v=4", "profile": "https://github.com/Iipin", "contributions": [ "code" ] }, { "login": "avihai-yosef", "name": "avihai-yosef", "avatar_url": "https://avatars.githubusercontent.com/u/79567307?v=4", "profile": "https://github.com/avihai-yosef", "contributions": [ "code" ] }, { "login": "anthonyh209", "name": "anthonyh209", "avatar_url": "https://avatars.githubusercontent.com/u/33107540?v=4", "profile": "https://github.com/anthonyh209", "contributions": [ "code" ] }, { "login": "ReznikovRoman", "name": "Roman Reznikov", "avatar_url": "https://avatars.githubusercontent.com/u/44291988?v=4", "profile": "http://linkedin.com/in/roman-reznikov", "contributions": [ "code" ] }, { "login": "gigelu", "name": "gigelu", "avatar_url": "https://avatars.githubusercontent.com/u/270697?v=4", "profile": "https://github.com/gigelu", "contributions": [ "code" ] }, { "login": "roeeyn", "name": "Rodrigo Medina", "avatar_url": "https://avatars.githubusercontent.com/u/13385000?v=4", "profile": "https://github.com/roeeyn", "contributions": [ "code" ] }, { "login": "gegnew", "name": "Gerrit Egnew", "avatar_url": "https://avatars.githubusercontent.com/u/35822787?v=4", "profile": "https://gerritegnew.info/", "contributions": [ "code" ] }, { "login": "danielkatzan", "name": "danielkatzan", "avatar_url": "https://avatars.githubusercontent.com/u/9249066?v=4", "profile": "https://github.com/danielkatzan", "contributions": [ "doc" ] }, { "login": "abdulhaq-e", "name": "Abdulhaq Emhemmed", "avatar_url": "https://avatars.githubusercontent.com/u/2532125?v=4", "profile": "https://github.com/abdulhaq-e", "contributions": [ "code" ] }, { "login": "klimantje", "name": "klimantje", "avatar_url": "https://avatars.githubusercontent.com/u/20017047?v=4", "profile": "https://github.com/klimantje", "contributions": [ "code" ] }, { "login": "tcrasset", "name": "Tom Crasset", "avatar_url": "https://avatars.githubusercontent.com/u/25140344?v=4", "profile": "https://github.com/tcrasset", "contributions": [ "code" ] }, { "login": "185504a9", "name": "cătălin", "avatar_url": "https://avatars.githubusercontent.com/u/45485069?v=4", "profile": "https://git.roboces.dev/catalin", "contributions": [ "code" ] }, { "login": "adhtruong", "name": "Andrew Truong", "avatar_url": "https://avatars.githubusercontent.com/u/40660973?v=4", "profile": "https://github.com/adhtruong", "contributions": [ "code", "doc" ] }, { "login": "anthonyjgraff", "name": "Anthony", "avatar_url": "https://avatars.githubusercontent.com/u/59455370?v=4", "profile": "https://github.com/anthonyjgraff", "contributions": [ "code", "doc", "test" ] }, { "login": "johnraz", "name": "Jonathan Liuti", "avatar_url": "https://avatars.githubusercontent.com/u/304164?v=4", "profile": "https://github.com/johnraz", "contributions": [ "code", "doc", "test" ] }, { "login": "julioolvr", "name": "Julio Olivera", "avatar_url": "https://avatars.githubusercontent.com/u/1302493?v=4", "profile": "https://julio.li/", "contributions": [ "code", "test" ] }, { "login": "g0di", "name": "Benoît Godard", "avatar_url": "https://avatars.githubusercontent.com/u/2545380?v=4", "profile": "https://github.com/g0di", "contributions": [ "code", "doc", "test" ] }, { "login": "hsorsky", "name": "Henry Sorsky", "avatar_url": "https://avatars.githubusercontent.com/u/36887638?v=4", "profile": "https://github.com/hsorsky", "contributions": [ "infra" ] }, { "login": "wer153", "name": "Kim Minki", "avatar_url": "https://avatars.githubusercontent.com/u/23370765?v=4", "profile": "https://github.com/wer153", "contributions": [ "doc" ] }, { "login": "TimDumol", "name": "Tim Joseph Dumol", "avatar_url": "https://avatars.githubusercontent.com/u/49169?v=4", "profile": "https://www.timdumol.com/", "contributions": [ "doc" ] }, { "login": "wangxin688", "name": "jeffry", "avatar_url": "https://avatars.githubusercontent.com/u/36665036?v=4", "profile": "https://github.com/wangxin688", "contributions": [ "code" ] }, { "login": "Reskov", "name": "Sergey Kovalev", "avatar_url": "https://avatars.githubusercontent.com/u/4832451?v=4", "profile": "https://github.com/Reskov", "contributions": [ "code" ] }, { "login": "Vegemash", "name": "Isaac Jackson", "avatar_url": "https://avatars.githubusercontent.com/u/2470379?v=4", "profile": "https://github.com/Vegemash", "contributions": [ "code" ] } ], "contributorsPerLine": 7, "skipCi": true, "repoType": "github", "repoHost": "https://github.com", "projectName": "polyfactory", "projectOwner": "litestar-org", "commitType": "docs" } python-polyfactory-2.18.1/.github/000077500000000000000000000000001472131022500170325ustar00rootroot00000000000000python-polyfactory-2.18.1/.github/CODEOWNERS000066400000000000000000000011261472131022500204250ustar00rootroot00000000000000# Code owner settings for `litestar` # @maintainers should be assigned to all reviews. # Most specific assignment takes precedence though, so if you add a more specific thing than the `*` glob, you must also add @maintainers # For more info about code owners see https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners#codeowners-file-example # Global Assignment * @litestar-org/maintainers @litestar-org/members # Documentation docs/* @litestar-org/maintainers @JacobCoffee @provinzkraut # Polyfactory * @guacs python-polyfactory-2.18.1/.github/ISSUE_TEMPLATE/000077500000000000000000000000001472131022500212155ustar00rootroot00000000000000python-polyfactory-2.18.1/.github/ISSUE_TEMPLATE/BUG.yaml000066400000000000000000000044761472131022500225310ustar00rootroot00000000000000name: "Bug Report" description: Create an issue for a bug. title: "Bug: " labels: ["bug", "triage required"] body: - type: textarea id: description attributes: label: "Description" description: Please enter an description of the bug you are encountering placeholder: validations: required: true - type: input id: reprod-url attributes: label: "URL to code causing the issue" description: Please enter the URL to provide a reproduction of the issue, if applicable placeholder: ex. https://github.com/USERNAME/REPO-NAME validations: required: false - type: textarea id: mcve attributes: label: "MCVE" description: "Please provide a minimal, complete, and verifiable example of the issue." value: | ```py # Your MCVE code here ``` render: python validations: required: false - type: textarea id: reprod attributes: label: "Steps to reproduce" description: Please enter the exact steps to reproduce the issue value: | 1. Go to '...' 2. Click on '....' 3. Scroll down to '....' 4. See error render: bash validations: required: false - type: textarea id: screenshot attributes: label: "Screenshots" description: If applicable, add screenshots to help explain your problem. value: | "In the format of: `![SCREENSHOT_DESCRIPTION](SCREENSHOT_LINK.png)`" validations: required: false - type: textarea id: logs attributes: label: "Logs" description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks. render: bash validations: required: false - type: textarea id: version attributes: label: "Release Version" description: What version of the project are you using when encountering this issue? validations: required: true - type: checkboxes id: platform attributes: label: "Platform" description: What platform are you encountering the issue on? options: - label: "Linux" - label: "Mac" - label: "Windows" - label: "Other (Please specify in the description above)" validations: required: false ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/.github/ISSUE_TEMPLATE/DOCS.yaml������������������������������������������0000664�0000000�0000000�00000000576�14721310225�0022641�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������name: "Documentation Update" description: Create an issue for documentation changes title: "Docs: <title>" labels: ["documentation"] body: - type: textarea id: summary attributes: label: "Summary" description: Provide a brief summary of your feature request placeholder: Describe in a few lines your feature request validations: required: true ����������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/.github/ISSUE_TEMPLATE/REQUEST.yaml���������������������������������������0000664�0000000�0000000�00000002301�14721310225�0023225�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������name: "Feature Request" description: Create an issue for a new feature request title: "Enhancement: <title>" labels: ["enhancement"] body: - type: textarea id: summary attributes: label: "Summary" description: Provide a brief summary of your feature request placeholder: Describe in a few lines your feature request validations: required: true - type: textarea id: basic_example attributes: label: "Basic Example" description: Indicate here some basic examples of your feature. placeholder: Provide some basic example of your feature request validations: required: false - type: textarea id: drawbacks attributes: label: "Drawbacks and Impact" description: What are the drawbacks or impacts of your feature request? placeholder: Describe any the drawbacks or impacts of your feature request validations: required: false - type: textarea id: unresolved_question attributes: label: "Unresolved questions" description: What, if any, unresolved questions do you have about your feature request? placeholder: Identify any unresolved issues. validations: required: false �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/.github/ISSUE_TEMPLATE/config.yml�����������������������������������������0000664�0000000�0000000�00000001201�14721310225�0023177�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������blank_lines_enabled: true contact_links: - name: Polyfactory Documentation url: https://polyfactory.litestar.dev/ about: Official Polyfactory documentation - please check here before opening an issue. - name: Litestar Documentation url: https://docs.litestar.dev/ about: Official Litestar documentation - please check here before opening an issue. - name: Litestar Website url: https://litestar.dev/ about: Main Litestar website - for details about Litestar's projects. - name: Discord url: https://discord.gg/MmcwxztmQb about: Join our Discord community to chat or get in touch with the maintainers. �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/.github/dependabot.yaml���������������������������������������������������0000664�0000000�0000000�00000000165�14721310225�0022025�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������version: 2 updates: - package-ecosystem: "github-actions" directory: "/" schedule: interval: "daily" �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/.github/workflows/��������������������������������������������������������0000775�0000000�0000000�00000000000�14721310225�0021067�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/.github/workflows/ci.yml��������������������������������������������������0000664�0000000�0000000�00000013166�14721310225�0022214�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������name: Tests And Linting on: pull_request: push: branches: - main jobs: validate: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: python-version: "3.12" - name: Install Pre-Commit run: python -m pip install pre-commit && pre-commit install - name: Load cached Pre-Commit Dependencies id: cached-pre-commit-dependencies uses: actions/cache@v4 with: path: ~/.cache/pre-commit/ key: pre-commit|${{ env.pythonLocation }}|${{ hashFiles('.pre-commit-config.yaml') }} - name: Execute Pre-Commit run: pre-commit run --show-diff-on-failure --color=always --all-files test: runs-on: ubuntu-latest strategy: fail-fast: true matrix: python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"] pydantic-version: ["1.10", "2.0"] sqla-version: ["1.4", "2"] exclude: - pydantic-version: "1.10" sqla-version: "1.4" steps: - name: Check out repository uses: actions/checkout@v4 - name: Set up python ${{ matrix.python-version }} id: checkout-python uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - name: Create cache file run: echo '${{ matrix.pydantic-version }}-${{ matrix.sqla-version }}' > ./matrix-file.txt - uses: pdm-project/setup-pdm@v4 name: Set up PDM with: python-version: ${{ matrix.python-version }} allow-python-prereleases: true cache: true cache-dependency-path: | ./pdm.lock ./matrix-file.txt - name: Install pydantic if: matrix.pydantic-version == '1.10' run: pdm add --no-sync -G pydantic "pydantic[email]==1.10.17" - name: Install SQLAlchemy if: matrix.sqla-version == '1.4' run: pdm add --no-sync -dG sqlalchemy "sqlalchemy[asyncio]==1.4.49" - name: Install dependencies run: pdm sync -G:all - name: Set pythonpath run: echo "PYTHONPATH=$PWD" >> $GITHUB_ENV - name: Test if: matrix.python-version != '3.12' || matrix.pydantic-version != '2.0' || matrix.sqla-version != '2' run: pdm run pytest tests - name: Test with Coverage if: matrix.python-version == '3.12' && matrix.pydantic-version == '2.0' && matrix.sqla-version == '2' run: pdm run pytest tests docs/examples --cov=. --cov-report=xml - uses: actions/upload-artifact@v4 if: matrix.python-version == '3.12' && matrix.pydantic-version == '2.0' && matrix.sqla-version == '2' with: name: coverage-data path: coverage.xml build-docs: needs: - validate if: github.event_name == 'pull_request' runs-on: ubuntu-latest steps: - name: Check out repository uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v5 with: python-version: "3.12" - uses: pdm-project/setup-pdm@v4 name: Set up PDM with: python-version: "3.12" allow-python-prereleases: true cache: true - name: Install dependencies run: pdm install -G:all - name: Build docs run: pdm run make docs - name: Save PR number env: PR_NUMBER: ${{ github.event.number }} run: echo $PR_NUMBER > .pr_number - name: Upload artifact uses: actions/upload-artifact@v4 with: name: docs-preview include-hidden-files: true path: | docs/_build/html .pr_number sonar: needs: - test - validate if: github.event.pull_request.head.repo.fork == false runs-on: ubuntu-latest steps: - name: Check out repository uses: actions/checkout@v4 - name: Download Artifacts uses: actions/download-artifact@v4 with: name: coverage-data - name: Fix coverage file for sonarcloud run: sed -i "s/home\/runner\/work\/polyfactory\/polyfactory/github\/workspace/g" coverage.xml - name: SonarCloud Scan uses: sonarsource/sonarcloud-github-action@master env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} codeql: needs: - test - validate runs-on: ubuntu-latest permissions: security-events: write steps: - name: Checkout repository uses: actions/checkout@v4 - name: Initialize CodeQL With Dependencies if: github.event_name == 'push' && github.ref_name == 'main' uses: github/codeql-action/init@v3 - name: Initialize CodeQL Without Dependencies if: github.event_name == 'pull_request' uses: github/codeql-action/init@v3 with: setup-python-dependencies: false - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v3 upload-test-coverage: runs-on: ubuntu-latest needs: - test steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: python-version: "3.12" - name: Download Artifacts uses: actions/download-artifact@v4 with: name: coverage-data - name: Fix coverage file name run: sed -i "s/home\/runner\/work\/polyfactory\/polyfactory/github\/workspace/g" coverage.xml - name: Upload coverage reports to Codecov uses: codecov/codecov-action@v4 with: files: coverage.xml token: ${{ secrets.CODECOV_TOKEN }} ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/.github/workflows/docs-preview.yml����������������������������������������0000664�0000000�0000000�00000004444�14721310225�0024227�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������name: Deploy Documentation Preview on: workflow_run: workflows: [Tests And Linting] types: [completed] jobs: deploy: if: ${{ github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.event == 'pull_request' }} runs-on: ubuntu-latest permissions: issues: write pull-requests: write steps: - name: Check out repository uses: actions/checkout@v4 - name: Download artifact uses: dawidd6/action-download-artifact@v3 with: workflow_conclusion: success run_id: ${{ github.event.workflow_run.id }} path: docs-preview name: docs-preview - name: Set PR number run: echo "PR_NUMBER=$(cat docs-preview/.pr_number)" >> $GITHUB_ENV - name: Deploy docs preview uses: JamesIves/github-pages-deploy-action@v4 with: folder: docs-preview/docs/_build/html token: ${{ secrets.DOCS_PREVIEW_DEPLOY_TOKEN }} repository-name: litestar-org/polyfactory-docs-preview clean: false target-folder: ${{ env.PR_NUMBER }} branch: gh-pages - uses: actions/github-script@v7 env: PR_NUMBER: ${{ env.PR_NUMBER }} with: script: | const issue_number = process.env.PR_NUMBER const body = "Documentation preview will be available shortly at https://litestar-org.github.io/polyfactory-docs-preview/" + issue_number const opts = github.rest.issues.listComments.endpoint.merge({ owner: context.repo.owner, repo: context.repo.repo, issue_number: issue_number, }); const comments = await github.paginate(opts) for (const comment of comments) { if (comment.user.id === 41898282 && comment.body === body) { await github.rest.issues.deleteComment({ owner: context.repo.owner, repo: context.repo.repo, comment_id: comment.id }) } } await github.rest.issues.createComment({ owner: context.repo.owner, repo: context.repo.repo, issue_number: issue_number, body: body, }) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/.github/workflows/docs.yml������������������������������������������������0000664�0000000�0000000�00000001775�14721310225�0022554�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������name: Documentation Building on: release: types: [published] push: branches: - main jobs: docs: permissions: contents: write runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: python-version: "3.12" - uses: pdm-project/setup-pdm@v4 name: Set up PDM with: python-version: "3.12" allow-python-prereleases: true cache: true - name: Install dependencies run: pdm install -G:all - name: Fetch gh pages run: git fetch origin gh-pages --depth=1 - name: Build release docs run: pdm run python tools/build_docs.py docs-build if: github.event_name == 'release' - name: Build dev docs run: pdm run python tools/build_docs.py docs-build if: github.event_name == 'push' - name: Deploy uses: JamesIves/github-pages-deploy-action@v4 with: folder: docs-build ���python-polyfactory-2.18.1/.github/workflows/pr-title.yml��������������������������������������������0000664�0000000�0000000�00000000532�14721310225�0023352�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������name: "Lint PR Title" on: pull_request_target: types: - opened - edited - synchronize permissions: pull-requests: read jobs: main: name: Validate PR title runs-on: ubuntu-latest steps: - uses: amannn/action-semantic-pull-request@v5 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} ����������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/.github/workflows/publish.yml���������������������������������������������0000664�0000000�0000000�00000002620�14721310225�0023260�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������name: Latest Release on: release: types: [published] workflow_dispatch: jobs: publish-release: name: upload release to PyPI runs-on: ubuntu-latest permissions: id-token: write environment: release steps: - name: Check out repository uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: python-version: "3.12" - uses: pdm-project/setup-pdm@v4 name: Set up PDM with: python-version: "3.12" allow-python-prereleases: true cache: true - name: Build package run: pdm build - name: Publish package distributions to PyPI uses: pypa/gh-action-pypi-publish@release/v1 build-docs: permissions: contents: write runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: python-version: "3.12" - uses: pdm-project/setup-pdm@v4 name: Set up PDM with: python-version: "3.12" allow-python-prereleases: true cache: true - name: Build package run: pdm build - name: Install docs dependencies run: pdm install -G:all - name: Build docs run: pdm run make docs - name: Deploy uses: JamesIves/github-pages-deploy-action@v4 with: folder: docs/_build/html ����������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/.gitignore����������������������������������������������������������������0000664�0000000�0000000�00000001314�14721310225�0017461�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# folders __pycache__/ .auto_pytabs_cache/ .hypothesis/ .idea/ .mypy_cache/ .pytest_cache/ .scannerwork/ .venv/ .vscode/ *.egg-info/ build/ dist/ node_modules/ results/ site/ target/ # files **/*.so **/*.sqlite **/*.sqlite* *.iml .DS_Store .coverage .python-version .ruff_cache /docs/_build/ coverage.* setup.py # pdm # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. #pdm.lock # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it # in version control. # https://pdm.fming.dev/#use-with-ide .pdm.toml # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm __pypackages__/ /.pdm-python ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/.pre-commit-config.yaml���������������������������������������������������0000664�0000000�0000000�00000004071�14721310225�0021755�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������default_language_version: python: "3.12" repos: - repo: https://github.com/compilerla/conventional-pre-commit rev: v3.4.0 hooks: - id: conventional-pre-commit stages: [commit-msg] - repo: https://github.com/pre-commit/pre-commit-hooks rev: v4.6.0 hooks: - id: check-ast - id: check-case-conflict - id: check-merge-conflict - id: check-toml - id: debug-statements - id: end-of-file-fixer - id: mixed-line-ending - id: trailing-whitespace - repo: https://github.com/pdm-project/pdm rev: 2.17.3 hooks: - id: pdm-lock-check - repo: https://github.com/charliermarsh/ruff-pre-commit rev: "v0.5.6" hooks: - id: ruff args: ["--fix"] - id: ruff-format - repo: https://github.com/codespell-project/codespell rev: v2.3.0 hooks: - id: codespell - repo: https://github.com/pre-commit/mirrors-prettier rev: "v4.0.0-alpha.8" hooks: - id: prettier exclude: ".all-contributorsrc" - repo: https://github.com/pre-commit/mirrors-mypy rev: "v1.11.1" hooks: - id: mypy exclude: "test_decimal_constraints|examples/fields/test_example_2|examples/configuration|tools/" additional_dependencies: [ attrs>=22.2.0, beanie, faker, hypothesis, mongomock_motor, msgspec, odmantic<1, pydantic>=2, pytest, sphinx, sqlalchemy>=2, ] - repo: https://github.com/RobertCraigie/pyright-python rev: v1.1.374 hooks: - id: pyright exclude: "tests" additional_dependencies: [ attrs>=22.2.0, beanie, faker, hypothesis, mongomock_motor, msgspec, odmantic<1, pydantic>=2, pytest, sphinx, sqlalchemy>=2, ] - repo: https://github.com/sphinx-contrib/sphinx-lint rev: "v0.9.1" hooks: - id: sphinx-lint �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/.sourcery.yaml������������������������������������������������������������0000664�0000000�0000000�00000001156�14721310225�0020312�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ignore: - .tox/ - .venv/ - dist/ - docs/_build/ - docs/_static/ - node_modules/ - vendor/ - venv/ rule_settings: enable: [default] disable: [dont-import-test-modules] rule_types: - refactoring - suggestion - comment python_version: "3.8" rules: [] metrics: quality_threshold: 25.0 github: ignore_labels: - sourcery-ignore - docs labels: - build-ignore request_review: origin: owner forked: author sourcery_branch: sourcery/{base_branch} clone_detection: min_lines: 3 min_duplicates: 2 identical_clones_only: false proxy: no_ssl_verify: false ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/CONTRIBUTING.rst����������������������������������������������������������0000664�0000000�0000000�00000010226�14721310225�0020134�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������Contributing ================== Setting up the environment -------------------------- 1. Install `Pizza Delivery Man <https://pdm.fming.dev/latest/>`_ 2. Run ``pdm install -G:all`` to create a `virtual environment <https://docs.python.org/3/tutorial/venv.html>`_ and install the dependencies 3. If you're working on the documentation and need to build it locally, install the extra dependencies with ``pdm install -G:docs`` 4. Install `pre-commit <https://pre-commit.com/>`_ 5. Run ``pre-commit install`` to install pre-commit hooks Code contributions ------------------ Workflow ++++++++ 1. `Fork <https://github.com/litestar-org/polyfactory/fork>`_ the `Polyfactory repository <https://github.com/litestar-org/polyfactory>`_ 2. Clone your fork locally with git 3. `Set up the environment <#setting-up-the-environment>`_ 4. Make your changes 5. (Optional) Run ``pre-commit run --all-files`` to run linters and formatters. This step is optional and will be executed automatically by git before you make a commit, but you may want to run it manually in order to apply fixes 6. Commit your changes to git 7. Push the changes to your fork 8. Open a `pull request <https://docs.github.com/en/pull-requests>`_. Give the pull request a descriptive title indicating what it changes. If it has a corresponding open issue. For example a pull request that fixes issue ``bug: Increased stack size making it impossible to find needle`` could be titled ``fix: Make needles easier to find by applying fire to haystack`` .. tip:: Pull requests and commits all need to follow the `Conventional Commit format <https://www.conventionalcommits.org>`_ Project documentation --------------------- The documentation is located in the ``/docs`` directory and is built with `ReST <https://docutils.sourceforge.io/rst.html>`_ and `Sphinx <https://www.sphinx-doc.org/en/master/>`_. If you're unfamiliar with any of those, `ReStructuredText primer <https://www.sphinx-doc.org/en/master/usage/restructuredtext/basics.html>`_ and `Sphinx quickstart <https://www.sphinx-doc.org/en/master/usage/quickstart.html>`_ are recommended reads. Docs theme and appearance +++++++++++++++++++++++++ We welcome contributions that enhance / improve the appearance and usability of the docs. We use a custom theme that inherits the `Shibuya theme <https://shibuya.lepture.com/>`_, which comes with a lot of options out of the box. If you wish to contribute to the docs style / setup, or static site generation, you should consult the theme docs as a first step. Running the docs locally ++++++++++++++++++++++++ To run or build the docs locally, you need to first install the required dependencies: .. code-block:: console :caption: Installing the docs dependencies pdm install -G:docs Then you can serve the documentation with ``make docs-serve``, or build them with ``make docs`` Writing and editing docs ++++++++++++++++++++++++ We welcome contributions that enhance / improve the content of the docs. Feel free to add examples, clarify text, restructure the docs etc., but make sure to follow these guidelines: - Write text in idiomatic english, using simple language - Keep examples simple and self contained - Provide links where applicable - Use `intersphinx <https://www.sphinx-doc.org/en/master/usage/extensions/intersphinx.html>`_ wherever possible when referencing external libraries - Provide diagrams using `mermaidjs <https://mermaid.js.org/>`_ where applicable and possible Creating a new release ---------------------- 1. Increment the version in ``pyproject.toml`` .. note:: The version should follow `semantic versioning <https://semver.org/>`_ and `PEP 440 <https://www.python.org/dev/peps/pep-0440/>`_. 2. Commit and push. 3. In GitHub go to the `releases tab <https://github.com/litestar-org/polyfactory/releases>`_ 4. Pick "`Draft a new release <https://github.com/litestar-org/polyfactory/releases/new>`_" 5. Give it a title and a tag, both ``vX.X.X`` 6. Fill in the release description. You can let GitHub do it for you and then edit as needed. 7. Publish the release. 8. Go to `Actions <https://github.com/litestar-org/polyfactory/actions>`_ and approve the workflow 9. Check that the workflow runs successfully ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/LICENSE�������������������������������������������������������������������0000664�0000000�0000000�00000002104�14721310225�0016474�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������The MIT License (MIT) Copyright (c) 2021, 2022, 2023 Litestar Org. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/Makefile������������������������������������������������������������������0000664�0000000�0000000�00000012765�14721310225�0017145�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������SHELL := /bin/bash # ============================================================================= # Variables # ============================================================================= .DEFAULT_GOAL:=help .ONESHELL: USING_PDM = $(shell grep "tool.pdm" pyproject.toml && echo "yes") ENV_PREFIX := $(shell if [ -d .venv ]; then echo ".venv/bin/"; fi) VENV_EXISTS := $(shell if [ -d .venv ]; then echo "yes"; fi) PDM_OPTS ?= PDM ?= pdm $(PDM_OPTS) .EXPORT_ALL_VARIABLES: .PHONY: help help: ## Display this help text for Makefile @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m<target>\033[0m\n"} /^[a-zA-Z0-9_-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST) .PHONY: upgrade upgrade: ## Upgrade all dependencies to the latest stable versions @echo "=> Updating all dependencies" @if [ "$(USING_PDM)" ]; then $(PDM) update; fi @echo "=> Dependencies Updated" @$(ENV_PREFIX)pre-commit autoupdate @echo "=> Updated Pre-commit" # ============================================================================= # Developer Utils # ============================================================================= .PHONY: install-pdm install-pdm: ## Install latest version of PDM @curl -sSLO https://pdm.fming.dev/install-pdm.py && \ curl -sSL https://pdm.fming.dev/install-pdm.py.sha256 | shasum -a 256 -c - && \ python3 install-pdm.py .PHONY: install install: ## Install the project, dependencies, and pre-commit for local development @if ! $(PDM) --version > /dev/null; then echo '=> Installing PDM'; $(MAKE) install-pdm; fi @if [ "$(VENV_EXISTS)" ]; then echo "=> Removing existing virtual environment"; fi if [ "$(VENV_EXISTS)" ]; then $(MAKE) destroy; fi if [ "$(VENV_EXISTS)" ]; then $(MAKE) clean; fi @if [ "$(USING_PDM)" ]; then $(PDM) config venv.in_project true && python3 -m venv --copies .venv && . $(ENV_PREFIX)/activate && $(ENV_PREFIX)/pip install --quiet -U wheel setuptools cython pip; fi @if [ "$(USING_PDM)" ]; then $(PDM) install -G:all; fi @echo "=> Installing pre-commit hooks" pre-commit install --install-hooks @echo "=> Install complete! Note: If you want to re-install re-run 'make install'" .PHONY: clean clean: ## Cleanup temporary build artifacts @echo "=> Cleaning working directory" @rm -rf .pytest_cache .ruff_cache .hypothesis build/ -rf dist/ .eggs/ @find . -name '*.egg-info' -exec rm -rf {} + @find . -name '*.egg' -exec rm -f {} + @find . -name '*.pyc' -exec rm -f {} + @find . -name '*.pyo' -exec rm -f {} + @find . -name '*~' -exec rm -f {} + @find . -name '__pycache__' -exec rm -rf {} + @find . -name '.ipynb_checkpoints' -exec rm -rf {} + @rm -rf .coverage coverage.xml coverage.json htmlcov/ .pytest_cache tests/.pytest_cache tests/**/.pytest_cache .mypy_cache $(MAKE) docs-clean .PHONY: destroy destroy: ## Destroy the virtual environment @rm -rf .venv .PHONY: refresh-lockfiles refresh-lockfiles: ## Sync lockfiles with requirements files. pdm update --update-reuse --group :all .PHONY: lock lock: ## Rebuild lockfiles from scratch, updating all dependencies pdm update --update-eager --group :all # ============================================================================= # Tests, Linting, Coverage # ============================================================================= .PHONY: lint lint: ## Runs pre-commit hooks; includes ruff linting, ruff formatting, codespell @echo "=> Running pre-commit process" @$(ENV_PREFIX)pre-commit run --all-files @echo "=> Pre-commit complete" .PHONY: coverage coverage: ## Run the tests and generate coverage report @echo "=> Running tests with coverage" @$(ENV_PREFIX)pytest tests --cov=polyfactory @$(ENV_PREFIX)coverage html @$(ENV_PREFIX)coverage xml @echo "=> Coverage report generated" .PHONY: test test: ## Run the tests @echo "=> Running test cases" @$(ENV_PREFIX)pytest tests @echo "=> Tests complete" .PHONY: test-examples test-examples: ## Run the examples tests pytest docs/examples .PHONY: test-all test-all: test test-examples ## Run all tests .PHONY: check-all check-all: lint test-all coverage ## Run all linting, tests, and coverage checks # ============================================================================= # Docs # ============================================================================= .PHONY: docs-install docs-install: ## Install docs dependencies @echo "=> Installing documentation dependencies" @$(PDM) install --group docs @echo "=> Installed documentation dependencies" docs-clean: ## Dump the existing built docs @echo "=> Cleaning documentation build assets" @rm -rf docs/_build @echo "=> Removed existing documentation build assets" docs-serve: docs-clean ## Serve the docs locally @echo "=> Serving documentation" $(ENV_PREFIX)sphinx-autobuild docs docs/_build/ -j auto --watch polyfactory --watch docs --watch tests --watch CONTRIBUTING.rst --port 8002 docs: docs-clean ## Dump the existing built docs and rebuild them @echo "=> Building documentation" @$(ENV_PREFIX)sphinx-build -M html docs docs/_build/ -E -a -j auto --keep-going changelog: @echo "=> Generating changelog" @$(ENV_PREFIX)git-cliff -c pyproject.toml -o docs/changelog.rst --github-repo litestar-org/polyfactory --github-token $(GITHUB_TOKEN) �����������python-polyfactory-2.18.1/README.md�����������������������������������������������������������������0000664�0000000�0000000�00000076361�14721310225�0016766�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<!-- markdownlint-disable --> <p align="center"> <img src="https://github.com/litestar-org/branding/blob/e27cda904e0649e5065ac1c26df6a279ba5d06b5/assets/Branding%20-%20SVG%20-%20Transparent/Polyfactory%20-%20Banner%20-%20Inline%20-%20Light.svg#gh-light-mode-only" alt="Litestar - Polyfactory Logo - Light" width="100%" height="auto" /> <img src="https://github.com/litestar-org/branding/blob/e27cda904e0649e5065ac1c26df6a279ba5d06b5/assets/Branding%20-%20SVG%20-%20Transparent/Polyfactory%20-%20Banner%20-%20Inline%20-%20Dark.svg#gh-dark-mode-only" alt="Litestar - Polyfactory Logo - Dark" width="100%" height="auto" /> </p> <div align="center"> <!-- prettier-ignore-start --> | Project | | Status | | --------- | :-- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | CI/CD | | [![Publish package](https://github.com/litestar-org/polyfactory/actions/workflows/publish.yml/badge.svg)](https://github.com/litestar-org/polyfactory/actions/workflows/publish.yml) [![ci](https://github.com/litestar-org/polyfactory/actions/workflows/ci.yml/badge.svg)](https://github.com/litestar-org/polyfactory/actions/workflows/ci.yml) [![pages-build-deployment](https://github.com/litestar-org/polyfactory/actions/workflows/pages/pages-build-deployment/badge.svg)](https://github.com/litestar-org/polyfactory/actions/workflows/pages/pages-build-deployment) | | Quality | | [![Coverage](https://sonarcloud.io/api/project_badges/measure?project=litestar-org_polyfactory&metric=coverage)](https://sonarcloud.io/summary/new_code?id=litestar-org_polyfactory) [![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=litestar-org_polyfactory&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=litestar-org_polyfactory) [![Maintainability Rating](https://sonarcloud.io/api/project_badges/measure?project=litestar-org_polyfactory&metric=sqale_rating)](https://sonarcloud.io/summary/new_code?id=litestar-org_polyfactory) [![Reliability Rating](https://sonarcloud.io/api/project_badges/measure?project=litestar-org_polyfactory&metric=reliability_rating)](https://sonarcloud.io/summary/new_code?id=litestar-org_polyfactory) [![Security Rating](https://sonarcloud.io/api/project_badges/measure?project=litestar-org_polyfactory&metric=security_rating)](https://sonarcloud.io/summary/new_code?id=litestar-org_polyfactory) | | Package | | [![PyPI - Version](https://img.shields.io/pypi/v/polyfactory?labelColor=202235&color=edb641&logo=python&logoColor=edb641)](https://badge.fury.io/py/polyfactory) ![PyPI - Support Python Versions](https://img.shields.io/pypi/pyversions/polyfactory?labelColor=202235&color=edb641&logo=python&logoColor=edb641) ![Pydantic Factories PyPI - Downloads](https://img.shields.io/pypi/dm/pydantic-factories?logo=python&label=Pydantic%20Factories%20downloads&labelColor=202235&color=edb641&logoColor=edb641) ![Polyfactory PyPI - Downloads](https://img.shields.io/pypi/dm/polyfactory?logo=python&label=Polyfactory%20downloads&labelColor=202235&color=edb641&logoColor=edb641) | | Community | | [![Reddit](https://img.shields.io/reddit/subreddit-subscribers/litestarapi?label=r%2FLitestar&logo=reddit&labelColor=202235&color=edb641&logoColor=edb641)](https://reddit.com/r/litestarapi) [![Discord](https://img.shields.io/discord/919193495116337154?labelColor=202235&color=edb641&label=chat%20on%20discord&logo=discord&logoColor=edb641)](https://discord.gg/X3FJqy8d2j) [![Matrix](https://img.shields.io/badge/chat%20on%20Matrix-bridged-202235?labelColor=202235&color=edb641&logo=matrix&logoColor=edb641)](https://matrix.to/#/#litestar:matrix.org) [![Medium](https://img.shields.io/badge/Medium-202235?labelColor=202235&color=edb641&logo=medium&logoColor=edb641)](https://blog.litestar.dev) [![Twitter](https://img.shields.io/twitter/follow/LitestarAPI?labelColor=202235&color=edb641&logo=twitter&logoColor=edb641&style=flat)](https://twitter.com/LitestarAPI) [![Blog](https://img.shields.io/badge/Blog-litestar.dev-202235?logo=blogger&labelColor=202235&color=edb641&logoColor=edb641)](https://blog.litestar.dev) | | Meta | | [![Litestar Project](https://img.shields.io/badge/Litestar%20Org-%E2%AD%90%20Polyfactory-202235.svg?logo=python&labelColor=202235&color=edb641&logoColor=edb641)](https://github.com/litestar-org/polyfactory) [![types - Mypy](https://img.shields.io/badge/types-Mypy-202235.svg?logo=python&labelColor=202235&color=edb641&logoColor=edb641)](https://github.com/python/mypy) [![License - MIT](https://img.shields.io/badge/license-MIT-202235.svg?logo=python&labelColor=202235&color=edb641&logoColor=edb641)](https://spdx.org/licenses/) [![Litestar Sponsors](https://img.shields.io/badge/Sponsor-%E2%9D%A4-%23edb641.svg?&logo=github&logoColor=edb641&labelColor=202235)](https://github.com/sponsors/litestar-org) [![Sourcery](https://img.shields.io/badge/Pydantic-v2-edb641?labelColor=202235&logoColor=edb641)](https://pydantic.dev) [![linting - Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/charliermarsh/ruff/main/assets/badge/v2.json&labelColor=202235)](https://github.com/astral-sh/ruff) [![code style - Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/format.json&labelColor=202235)](https://github.com/astral-sh/ruff) [![Sourcery](https://img.shields.io/badge/Sourcery-enabled-edb641?labelColor=202235&logoColor=edb641)](https://sourcery.ai) [![All Contributors](https://img.shields.io/github/all-contributors/litestar-org/polyfactory?labelColor=202235&color=edb641&logoColor=edb641)](#contributors-) | <!-- prettier-ignore-end --> </div> <!-- markdownlint-restore --> # Polyfactory Polyfactory is a simple and powerful mock data generation library, based around type hints and supporting dataclasses, typed-dicts, pydantic models, msgspec structs and more. Polyfactory part of the Litestar project and as such actively maintained by a community of maintainers and contributors. ## Example ```python from dataclasses import dataclass from polyfactory.factories import DataclassFactory @dataclass class Person: name: str age: float height: float weight: float class PersonFactory(DataclassFactory[Person]): ... def test_is_person() -> None: person_instance = PersonFactory.build() assert isinstance(person_instance, Person) ``` That's it - with almost no work, we are able to create a mock data object fitting the `Person` class model definition. This is possible because of the typing information available on the dataclass, which are used as a source of truth for data generation. The factory parses the information stored in the dataclass and generates a dictionary of kwargs that are passed to `Person`. ## Documentation Usage and API reference documentation is available on https://polyfactory.litestar.dev/. ## Installation ```shell pip install polyfactory ``` ## Relation to Pydantic-Factories Prior to version 2, this library was known as [pydantic-factories](https://pypi.org/project/pydantic-factories/), a name under which it gained quite a bit of popularity. A main motivator for the 2.0 release was that we wanted to support more than just Pydantic models, something which also required a change to its core architecture. As this library would no longer be directly tied to Pydantic, `polyfactory` was chosen as its new name to reflect its capabilities; It can generate mock data for dataclasses, typed-dicts, Pydantic, odmantic, and beanie ODM models, as well as custom factories. ## Contributing This library is a community driven open source project. We welcome and encourage contributions. Please check out the GitHub issues, read the contribution guide (at the repository's root), and you're always welcome to [join our discord server](https://discord.gg/F4jPQzHpBU). ## Contributors ✨ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)): <!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section --> <!-- prettier-ignore-start --> <!-- markdownlint-disable --> <table> <tbody> <tr> <td align="center" valign="top" width="14.28%"><a href="https://github.com/Goldziher"><img src="https://avatars.githubusercontent.com/u/30733348?v=4?s=100" width="100px;" alt="Na'aman Hirschfeld"/><br /><sub><b>Na'aman Hirschfeld</b></sub></a><br /><a href="#maintenance-Goldziher" title="Maintenance">🚧</a> <a href="#infra-Goldziher" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="https://github.com/litestar-org/polyfactory/commits?author=Goldziher" title="Tests">⚠️</a> <a href="https://github.com/litestar-org/polyfactory/commits?author=Goldziher" title="Code">💻</a> <a href="https://github.com/litestar-org/polyfactory/commits?author=Goldziher" title="Documentation">📖</a></td> <td align="center" valign="top" width="14.28%"><a href="https://scriptr.dev/"><img src="https://avatars.githubusercontent.com/u/45884264?v=4?s=100" width="100px;" alt="Jacob Coffee"/><br /><sub><b>Jacob Coffee</b></sub></a><br /><a href="#maintenance-JacobCoffee" title="Maintenance">🚧</a> <a href="https://github.com/litestar-org/polyfactory/commits?author=JacobCoffee" title="Documentation">📖</a> <a href="https://github.com/litestar-org/polyfactory/commits?author=JacobCoffee" title="Tests">⚠️</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/provinzkraut"><img src="https://avatars.githubusercontent.com/u/25355197?v=4?s=100" width="100px;" alt="Janek Nouvertné"/><br /><sub><b>Janek Nouvertné</b></sub></a><br /><a href="#maintenance-provinzkraut" title="Maintenance">🚧</a> <a href="https://github.com/litestar-org/polyfactory/commits?author=provinzkraut" title="Documentation">📖</a> <a href="https://github.com/litestar-org/polyfactory/commits?author=provinzkraut" title="Tests">⚠️</a> <a href="https://github.com/litestar-org/polyfactory/commits?author=provinzkraut" title="Code">💻</a></td> <td align="center" valign="top" width="14.28%"><a href="https://schutt.io"><img src="https://avatars.githubusercontent.com/u/20659309?v=4?s=100" width="100px;" alt="Peter Schutt"/><br /><sub><b>Peter Schutt</b></sub></a><br /><a href="#maintenance-peterschutt" title="Maintenance">🚧</a> <a href="https://github.com/litestar-org/polyfactory/commits?author=peterschutt" title="Tests">⚠️</a> <a href="https://github.com/litestar-org/polyfactory/commits?author=peterschutt" title="Code">💻</a> <a href="https://github.com/litestar-org/polyfactory/commits?author=peterschutt" title="Documentation">📖</a></td> <td align="center" valign="top" width="14.28%"><a href="https://czaplicki.it/"><img src="https://avatars.githubusercontent.com/u/9108586?v=4?s=100" width="100px;" alt="Marek Czaplicki"/><br /><sub><b>Marek Czaplicki</b></sub></a><br /><a href="https://github.com/litestar-org/polyfactory/commits?author=mdczaplicki" title="Code">💻</a> <a href="https://github.com/litestar-org/polyfactory/commits?author=mdczaplicki" title="Tests">⚠️</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/przybylop"><img src="https://avatars.githubusercontent.com/u/82805821?v=4?s=100" width="100px;" alt="Piotr Przybyło"/><br /><sub><b>Piotr Przybyło</b></sub></a><br /><a href="https://github.com/litestar-org/polyfactory/commits?author=przybylop" title="Code">💻</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/sygutss"><img src="https://avatars.githubusercontent.com/u/48909366?v=4?s=100" width="100px;" alt="sygutss"/><br /><sub><b>sygutss</b></sub></a><br /><a href="https://github.com/litestar-org/polyfactory/issues?q=author%3Asygutss" title="Bug reports">🐛</a> <a href="https://github.com/litestar-org/polyfactory/commits?author=sygutss" title="Code">💻</a></td> </tr> <tr> <td align="center" valign="top" width="14.28%"><a href="https://github.com/chrisbeardy"><img src="https://avatars.githubusercontent.com/u/20585410?v=4?s=100" width="100px;" alt="chrisbeardy"/><br /><sub><b>chrisbeardy</b></sub></a><br /><a href="https://github.com/litestar-org/polyfactory/commits?author=chrisbeardy" title="Documentation">📖</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/guacs"><img src="https://avatars.githubusercontent.com/u/126393040?v=4?s=100" width="100px;" alt="guacs"/><br /><sub><b>guacs</b></sub></a><br /><a href="https://github.com/litestar-org/polyfactory/commits?author=guacs" title="Code">💻</a> <a href="#infra-guacs" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="https://github.com/litestar-org/polyfactory/commits?author=guacs" title="Documentation">📖</a> <a href="https://github.com/litestar-org/polyfactory/commits?author=guacs" title="Tests">⚠️</a> <a href="#maintenance-guacs" title="Maintenance">🚧</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/VSHUMILIN97"><img src="https://avatars.githubusercontent.com/u/27234763?v=4?s=100" width="100px;" alt="Vadim"/><br /><sub><b>Vadim</b></sub></a><br /><a href="https://github.com/litestar-org/polyfactory/commits?author=VSHUMILIN97" title="Code">💻</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/Simske"><img src="https://avatars.githubusercontent.com/u/2445660?v=4?s=100" width="100px;" alt="Simske"/><br /><sub><b>Simske</b></sub></a><br /><a href="https://github.com/litestar-org/polyfactory/commits?author=Simske" title="Code">💻</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/sondrelg"><img src="https://avatars.githubusercontent.com/u/25310870?v=4?s=100" width="100px;" alt="Sondre Lillebø Gundersen"/><br /><sub><b>Sondre Lillebø Gundersen</b></sub></a><br /><a href="https://github.com/litestar-org/polyfactory/commits?author=sondrelg" title="Code">💻</a></td> <td align="center" valign="top" width="14.28%"><a href="https://mciszczon.pl/"><img src="https://avatars.githubusercontent.com/u/1078369?v=4?s=100" width="100px;" alt="Mateusz Ciszczoń"/><br /><sub><b>Mateusz Ciszczoń</b></sub></a><br /><a href="https://github.com/litestar-org/polyfactory/commits?author=mciszczon" title="Code">💻</a></td> <td align="center" valign="top" width="14.28%"><a href="https://www.linkedin.com/in/pedro-bernardes/"><img src="https://avatars.githubusercontent.com/u/18899993?v=4?s=100" width="100px;" alt="Pedro Bernardes"/><br /><sub><b>Pedro Bernardes</b></sub></a><br /><a href="https://github.com/litestar-org/polyfactory/commits?author=phbernardes" title="Code">💻</a></td> </tr> <tr> <td align="center" valign="top" width="14.28%"><a href="https://github.com/lindycoder"><img src="https://avatars.githubusercontent.com/u/12926519?v=4?s=100" width="100px;" alt="Martin Roy"/><br /><sub><b>Martin Roy</b></sub></a><br /><a href="https://github.com/litestar-org/polyfactory/commits?author=lindycoder" title="Code">💻</a></td> <td align="center" valign="top" width="14.28%"><a href="http://matthewtyleraylward.com"><img src="https://avatars.githubusercontent.com/u/19205392?v=4?s=100" width="100px;" alt="Matthew Aylward "/><br /><sub><b>Matthew Aylward </b></sub></a><br /><a href="https://github.com/litestar-org/polyfactory/commits?author=Butch78" title="Code">💻</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/EltonChou"><img src="https://avatars.githubusercontent.com/u/12560310?v=4?s=100" width="100px;" alt="Elton H.Y. Chou"/><br /><sub><b>Elton H.Y. Chou</b></sub></a><br /><a href="https://github.com/litestar-org/polyfactory/commits?author=EltonChou" title="Code">💻</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/nguyent"><img src="https://avatars.githubusercontent.com/u/576848?v=4?s=100" width="100px;" alt="Thang"/><br /><sub><b>Thang</b></sub></a><br /><a href="https://github.com/litestar-org/polyfactory/commits?author=nguyent" title="Code">💻</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/DaanRademaker"><img src="https://avatars.githubusercontent.com/u/29598493?v=4?s=100" width="100px;" alt="Daan"/><br /><sub><b>Daan</b></sub></a><br /><a href="https://github.com/litestar-org/polyfactory/commits?author=DaanRademaker" title="Code">💻</a></td> <td align="center" valign="top" width="14.28%"><a href="https://lyz-code.github.io/blue-book/"><img src="https://avatars.githubusercontent.com/u/24810987?v=4?s=100" width="100px;" alt="Lyz"/><br /><sub><b>Lyz</b></sub></a><br /><a href="https://github.com/litestar-org/polyfactory/commits?author=lyz-code" title="Code">💻</a></td> <td align="center" valign="top" width="14.28%"><a href="https://portfolio.schiffer.pro/"><img src="https://avatars.githubusercontent.com/u/3502492?v=4?s=100" width="100px;" alt="Thorin Schiffer"/><br /><sub><b>Thorin Schiffer</b></sub></a><br /><a href="https://github.com/litestar-org/polyfactory/commits?author=thorin-schiffer" title="Code">💻</a></td> </tr> <tr> <td align="center" valign="top" width="14.28%"><a href="https://github.com/Iipin"><img src="https://avatars.githubusercontent.com/u/52832022?v=4?s=100" width="100px;" alt="Iipin"/><br /><sub><b>Iipin</b></sub></a><br /><a href="https://github.com/litestar-org/polyfactory/commits?author=Iipin" title="Code">💻</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/avihai-yosef"><img src="https://avatars.githubusercontent.com/u/79567307?v=4?s=100" width="100px;" alt="avihai-yosef"/><br /><sub><b>avihai-yosef</b></sub></a><br /><a href="https://github.com/litestar-org/polyfactory/commits?author=avihai-yosef" title="Code">💻</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/anthonyh209"><img src="https://avatars.githubusercontent.com/u/33107540?v=4?s=100" width="100px;" alt="anthonyh209"/><br /><sub><b>anthonyh209</b></sub></a><br /><a href="https://github.com/litestar-org/polyfactory/commits?author=anthonyh209" title="Code">💻</a></td> <td align="center" valign="top" width="14.28%"><a href="http://linkedin.com/in/roman-reznikov"><img src="https://avatars.githubusercontent.com/u/44291988?v=4?s=100" width="100px;" alt="Roman Reznikov"/><br /><sub><b>Roman Reznikov</b></sub></a><br /><a href="https://github.com/litestar-org/polyfactory/commits?author=ReznikovRoman" title="Code">💻</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/gigelu"><img src="https://avatars.githubusercontent.com/u/270697?v=4?s=100" width="100px;" alt="gigelu"/><br /><sub><b>gigelu</b></sub></a><br /><a href="https://github.com/litestar-org/polyfactory/commits?author=gigelu" title="Code">💻</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/roeeyn"><img src="https://avatars.githubusercontent.com/u/13385000?v=4?s=100" width="100px;" alt="Rodrigo Medina"/><br /><sub><b>Rodrigo Medina</b></sub></a><br /><a href="https://github.com/litestar-org/polyfactory/commits?author=roeeyn" title="Code">💻</a></td> <td align="center" valign="top" width="14.28%"><a href="https://gerritegnew.info/"><img src="https://avatars.githubusercontent.com/u/35822787?v=4?s=100" width="100px;" alt="Gerrit Egnew"/><br /><sub><b>Gerrit Egnew</b></sub></a><br /><a href="https://github.com/litestar-org/polyfactory/commits?author=gegnew" title="Code">💻</a></td> </tr> <tr> <td align="center" valign="top" width="14.28%"><a href="https://github.com/danielkatzan"><img src="https://avatars.githubusercontent.com/u/9249066?v=4?s=100" width="100px;" alt="danielkatzan"/><br /><sub><b>danielkatzan</b></sub></a><br /><a href="https://github.com/litestar-org/polyfactory/commits?author=danielkatzan" title="Documentation">📖</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/abdulhaq-e"><img src="https://avatars.githubusercontent.com/u/2532125?v=4?s=100" width="100px;" alt="Abdulhaq Emhemmed"/><br /><sub><b>Abdulhaq Emhemmed</b></sub></a><br /><a href="https://github.com/litestar-org/polyfactory/commits?author=abdulhaq-e" title="Code">💻</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/klimantje"><img src="https://avatars.githubusercontent.com/u/20017047?v=4?s=100" width="100px;" alt="klimantje"/><br /><sub><b>klimantje</b></sub></a><br /><a href="https://github.com/litestar-org/polyfactory/commits?author=klimantje" title="Code">💻</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/tcrasset"><img src="https://avatars.githubusercontent.com/u/25140344?v=4?s=100" width="100px;" alt="Tom Crasset"/><br /><sub><b>Tom Crasset</b></sub></a><br /><a href="https://github.com/litestar-org/polyfactory/commits?author=tcrasset" title="Code">💻</a></td> <td align="center" valign="top" width="14.28%"><a href="https://git.roboces.dev/catalin"><img src="https://avatars.githubusercontent.com/u/45485069?v=4?s=100" width="100px;" alt="cătălin"/><br /><sub><b>cătălin</b></sub></a><br /><a href="https://github.com/litestar-org/polyfactory/commits?author=185504a9" title="Code">💻</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/adhtruong"><img src="https://avatars.githubusercontent.com/u/40660973?v=4?s=100" width="100px;" alt="Andrew Truong"/><br /><sub><b>Andrew Truong</b></sub></a><br /><a href="https://github.com/litestar-org/polyfactory/commits?author=adhtruong" title="Code">💻</a> <a href="https://github.com/litestar-org/polyfactory/commits?author=adhtruong" title="Documentation">📖</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/anthonyjgraff"><img src="https://avatars.githubusercontent.com/u/59455370?v=4?s=100" width="100px;" alt="Anthony"/><br /><sub><b>Anthony</b></sub></a><br /><a href="https://github.com/litestar-org/polyfactory/commits?author=anthonyjgraff" title="Code">💻</a> <a href="https://github.com/litestar-org/polyfactory/commits?author=anthonyjgraff" title="Documentation">📖</a> <a href="https://github.com/litestar-org/polyfactory/commits?author=anthonyjgraff" title="Tests">⚠️</a></td> </tr> <tr> <td align="center" valign="top" width="14.28%"><a href="https://github.com/johnraz"><img src="https://avatars.githubusercontent.com/u/304164?v=4?s=100" width="100px;" alt="Jonathan Liuti"/><br /><sub><b>Jonathan Liuti</b></sub></a><br /><a href="https://github.com/litestar-org/polyfactory/commits?author=johnraz" title="Code">💻</a> <a href="https://github.com/litestar-org/polyfactory/commits?author=johnraz" title="Documentation">📖</a> <a href="https://github.com/litestar-org/polyfactory/commits?author=johnraz" title="Tests">⚠️</a></td> <td align="center" valign="top" width="14.28%"><a href="https://julio.li/"><img src="https://avatars.githubusercontent.com/u/1302493?v=4?s=100" width="100px;" alt="Julio Olivera"/><br /><sub><b>Julio Olivera</b></sub></a><br /><a href="https://github.com/litestar-org/polyfactory/commits?author=julioolvr" title="Code">💻</a> <a href="https://github.com/litestar-org/polyfactory/commits?author=julioolvr" title="Tests">⚠️</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/g0di"><img src="https://avatars.githubusercontent.com/u/2545380?v=4?s=100" width="100px;" alt="Benoît Godard"/><br /><sub><b>Benoît Godard</b></sub></a><br /><a href="https://github.com/litestar-org/polyfactory/commits?author=g0di" title="Code">💻</a> <a href="https://github.com/litestar-org/polyfactory/commits?author=g0di" title="Documentation">📖</a> <a href="https://github.com/litestar-org/polyfactory/commits?author=g0di" title="Tests">⚠️</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/hsorsky"><img src="https://avatars.githubusercontent.com/u/36887638?v=4?s=100" width="100px;" alt="Henry Sorsky"/><br /><sub><b>Henry Sorsky</b></sub></a><br /><a href="#infra-hsorsky" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/wer153"><img src="https://avatars.githubusercontent.com/u/23370765?v=4?s=100" width="100px;" alt="Kim Minki"/><br /><sub><b>Kim Minki</b></sub></a><br /><a href="https://github.com/litestar-org/polyfactory/commits?author=wer153" title="Documentation">📖</a></td> <td align="center" valign="top" width="14.28%"><a href="https://www.timdumol.com/"><img src="https://avatars.githubusercontent.com/u/49169?v=4?s=100" width="100px;" alt="Tim Joseph Dumol"/><br /><sub><b>Tim Joseph Dumol</b></sub></a><br /><a href="https://github.com/litestar-org/polyfactory/commits?author=TimDumol" title="Documentation">📖</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/wangxin688"><img src="https://avatars.githubusercontent.com/u/36665036?v=4?s=100" width="100px;" alt="jeffry"/><br /><sub><b>jeffry</b></sub></a><br /><a href="https://github.com/litestar-org/polyfactory/commits?author=wangxin688" title="Code">💻</a></td> </tr> <tr> <td align="center" valign="top" width="14.28%"><a href="https://github.com/Reskov"><img src="https://avatars.githubusercontent.com/u/4832451?v=4?s=100" width="100px;" alt="Sergey Kovalev"/><br /><sub><b>Sergey Kovalev</b></sub></a><br /><a href="https://github.com/litestar-org/polyfactory/commits?author=Reskov" title="Code">💻</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/Vegemash"><img src="https://avatars.githubusercontent.com/u/2470379?v=4?s=100" width="100px;" alt="Isaac Jackson"/><br /><sub><b>Isaac Jackson</b></sub></a><br /><a href="https://github.com/litestar-org/polyfactory/commits?author=Vegemash" title="Code">💻</a></td> </tr> </tbody> </table> <!-- markdownlint-restore --> <!-- prettier-ignore-end --> <!-- ALL-CONTRIBUTORS-LIST:END --> This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome! �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/���������������������������������������������������������������������0000775�0000000�0000000�00000000000�14721310225�0016422�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/PYPI_README.md�������������������������������������������������������0000664�0000000�0000000�00000057422�14721310225�0020554�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<!-- markdownlint-disable --> <p align="center"> <img src="https://github.com/litestar-org/branding/blob/473f54621e55cde9acbb6fcab7fc03036173eb3d/assets/Branding%20-%20PNG%20-%20Transparent/Polyfactory%20-%20Banner%20-%20Inline%20-%20Light.png?raw=true" alt="Polyfactory Logo - Light" width="100%" height="auto" /> </p> <!-- markdownlint-restore --> <div align="center"> <!-- prettier-ignore-start --> | Project | | Status | | --------- | :-- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | CI/CD | | [![Publish package](https://github.com/litestar-org/polyfactory/actions/workflows/publish.yaml/badge.svg)](https://github.com/litestar-org/polyfactory/actions/workflows/publish.yaml) [![ci](https://github.com/litestar-org/polyfactory/actions/workflows/ci.yaml/badge.svg)](https://github.com/litestar-org/polyfactory/actions/workflows/ci.yml) [![pages-build-deployment](https://github.com/litestar-org/polyfactory/actions/workflows/pages/pages-build-deployment/badge.svg)](https://github.com/litestar-org/polyfactory/actions/workflows/pages/pages-build-deployment) | | Quality | | [![Coverage](https://sonarcloud.io/api/project_badges/measure?project=litestar-org_litestar&metric=coverage)](https://sonarcloud.io/summary/new_code?id=litestar-org_litestar) [![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=litestar-org_litestar&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=litestar-org_litestar) [![Maintainability Rating](https://sonarcloud.io/api/project_badges/measure?project=litestar-org_litestar&metric=sqale_rating)](https://sonarcloud.io/summary/new_code?id=litestar-org_litestar) [![Reliability Rating](https://sonarcloud.io/api/project_badges/measure?project=litestar-org_litestar&metric=reliability_rating)](https://sonarcloud.io/summary/new_code?id=litestar-org_litestar) [![Security Rating](https://sonarcloud.io/api/project_badges/measure?project=litestar-org_litestar&metric=security_rating)](https://sonarcloud.io/summary/new_code?id=litestar-org_litestar) | | Package | | [![PyPI - Version](https://img.shields.io/pypi/v/polyfactory?labelColor=202235&color=edb641&logo=python&logoColor=edb641)](https://badge.fury.io/py/polyfactory) ![PyPI - Support Python Versions](https://img.shields.io/pypi/pyversions/polyfactory?labelColor=202235&color=edb641&logo=python&logoColor=edb641) ![Pydantic Factories PyPI - Downloads](https://img.shields.io/pypi/dm/pydantic-factories?logo=python&label=Pydantic%20Factories%20downloads&labelColor=202235&color=edb641&logoColor=edb641) ![Polyfactory PyPI - Downloads](https://img.shields.io/pypi/dm/polyfactory?logo=python&label=Polyfactory%20downloads&labelColor=202235&color=edb641&logoColor=edb641) | | Community | | [![Reddit](https://img.shields.io/reddit/subreddit-subscribers/litestarapi?label=r%2FLitestar&logo=reddit&labelColor=202235&color=edb641&logoColor=edb641)](https://reddit.com/r/litestarapi) [![Discord](https://img.shields.io/discord/919193495116337154?labelColor=202235&color=edb641&label=chat%20on%20discord&logo=discord&logoColor=edb641)](https://discord.gg/X3FJqy8d2j) [![Matrix](https://img.shields.io/badge/chat%20on%20Matrix-bridged-202235?labelColor=202235&color=edb641&logo=matrix&logoColor=edb641)](https://matrix.to/#/#litestar:matrix.org) [![Medium](https://img.shields.io/badge/Medium-202235?labelColor=202235&color=edb641&logo=medium&logoColor=edb641)](https://blog.litestar.dev) [![Twitter](https://img.shields.io/twitter/follow/LitestarAPI?labelColor=202235&color=edb641&logo=twitter&logoColor=edb641&style=flat)](https://twitter.com/LitestarAPI) [![Blog](https://img.shields.io/badge/Blog-litestar.dev-202235?logo=blogger&labelColor=202235&color=edb641&logoColor=edb641)](https://blog.litestar.dev) | | Meta | | [![Litestar Project](https://img.shields.io/badge/Litestar%20Org-%E2%AD%90%20Polyfactory-202235.svg?logo=python&labelColor=202235&color=edb641&logoColor=edb641)](https://github.com/litestar-org/polyfactory) [![types - Mypy](https://img.shields.io/badge/types-Mypy-202235.svg?logo=python&labelColor=202235&color=edb641&logoColor=edb641)](https://github.com/python/mypy) [![License - MIT](https://img.shields.io/badge/license-MIT-202235.svg?logo=python&labelColor=202235&color=edb641&logoColor=edb641)](https://spdx.org/licenses/) [![Litestar Sponsors](https://img.shields.io/badge/Sponsor-%E2%9D%A4-%23edb641.svg?&logo=github&logoColor=edb641&labelColor=202235)](https://github.com/sponsors/litestar-org) [![linting - Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/charliermarsh/ruff/main/assets/badge/v2.json&labelColor=202235)](https://github.com/astral-sh/ruff) [![code style - Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/format.json&labelColor=202235)](https://github.com/astral-sh/ruff) [![Sourcery](https://img.shields.io/badge/Sourcery-enabled-edb641?labelColor=202235&logoColor=edb641)](https://sourcery.ai) [![All Contributors](https://img.shields.io/github/all-contributors/litestar-org/polyfactory?labelColor=202235&color=edb641&logoColor=edb641)](#contributors-) | <!-- prettier-ignore-end --> </div> <!-- markdownlint-restore --> # Polyfactory Polyfactory is a simple and powerful mock data generation library, based around type hints and supporting dataclasses, typed-dicts, pydantic models, msgspec structs and more. Polyfactory part of the Litestar project and as such actively maintained by a community of maintainers and contributors. ## Example ```python from dataclasses import dataclass from polyfactory.factories import DataclassFactory @dataclass class Person: name: str age: float height: float weight: float class PersonFactory(DataclassFactory[Person]): ... def test_is_person() -> None: person_instance = PersonFactory.build() assert isinstance(person_instance, Person) ``` That's it - with almost no work, we are able to create a mock data object fitting the `Person` class model definition. This is possible because of the typing information available on the dataclass, which are used as a source of truth for data generation. The factory parses the information stored in the dataclass and generates a dictionary of kwargs that are passed to `Person`. ## Documentation Usage and API reference documentation is available on https://polyfactory.litestar.dev/. ## Installation ```shell pip install polyfactory ``` ## Relation to Pydantic-Factories Prior to version 2, this library was known as [pydantic-factories](https://pypi.org/project/pydantic-factories/), a name under which it gained quite a bit of popularity. A main motivator for the 2.0 release was that we wanted to support more than just Pydantic models, something which also required a change to its core architecture. As this library would no longer be directly tied to Pydantic, `polyfactory` was chosen as its new name to reflect its capabilities; It can generate mock data for dataclasses, typed-dicts, Pydantic, odmantic, and beanie ODM models, as well as custom factories. ## Contributing This library is a community driven open source project. We welcome and encourage contributions. Please checkout the GitHub issues, read the contribution guide (at the repository's root), and you're always welcome to [join our discord server](https://discord.gg/F4jPQzHpBU). ## Contributors ✨ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)): <!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section --> <!-- prettier-ignore-start --> <!-- markdownlint-disable --> <table> <tbody> <tr> <td align="center" valign="top" width="14.28%"><a href="https://github.com/Goldziher"><img src="https://avatars.githubusercontent.com/u/30733348?v=4?s=100" width="100px;" alt="Na'aman Hirschfeld"/><br /><sub><b>Na'aman Hirschfeld</b></sub></a><br /><a href="#maintenance-Goldziher" title="Maintenance">🚧</a> <a href="#infra-Goldziher" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="https://github.com/litestar-org/polyfactory/commits?author=Goldziher" title="Tests">⚠️</a> <a href="https://github.com/litestar-org/polyfactory/commits?author=Goldziher" title="Code">💻</a> <a href="https://github.com/litestar-org/polyfactory/commits?author=Goldziher" title="Documentation">📖</a></td> <td align="center" valign="top" width="14.28%"><a href="https://scriptr.dev/"><img src="https://avatars.githubusercontent.com/u/45884264?v=4?s=100" width="100px;" alt="Jacob Coffee"/><br /><sub><b>Jacob Coffee</b></sub></a><br /><a href="#maintenance-JacobCoffee" title="Maintenance">🚧</a> <a href="https://github.com/litestar-org/polyfactory/commits?author=JacobCoffee" title="Documentation">📖</a> <a href="https://github.com/litestar-org/polyfactory/commits?author=JacobCoffee" title="Tests">⚠️</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/provinzkraut"><img src="https://avatars.githubusercontent.com/u/25355197?v=4?s=100" width="100px;" alt="Janek Nouvertné"/><br /><sub><b>Janek Nouvertné</b></sub></a><br /><a href="#maintenance-provinzkraut" title="Maintenance">🚧</a> <a href="https://github.com/litestar-org/polyfactory/commits?author=provinzkraut" title="Documentation">📖</a> <a href="https://github.com/litestar-org/polyfactory/commits?author=provinzkraut" title="Tests">⚠️</a> <a href="https://github.com/litestar-org/polyfactory/commits?author=provinzkraut" title="Code">💻</a></td> <td align="center" valign="top" width="14.28%"><a href="https://schutt.io"><img src="https://avatars.githubusercontent.com/u/20659309?v=4?s=100" width="100px;" alt="Peter Schutt"/><br /><sub><b>Peter Schutt</b></sub></a><br /><a href="#maintenance-peterschutt" title="Maintenance">🚧</a> <a href="https://github.com/litestar-org/polyfactory/commits?author=peterschutt" title="Tests">⚠️</a> <a href="https://github.com/litestar-org/polyfactory/commits?author=peterschutt" title="Code">💻</a> <a href="https://github.com/litestar-org/polyfactory/commits?author=peterschutt" title="Documentation">📖</a></td> <td align="center" valign="top" width="14.28%"><a href="https://czaplicki.it/"><img src="https://avatars.githubusercontent.com/u/9108586?v=4?s=100" width="100px;" alt="Marek Czaplicki"/><br /><sub><b>Marek Czaplicki</b></sub></a><br /><a href="https://github.com/litestar-org/polyfactory/commits?author=mdczaplicki" title="Code">💻</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/przybylop"><img src="https://avatars.githubusercontent.com/u/82805821?v=4?s=100" width="100px;" alt="Piotr Przybyło"/><br /><sub><b>Piotr Przybyło</b></sub></a><br /><a href="https://github.com/litestar-org/polyfactory/commits?author=przybylop" title="Code">💻</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/sygutss"><img src="https://avatars.githubusercontent.com/u/48909366?v=4?s=100" width="100px;" alt="sygutss"/><br /><sub><b>sygutss</b></sub></a><br /><a href="https://github.com/litestar-org/polyfactory/issues?q=author%3Asygutss" title="Bug reports">🐛</a> <a href="https://github.com/litestar-org/polyfactory/commits?author=sygutss" title="Code">💻</a></td> </tr> <tr> <td align="center" valign="top" width="14.28%"><a href="https://github.com/chrisbeardy"><img src="https://avatars.githubusercontent.com/u/20585410?v=4?s=100" width="100px;" alt="chrisbeardy"/><br /><sub><b>chrisbeardy</b></sub></a><br /><a href="https://github.com/litestar-org/polyfactory/commits?author=chrisbeardy" title="Documentation">📖</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/guacs"><img src="https://avatars.githubusercontent.com/u/126393040?v=4?s=100" width="100px;" alt="guacs"/><br /><sub><b>guacs</b></sub></a><br /><a href="https://github.com/litestar-org/polyfactory/commits?author=guacs" title="Code">💻</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/VSHUMILIN97"><img src="https://avatars.githubusercontent.com/u/27234763?v=4?s=100" width="100px;" alt="Vadim"/><br /><sub><b>Vadim</b></sub></a><br /><a href="https://github.com/litestar-org/polyfactory/commits?author=VSHUMILIN97" title="Code">💻</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/Simske"><img src="https://avatars.githubusercontent.com/u/2445660?v=4?s=100" width="100px;" alt="Simske"/><br /><sub><b>Simske</b></sub></a><br /><a href="https://github.com/litestar-org/polyfactory/commits?author=Simske" title="Code">💻</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/sondrelg"><img src="https://avatars.githubusercontent.com/u/25310870?v=4?s=100" width="100px;" alt="Sondre Lillebø Gundersen"/><br /><sub><b>Sondre Lillebø Gundersen</b></sub></a><br /><a href="https://github.com/litestar-org/polyfactory/commits?author=sondrelg" title="Code">💻</a></td> <td align="center" valign="top" width="14.28%"><a href="https://mciszczon.pl/"><img src="https://avatars.githubusercontent.com/u/1078369?v=4?s=100" width="100px;" alt="Mateusz Ciszczoń"/><br /><sub><b>Mateusz Ciszczoń</b></sub></a><br /><a href="https://github.com/litestar-org/polyfactory/commits?author=mciszczon" title="Code">💻</a></td> <td align="center" valign="top" width="14.28%"><a href="https://www.linkedin.com/in/pedro-bernardes/"><img src="https://avatars.githubusercontent.com/u/18899993?v=4?s=100" width="100px;" alt="Pedro Bernardes"/><br /><sub><b>Pedro Bernardes</b></sub></a><br /><a href="https://github.com/litestar-org/polyfactory/commits?author=phbernardes" title="Code">💻</a></td> </tr> <tr> <td align="center" valign="top" width="14.28%"><a href="https://github.com/lindycoder"><img src="https://avatars.githubusercontent.com/u/12926519?v=4?s=100" width="100px;" alt="Martin Roy"/><br /><sub><b>Martin Roy</b></sub></a><br /><a href="https://github.com/litestar-org/polyfactory/commits?author=lindycoder" title="Code">💻</a></td> <td align="center" valign="top" width="14.28%"><a href="http://matthewtyleraylward.com"><img src="https://avatars.githubusercontent.com/u/19205392?v=4?s=100" width="100px;" alt="Matthew Aylward "/><br /><sub><b>Matthew Aylward </b></sub></a><br /><a href="https://github.com/litestar-org/polyfactory/commits?author=Butch78" title="Code">💻</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/EltonChou"><img src="https://avatars.githubusercontent.com/u/12560310?v=4?s=100" width="100px;" alt="Elton H.Y. Chou"/><br /><sub><b>Elton H.Y. Chou</b></sub></a><br /><a href="https://github.com/litestar-org/polyfactory/commits?author=EltonChou" title="Code">💻</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/nguyent"><img src="https://avatars.githubusercontent.com/u/576848?v=4?s=100" width="100px;" alt="Thang"/><br /><sub><b>Thang</b></sub></a><br /><a href="https://github.com/litestar-org/polyfactory/commits?author=nguyent" title="Code">💻</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/DaanRademaker"><img src="https://avatars.githubusercontent.com/u/29598493?v=4?s=100" width="100px;" alt="Daan"/><br /><sub><b>Daan</b></sub></a><br /><a href="https://github.com/litestar-org/polyfactory/commits?author=DaanRademaker" title="Code">💻</a></td> <td align="center" valign="top" width="14.28%"><a href="https://lyz-code.github.io/blue-book/"><img src="https://avatars.githubusercontent.com/u/24810987?v=4?s=100" width="100px;" alt="Lyz"/><br /><sub><b>Lyz</b></sub></a><br /><a href="https://github.com/litestar-org/polyfactory/commits?author=lyz-code" title="Code">💻</a></td> <td align="center" valign="top" width="14.28%"><a href="https://portfolio.schiffer.pro/"><img src="https://avatars.githubusercontent.com/u/3502492?v=4?s=100" width="100px;" alt="Thorin Schiffer"/><br /><sub><b>Thorin Schiffer</b></sub></a><br /><a href="https://github.com/litestar-org/polyfactory/commits?author=thorin-schiffer" title="Code">💻</a></td> </tr> <tr> <td align="center" valign="top" width="14.28%"><a href="https://github.com/Iipin"><img src="https://avatars.githubusercontent.com/u/52832022?v=4?s=100" width="100px;" alt="Iipin"/><br /><sub><b>Iipin</b></sub></a><br /><a href="https://github.com/litestar-org/polyfactory/commits?author=Iipin" title="Code">💻</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/avihai-yosef"><img src="https://avatars.githubusercontent.com/u/79567307?v=4?s=100" width="100px;" alt="avihai-yosef"/><br /><sub><b>avihai-yosef</b></sub></a><br /><a href="https://github.com/litestar-org/polyfactory/commits?author=avihai-yosef" title="Code">💻</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/anthonyh209"><img src="https://avatars.githubusercontent.com/u/33107540?v=4?s=100" width="100px;" alt="anthonyh209"/><br /><sub><b>anthonyh209</b></sub></a><br /><a href="https://github.com/litestar-org/polyfactory/commits?author=anthonyh209" title="Code">💻</a></td> <td align="center" valign="top" width="14.28%"><a href="http://linkedin.com/in/roman-reznikov"><img src="https://avatars.githubusercontent.com/u/44291988?v=4?s=100" width="100px;" alt="Roman Reznikov"/><br /><sub><b>Roman Reznikov</b></sub></a><br /><a href="https://github.com/litestar-org/polyfactory/commits?author=ReznikovRoman" title="Code">💻</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/gigelu"><img src="https://avatars.githubusercontent.com/u/270697?v=4?s=100" width="100px;" alt="gigelu"/><br /><sub><b>gigelu</b></sub></a><br /><a href="https://github.com/litestar-org/polyfactory/commits?author=gigelu" title="Code">💻</a></td> <td align="center" valign="top" width="14.28%"><a href="https://github.com/roeeyn"><img src="https://avatars.githubusercontent.com/u/13385000?v=4?s=100" width="100px;" alt="Rodrigo Medina"/><br /><sub><b>Rodrigo Medina</b></sub></a><br /><a href="https://github.com/litestar-org/polyfactory/commits?author=roeeyn" title="Code">💻</a></td> <td align="center" valign="top" width="14.28%"><a href="https://gerritegnew.info/"><img src="https://avatars.githubusercontent.com/u/35822787?v=4?s=100" width="100px;" alt="Gerrit Egnew"/><br /><sub><b>Gerrit Egnew</b></sub></a><br /><a href="https://github.com/litestar-org/polyfactory/commits?author=gegnew" title="Code">💻</a></td> </tr> <tr> <td align="center" valign="top" width="14.28%"><a href="https://github.com/danielkatzan"><img src="https://avatars.githubusercontent.com/u/9249066?v=4?s=100" width="100px;" alt="danielkatzan"/><br /><sub><b>danielkatzan</b></sub></a><br /><a href="https://github.com/litestar-org/polyfactory/commits?author=danielkatzan" title="Documentation">📖</a></td> </tr> </tbody> </table> <!-- markdownlint-restore --> <!-- prettier-ignore-end --> <!-- ALL-CONTRIBUTORS-LIST:END --> This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome! ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/__init__.py����������������������������������������������������������0000664�0000000�0000000�00000000000�14721310225�0020521�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/_static/�������������������������������������������������������������0000775�0000000�0000000�00000000000�14721310225�0020050�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/_static/logo.svg�����������������������������������������������������0000664�0000000�0000000�00000007640�14721310225�0021540�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<svg xmlns="http://www.w3.org/2000/svg" width="500" zoomAndPan="magnify" viewBox="0 0 375 374.999991" height="500" preserveAspectRatio="xMidYMid meet" version="1.0"> <defs> <clipPath id="9eb7762d41"> <path d="M 15.933594 105 L 328 105 L 328 259 L 15.933594 259 Z M 15.933594 105 " clip-rule="nonzero"/> </clipPath> <clipPath id="183d3cc178"> <path d="M 142 78.769531 L 359.433594 78.769531 L 359.433594 296.269531 L 142 296.269531 Z M 142 78.769531 " clip-rule="nonzero"/> </clipPath> </defs> <g clip-path="url(#9eb7762d41)"> <path fill="#edb641" d="M 147.625 240.3125 C 161.5 233.984375 173.554688 227.011719 183.425781 220.550781 C 202.304688 208.203125 226.4375 185.242188 227.761719 183.410156 L 218.917969 177.503906 L 211.257812 172.386719 L 235.503906 171.441406 L 243.296875 171.136719 L 245.414062 163.640625 L 252.007812 140.304688 L 260.402344 163.054688 L 263.097656 170.363281 L 270.890625 170.058594 L 295.136719 169.113281 L 276.078125 184.117188 L 269.953125 188.9375 L 272.652344 196.25 L 281.046875 218.996094 L 260.871094 205.523438 L 254.390625 201.195312 L 248.265625 206.015625 L 229.207031 221.023438 L 232.480469 209.425781 L 235.796875 197.691406 L 236.207031 196.234375 C 213.003906 213.585938 180.546875 230.304688 161.140625 236.488281 C 156.6875 237.90625 152.183594 239.179688 147.625 240.3125 Z M 101.992188 258.078125 C 136.382812 256.734375 177.355469 248 217.675781 222.363281 L 209.90625 249.867188 L 254.910156 214.4375 L 302.539062 246.246094 L 282.71875 192.539062 L 327.71875 157.109375 L 270.46875 159.34375 L 250.648438 105.636719 L 235.085938 160.726562 L 177.835938 162.964844 L 210.980469 185.097656 C 189.164062 204.921875 134.445312 247.195312 61.957031 250.03125 C 47.300781 250.601562 31.914062 249.558594 15.933594 246.394531 C 15.933594 246.394531 52.011719 260.035156 101.992188 258.078125 " fill-opacity="1" fill-rule="nonzero"/> </g> <g clip-path="url(#183d3cc178)"> <path fill="#edb641" d="M 250.789062 78.96875 C 190.78125 78.96875 142.140625 127.570312 142.140625 187.519531 C 142.140625 198.875 143.886719 209.816406 147.121094 220.101562 C 151.847656 217.75 156.363281 215.316406 160.660156 212.84375 C 158.394531 204.789062 157.183594 196.296875 157.183594 187.519531 C 157.183594 135.871094 199.089844 93.996094 250.789062 93.996094 C 302.484375 93.996094 344.390625 135.871094 344.390625 187.519531 C 344.390625 239.171875 302.484375 281.042969 250.789062 281.042969 C 222.75 281.042969 197.597656 268.722656 180.441406 249.210938 C 175.453125 251.152344 170.402344 252.917969 165.289062 254.511719 C 185.183594 279.816406 216.082031 296.070312 250.789062 296.070312 C 310.792969 296.070312 359.433594 247.472656 359.433594 187.519531 C 359.433594 127.570312 310.792969 78.96875 250.789062 78.96875 " fill-opacity="1" fill-rule="nonzero"/> </g> <path fill="#edb641" d="M 92.292969 173.023438 L 98.289062 191.460938 L 117.691406 191.460938 L 101.992188 202.855469 L 107.988281 221.292969 L 92.292969 209.898438 L 76.59375 221.292969 L 82.589844 202.855469 L 66.894531 191.460938 L 86.296875 191.460938 L 92.292969 173.023438 " fill-opacity="1" fill-rule="nonzero"/> <path fill="#edb641" d="M 120.214844 112.25 L 125.390625 128.167969 L 142.140625 128.167969 L 128.589844 138 L 133.765625 153.917969 L 120.214844 144.082031 L 106.664062 153.917969 L 111.839844 138 L 98.289062 128.167969 L 115.039062 128.167969 L 120.214844 112.25 " fill-opacity="1" fill-rule="nonzero"/> <path fill="#edb641" d="M 34.695312 209.136719 L 37.71875 218.421875 L 47.492188 218.421875 L 39.585938 224.160156 L 42.605469 233.449219 L 34.695312 227.707031 L 26.792969 233.449219 L 29.8125 224.160156 L 21.90625 218.421875 L 31.679688 218.421875 L 34.695312 209.136719 " fill-opacity="1" fill-rule="nonzero"/> </svg> ������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/changelog.rst��������������������������������������������������������0000664�0000000�0000000�00000310376�14721310225�0021115�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������========= Changelog ========= All commits to this project will be documented in this file. [unreleased] ------------ `67c5720 <https://github.com/litestar-org/polyfactory/commit/67c57208de5ce993bdb2c7888864ac4e71964511>`_ is the last commit in the changelog before unreleased changes. Bug Fixes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`24701eb <https://github.com/litestar-org/polyfactory/commit/24701eb593493f7c038709b1327dbf6dd8942e87>`_) - Constrained 0 length lists (#570) by `@marcozzxx810 <https://github.com/marcozzxx810>`_ in `#570 <https://github.com/litestar-org/polyfactory/pull/570>`_ * (`6f5b78c <https://github.com/litestar-org/polyfactory/commit/6f5b78cc5ef3f0fb1037d17d06837af54aac586d>`_) - Use provider map for any in coverage (#574) by `@adhtruong <https://github.com/adhtruong>`_ in `#574 <https://github.com/litestar-org/polyfactory/pull/574>`_ * (`4aaf656 <https://github.com/litestar-org/polyfactory/commit/4aaf656baa5b612fa3b63c6047b653b9b785f60d>`_) - Tuple randomized length (#573) by `@adhtruong <https://github.com/adhtruong>`_ in `#573 <https://github.com/litestar-org/polyfactory/pull/573>`_ * (`9a83ad6 <https://github.com/litestar-org/polyfactory/commit/9a83ad6354d675b42eb514f9354e845490608ba6>`_) - Adjust min/max items to valid lengths for Set[Enum] fields (#567) by `@adrianeboyd <https://github.com/adrianeboyd>`_ in `#567 <https://github.com/litestar-org/polyfactory/pull/567>`_ * (`135d7fe <https://github.com/litestar-org/polyfactory/commit/135d7fea8d939a1fa8c87838d2b705db8968dccd>`_) - Handle Optional type recursive models (#584) by `@adhtruong <https://github.com/adhtruong>`_ in `#584 <https://github.com/litestar-org/polyfactory/pull/584>`_ * (`6440faa <https://github.com/litestar-org/polyfactory/commit/6440faa24abfc34c2d10e31797224f5aec2d43c0>`_) - Handle recursive collections (#587) by `@adhtruong <https://github.com/adhtruong>`_ in `#587 <https://github.com/litestar-org/polyfactory/pull/587>`_ Documentation ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`841831d <https://github.com/litestar-org/polyfactory/commit/841831d12f59a0825e490e71fdbc32744c433565>`_) - Swap word with its antonym to match the context (#575) by `@UncleGoogle <https://github.com/UncleGoogle>`_ in `#575 <https://github.com/litestar-org/polyfactory/pull/575>`_ Features ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`c0c2704 <https://github.com/litestar-org/polyfactory/commit/c0c27049afc9dd60395d5dd087f47ee700e1a6a7>`_) - Enhance register_fixture return type annotation (#581) by `@giulioindev <https://github.com/giulioindev>`_ in `#581 <https://github.com/litestar-org/polyfactory/pull/581>`_ Build ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`d75b1d2 <https://github.com/litestar-org/polyfactory/commit/d75b1d2eee3c042b3bf1ea7b8c2b0b6a744df75d>`_) - Update pre-commit dependencies (#571) by `@adhtruong <https://github.com/adhtruong>`_ in `#571 <https://github.com/litestar-org/polyfactory/pull/571>`_ `Release [v2.16.2] - 2024-07-09 <https://github.com/litestar-org/polyfactory/releases/tag/v2.16.2>`_ ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * `See All commits in v2.16.2 <https://github.com/litestar-org/polyfactory/commits/v2.16.2>`_ `23281ee <https://github.com/litestar-org/polyfactory/commit/23281eed6c596a7defdc022e8d595cb3f4d2f169>`_ ... `67c5720 <https://github.com/litestar-org/polyfactory/commit/67c57208de5ce993bdb2c7888864ac4e71964511>`_ | `See diff for 2.16.2 <https://github.com/litestar-org/polyfactory/compare/23281eed6c596a7defdc022e8d595cb3f4d2f169...67c57208de5ce993bdb2c7888864ac4e71964511>`_ Bug Fixes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`3bb97e0 <https://github.com/litestar-org/polyfactory/commit/3bb97e0672d7fadb8532a882e62922b135c81fec>`_) - Nested model in collection build context (#564) by `@sam-or <https://github.com/sam-or>`_ in `#564 <https://github.com/litestar-org/polyfactory/pull/564>`_ Miscellaneous Tasks ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`67c5720 <https://github.com/litestar-org/polyfactory/commit/67c57208de5ce993bdb2c7888864ac4e71964511>`_) - Bump patch version by `@guacs <https://github.com/guacs>`_ `Release [v2.16.1] - 2024-07-08 <https://github.com/litestar-org/polyfactory/releases/tag/v2.16.1>`_ ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * `See All commits in v2.16.1 <https://github.com/litestar-org/polyfactory/commits/v2.16.1>`_ `4928f07 <https://github.com/litestar-org/polyfactory/commit/4928f0735ad58adc63f093062b4938dfc5003ea9>`_ ... `23281ee <https://github.com/litestar-org/polyfactory/commit/23281eed6c596a7defdc022e8d595cb3f4d2f169>`_ | `See diff for 2.16.1 <https://github.com/litestar-org/polyfactory/compare/4928f0735ad58adc63f093062b4938dfc5003ea9...23281eed6c596a7defdc022e8d595cb3f4d2f169>`_ Bug Fixes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`86869c2 <https://github.com/litestar-org/polyfactory/commit/86869c231255f9269420039b35b3b2f3572a0255>`_) - Use provider map for generating value for 'Any' (#522) by `@guacs <https://github.com/guacs>`_ in `#522 <https://github.com/litestar-org/polyfactory/pull/522>`_ * (`cbe6dfc <https://github.com/litestar-org/polyfactory/commit/cbe6dfce14b1778cf2434a93addeb6936ce3c61b>`_) - Pydantic factory_use_construct is not propagated to the nested (#549) by `@Reskov <https://github.com/Reskov>`_ in `#549 <https://github.com/litestar-org/polyfactory/pull/549>`_ * (`b09bf64 <https://github.com/litestar-org/polyfactory/commit/b09bf64e56ac9bf32ba77b835abbc43ededabd9f>`_) - Send correct field_meta to avoid over nesting (#527) by `@Vegemash <https://github.com/Vegemash>`_ in `#527 <https://github.com/litestar-org/polyfactory/pull/527>`_ Documentation ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`740fd34 <https://github.com/litestar-org/polyfactory/commit/740fd345685df6b313f8a4e12e041129b4dcd2e1>`_) - Link to GitHub repo (#547) by `@Alc-Alc <https://github.com/Alc-Alc>`_ in `#547 <https://github.com/litestar-org/polyfactory/pull/547>`_ * (`c34e72e <https://github.com/litestar-org/polyfactory/commit/c34e72e96d0530293739442a48a679dc85ec33fa>`_) - Add Reskov as a contributor for code (#556) by `@allcontributors[bot] <https://github.com/allcontributors[bot]>`_ in `#556 <https://github.com/litestar-org/polyfactory/pull/556>`_ * (`3320989 <https://github.com/litestar-org/polyfactory/commit/3320989ed73265861ec11d09be5c57ed8f06c03f>`_) - Add Vegemash as a contributor for code (#562) by `@allcontributors[bot] <https://github.com/allcontributors[bot]>`_ in `#562 <https://github.com/litestar-org/polyfactory/pull/562>`_ Miscellaneous Tasks ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`f8e9318 <https://github.com/litestar-org/polyfactory/commit/f8e93188b447b6c28ee4466da3a128f2edafc5bd>`_) - Migrate formatting to ruff (#554) by `@adhtruong <https://github.com/adhtruong>`_ in `#554 <https://github.com/litestar-org/polyfactory/pull/554>`_ * (`36a9cc1 <https://github.com/litestar-org/polyfactory/commit/36a9cc15d91d6a64e6aecf76757c10b11bc7a87c>`_) - Bump pydantic (#561) by `@Vegemash <https://github.com/Vegemash>`_ in `#561 <https://github.com/litestar-org/polyfactory/pull/561>`_ * (`23281ee <https://github.com/litestar-org/polyfactory/commit/23281eed6c596a7defdc022e8d595cb3f4d2f169>`_) - Bump patch version by `@guacs <https://github.com/guacs>`_ `Release [v2.16.0] - 2024-05-13 <https://github.com/litestar-org/polyfactory/releases/tag/v2.16.0>`_ ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * `See All commits in v2.16.0 <https://github.com/litestar-org/polyfactory/commits/v2.16.0>`_ `1d1c7f9 <https://github.com/litestar-org/polyfactory/commit/1d1c7f9d02f9c7a8eb977dc0624bf5a045d55ddc>`_ ... `4928f07 <https://github.com/litestar-org/polyfactory/commit/4928f0735ad58adc63f093062b4938dfc5003ea9>`_ | `See diff for 2.16.0 <https://github.com/litestar-org/polyfactory/compare/1d1c7f9d02f9c7a8eb977dc0624bf5a045d55ddc...4928f0735ad58adc63f093062b4938dfc5003ea9>`_ Bug Fixes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`719495e <https://github.com/litestar-org/polyfactory/commit/719495e6dca5c6938975b6bc0456205d28e2c90d>`_) - Ignore non-columns types (#510) by `@adhtruong <https://github.com/adhtruong>`_ in `#510 <https://github.com/litestar-org/polyfactory/pull/510>`_ * (`bb04b4e <https://github.com/litestar-org/polyfactory/commit/bb04b4e81764289ba5a138c0b82faa73bb4e5257>`_) - Favour SA mapped type over impl type (#513) by `@adhtruong <https://github.com/adhtruong>`_ in `#513 <https://github.com/litestar-org/polyfactory/pull/513>`_ * (`0032b5e <https://github.com/litestar-org/polyfactory/commit/0032b5e962906239ecd4c4bd7276dc0d9e9f142d>`_) - Add footer to changelog generation by `@JacobCoffee <https://github.com/JacobCoffee>`_ * (`5fd7d6c <https://github.com/litestar-org/polyfactory/commit/5fd7d6c2bedb3c602e009618137c6ab215172625>`_) - Resolve mypy issues (#540) by `@adhtruong <https://github.com/adhtruong>`_ in `#540 <https://github.com/litestar-org/polyfactory/pull/540>`_ * (`9e6edab <https://github.com/litestar-org/polyfactory/commit/9e6edabd4ee5242c54f3ddb66e539a415da86901>`_) - Fix json type error and pg dialect default value e… (#542) by `@wangxin688 <https://github.com/wangxin688>`_ in `#542 <https://github.com/litestar-org/polyfactory/pull/542>`_ Documentation ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`01d1dbe <https://github.com/litestar-org/polyfactory/commit/01d1dbeb46cc722b075dba85cfd6bcb94505e65d>`_) - Apply organization theme (#533) by `@JacobCoffee <https://github.com/JacobCoffee>`_ in `#533 <https://github.com/litestar-org/polyfactory/pull/533>`_ * (`5a0a5be <https://github.com/litestar-org/polyfactory/commit/5a0a5bed4ddb679868d9365a5ffbcc6c3fed686c>`_) - Polyfactory landing page (#535) by `@JacobCoffee <https://github.com/JacobCoffee>`_ in `#535 <https://github.com/litestar-org/polyfactory/pull/535>`_ * (`2f781ee <https://github.com/litestar-org/polyfactory/commit/2f781eee7f06436661874a4e469c601bb0de6cd4>`_) - Add wangxin688 as a contributor for code (#544) by `@allcontributors[bot] <https://github.com/allcontributors[bot]>`_ in `#544 <https://github.com/litestar-org/polyfactory/pull/544>`_ Features ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`1792c19 <https://github.com/litestar-org/polyfactory/commit/1792c19fc100b16b610902c19c90b2031420c57e>`_) - Support nested type in pg.array types and others (#530) by `@wangxin688 <https://github.com/wangxin688>`_ in `#530 <https://github.com/litestar-org/polyfactory/pull/530>`_ * (`013135c <https://github.com/litestar-org/polyfactory/commit/013135c17387e451d88a7b73157ad08333649112>`_) - Refresh object in async_session after commit to db (#541) by `@wangxin688 <https://github.com/wangxin688>`_ in `#541 <https://github.com/litestar-org/polyfactory/pull/541>`_ * (`e4695a7 <https://github.com/litestar-org/polyfactory/commit/e4695a7d16e1a63b7cce036ca653d839ea0104fb>`_) - Copy mutable args (#529) by `@adhtruong <https://github.com/adhtruong>`_ in `#529 <https://github.com/litestar-org/polyfactory/pull/529>`_ Miscellaneous Tasks ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`fac9fba <https://github.com/litestar-org/polyfactory/commit/fac9fbad94f0a82a062bfdac11b2da19f906e32f>`_) - Upgrade dependencies (#517) by `@adhtruong <https://github.com/adhtruong>`_ in `#517 <https://github.com/litestar-org/polyfactory/pull/517>`_ * (`3da64f6 <https://github.com/litestar-org/polyfactory/commit/3da64f615056c8d2f11c6bfc55c86877a89c2414>`_) - Update changelog.rst (#537) by `@impaktor <https://github.com/impaktor>`_ in `#537 <https://github.com/litestar-org/polyfactory/pull/537>`_ * (`3e2d22c <https://github.com/litestar-org/polyfactory/commit/3e2d22c5bafc5ed984338be54c3eace3cacc720f>`_) - Update maintainer emails (#545) by `@guacs <https://github.com/guacs>`_ in `#545 <https://github.com/litestar-org/polyfactory/pull/545>`_ Ci ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`6507c6d <https://github.com/litestar-org/polyfactory/commit/6507c6d86094dbcf678083e3ce7d06a5b4dd2f60>`_) - Add codecov coverage, fix badges (#536) by `@JacobCoffee <https://github.com/JacobCoffee>`_ in `#536 <https://github.com/litestar-org/polyfactory/pull/536>`_ `Release [v2.15.0] - 2024-03-02 <https://github.com/litestar-org/polyfactory/releases/tag/v2.15.0>`_ ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * `See All commits in v2.15.0 <https://github.com/litestar-org/polyfactory/commits/v2.15.0>`_ `b44c68b <https://github.com/litestar-org/polyfactory/commit/b44c68b0c1d8c253f828edbbfc88c3f39ec2fdca>`_ ... `1d1c7f9 <https://github.com/litestar-org/polyfactory/commit/1d1c7f9d02f9c7a8eb977dc0624bf5a045d55ddc>`_ | `See diff for 2.15.0 <https://github.com/litestar-org/polyfactory/compare/b44c68b0c1d8c253f828edbbfc88c3f39ec2fdca...1d1c7f9d02f9c7a8eb977dc0624bf5a045d55ddc>`_ Bug Fixes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`c4e3d91 <https://github.com/litestar-org/polyfactory/commit/c4e3d919368d158f839a6ea6278a28007fb7f5dc>`_) - Prefer ``sqlalchemy.type.impl`` if it exists (#502) by `@cofin <https://github.com/cofin>`_ in `#502 <https://github.com/litestar-org/polyfactory/pull/502>`_ * (`0f8f9e8 <https://github.com/litestar-org/polyfactory/commit/0f8f9e8d0dbd6156ef55d2d61dc6831c4e59c0b0>`_) - Handle constrained unions properly (#499) by `@guacs <https://github.com/guacs>`_ in `#499 <https://github.com/litestar-org/polyfactory/pull/499>`_ Documentation ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`61c8892 <https://github.com/litestar-org/polyfactory/commit/61c889229f40e9a454b4dbbaff3e620940ea99ad>`_) - Fix typo on use_defaults (#497) by `@TimDumol <https://github.com/TimDumol>`_ in `#497 <https://github.com/litestar-org/polyfactory/pull/497>`_ * (`9e34fa7 <https://github.com/litestar-org/polyfactory/commit/9e34fa7aa36acd104e61222dac1507bc1efeefd7>`_) - Add TimDumol as a contributor for doc (#498) by `@allcontributors[bot] <https://github.com/allcontributors[bot]>`_ in `#498 <https://github.com/litestar-org/polyfactory/pull/498>`_ Features ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`46ecdc6 <https://github.com/litestar-org/polyfactory/commit/46ecdc67f998464d82cf834ff048376283e29ac8>`_) - Support Pydantic v1 and v2 simultaneously (#492) by `@guacs <https://github.com/guacs>`_ in `#492 <https://github.com/litestar-org/polyfactory/pull/492>`_ Miscellaneous Tasks ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`1078230 <https://github.com/litestar-org/polyfactory/commit/10782304e0d835a5583e7360a4712fae76749c4a>`_) - Bump pdm-project/setup-pdm from 3 to 4 (#496) by `@dependabot[bot] <https://github.com/dependabot[bot]>`_ in `#496 <https://github.com/litestar-org/polyfactory/pull/496>`_ * (`1d1c7f9 <https://github.com/litestar-org/polyfactory/commit/1d1c7f9d02f9c7a8eb977dc0624bf5a045d55ddc>`_) - Release v2.15.0 by `@guacs <https://github.com/guacs>`_ Refactor ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`2acfdc6 <https://github.com/litestar-org/polyfactory/commit/2acfdc6ab96f3ecb504c9c89960198fc8a1effd9>`_) - Change order of imports for pydantic v1 (#509) by `@guacs <https://github.com/guacs>`_ in `#509 <https://github.com/litestar-org/polyfactory/pull/509>`_ Testing ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`1ae2d52 <https://github.com/litestar-org/polyfactory/commit/1ae2d528b018ac4d6773b423f3ab8af8d91f4f7b>`_) - Refactor the tests to move tests to correct places (#495) by `@guacs <https://github.com/guacs>`_ in `#495 <https://github.com/litestar-org/polyfactory/pull/495>`_ `Release [v2.14.1] - 2024-01-20 <https://github.com/litestar-org/polyfactory/releases/tag/v2.14.1>`_ ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * `See All commits in v2.14.1 <https://github.com/litestar-org/polyfactory/commits/v2.14.1>`_ `83f2992 <https://github.com/litestar-org/polyfactory/commit/83f299231d631e5a361a515616b0d88daa1d3fd7>`_ ... `b44c68b <https://github.com/litestar-org/polyfactory/commit/b44c68b0c1d8c253f828edbbfc88c3f39ec2fdca>`_ | `See diff for 2.14.1 <https://github.com/litestar-org/polyfactory/compare/83f299231d631e5a361a515616b0d88daa1d3fd7...b44c68b0c1d8c253f828edbbfc88c3f39ec2fdca>`_ Bug Fixes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`fa50e20 <https://github.com/litestar-org/polyfactory/commit/fa50e20a333b0778119c4256558e05088b26b5c4>`_) - Handle unions properly (#491) by `@guacs <https://github.com/guacs>`_ in `#491 <https://github.com/litestar-org/polyfactory/pull/491>`_ Miscellaneous Tasks ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`b44c68b <https://github.com/litestar-org/polyfactory/commit/b44c68b0c1d8c253f828edbbfc88c3f39ec2fdca>`_) - Bump patch version by `@guacs <https://github.com/guacs>`_ `Release [v2.14.0] - 2024-01-19 <https://github.com/litestar-org/polyfactory/releases/tag/v2.14.0>`_ ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * `See All commits in v2.14.0 <https://github.com/litestar-org/polyfactory/commits/v2.14.0>`_ `8dc8e1a <https://github.com/litestar-org/polyfactory/commit/8dc8e1a4594a75ad9a16e1b6f5041b6044fc4f51>`_ ... `83f2992 <https://github.com/litestar-org/polyfactory/commit/83f299231d631e5a361a515616b0d88daa1d3fd7>`_ | `See diff for 2.14.0 <https://github.com/litestar-org/polyfactory/compare/8dc8e1a4594a75ad9a16e1b6f5041b6044fc4f51...83f299231d631e5a361a515616b0d88daa1d3fd7>`_ Bug Fixes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`fb4e50a <https://github.com/litestar-org/polyfactory/commit/fb4e50acaa0796ed7164457c6c767c3351530a81>`_) - Add min version to typing-extensions (#471) by `@hsorsky <https://github.com/hsorsky>`_ in `#471 <https://github.com/litestar-org/polyfactory/pull/471>`_ * (`40538c9 <https://github.com/litestar-org/polyfactory/commit/40538c9a0a4e9ec72b6a8864fc4e6f1293715603>`_) - Set as default type for factory only if model is defined (#479) by `@guacs <https://github.com/guacs>`_ in `#479 <https://github.com/litestar-org/polyfactory/pull/479>`_ Documentation ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`c22633c <https://github.com/litestar-org/polyfactory/commit/c22633ccf76e0fa58bc53795dfedb78a6abfb807>`_) - Add hsorsky as a contributor for infra (#477) by `@allcontributors[bot] <https://github.com/allcontributors[bot]>`_ in `#477 <https://github.com/litestar-org/polyfactory/pull/477>`_ * (`b9c2127 <https://github.com/litestar-org/polyfactory/commit/b9c212799a3144aa81b43a93f663d20e4d3036ab>`_) - Fix broken uri (#485) by `@wer153 <https://github.com/wer153>`_ in `#485 <https://github.com/litestar-org/polyfactory/pull/485>`_ * (`8f96365 <https://github.com/litestar-org/polyfactory/commit/8f963653a949ae8e5b768473bb654a989b4416fe>`_) - Add wer153 as a contributor for doc (#486) by `@allcontributors[bot] <https://github.com/allcontributors[bot]>`_ in `#486 <https://github.com/litestar-org/polyfactory/pull/486>`_ * (`7ec9eb0 <https://github.com/litestar-org/polyfactory/commit/7ec9eb010a1fae8db5807ae4f1934771909e3a38>`_) - Fix code block (#484) by `@wer153 <https://github.com/wer153>`_ in `#484 <https://github.com/litestar-org/polyfactory/pull/484>`_ Features ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`b33e662 <https://github.com/litestar-org/polyfactory/commit/b33e6621ee6add4fdd2e327834401830f6771d4b>`_) - Allow use of the default value based on configuration (#472) by `@guacs <https://github.com/guacs>`_ in `#472 <https://github.com/litestar-org/polyfactory/pull/472>`_ * (`80bd012 <https://github.com/litestar-org/polyfactory/commit/80bd012fbfb3d22e087dafd68173e633ec727175>`_) - Add recursion guard (#468) by `@adhtruong <https://github.com/adhtruong>`_ in `#468 <https://github.com/litestar-org/polyfactory/pull/468>`_ * (`c7556e8 <https://github.com/litestar-org/polyfactory/commit/c7556e8e5eafaebfdc0dded747ae4e8a144b7cc7>`_) - Pass on factory config (#483) by `@adhtruong <https://github.com/adhtruong>`_ in `#483 <https://github.com/litestar-org/polyfactory/pull/483>`_ * (`94ad561 <https://github.com/litestar-org/polyfactory/commit/94ad5611772e2bed977b693a030f517b3567a6ea>`_) - Support type alias (#487) by `@adhtruong <https://github.com/adhtruong>`_ in `#487 <https://github.com/litestar-org/polyfactory/pull/487>`_ Miscellaneous Tasks ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`bb433a4 <https://github.com/litestar-org/polyfactory/commit/bb433a4291ede8147858585ebf0cff9c7cc53eb1>`_) - Update pre commit (#478) by `@guacs <https://github.com/guacs>`_ in `#478 <https://github.com/litestar-org/polyfactory/pull/478>`_ * (`2b57706 <https://github.com/litestar-org/polyfactory/commit/2b57706fbd4b9120d5a31643e51098cac65df1da>`_) - Bump actions/cache from 3 to 4 (#488) by `@dependabot[bot] <https://github.com/dependabot[bot]>`_ in `#488 <https://github.com/litestar-org/polyfactory/pull/488>`_ * (`83f2992 <https://github.com/litestar-org/polyfactory/commit/83f299231d631e5a361a515616b0d88daa1d3fd7>`_) - Bump minor version by `@guacs <https://github.com/guacs>`_ `Release [v2.13.0] - 2023-12-19 <https://github.com/litestar-org/polyfactory/releases/tag/v2.13.0>`_ ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * `See All commits in v2.13.0 <https://github.com/litestar-org/polyfactory/commits/v2.13.0>`_ `fe05c4e <https://github.com/litestar-org/polyfactory/commit/fe05c4e60a50d8f043e4d1dbee5ea0a0c4d9abd8>`_ ... `8dc8e1a <https://github.com/litestar-org/polyfactory/commit/8dc8e1a4594a75ad9a16e1b6f5041b6044fc4f51>`_ | `See diff for 2.13.0 <https://github.com/litestar-org/polyfactory/compare/fe05c4e60a50d8f043e4d1dbee5ea0a0c4d9abd8...8dc8e1a4594a75ad9a16e1b6f5041b6044fc4f51>`_ Bug Fixes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`b479e4a <https://github.com/litestar-org/polyfactory/commit/b479e4af4617d108cbd90890cbda4408ee51ba4a>`_) - Flatten_annotation behaviour for Optional (#440) by `@sam-or <https://github.com/sam-or>`_ in `#440 <https://github.com/litestar-org/polyfactory/pull/440>`_ * (`6961eaa <https://github.com/litestar-org/polyfactory/commit/6961eaa3b65fc63b716e854bd2eb28b5bc96e029>`_) - Don't blindly suppress ValueError (#450) by `@guacs <https://github.com/guacs>`_ in `#450 <https://github.com/litestar-org/polyfactory/pull/450>`_ Features ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`623d8c9 <https://github.com/litestar-org/polyfactory/commit/623d8c97c2a178cc9721fa7b562ce2aee3eddea2>`_) - Optional ``__model__`` type (#452) by `@Mityuha <https://github.com/Mityuha>`_ in `#452 <https://github.com/litestar-org/polyfactory/pull/452>`_ Miscellaneous Tasks ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`1407f07 <https://github.com/litestar-org/polyfactory/commit/1407f07fed3223a11f89b8b9d0019d581f08c1d3>`_) - Bump actions/github-script from 6 to 7 (#438) by `@dependabot[bot] <https://github.com/dependabot[bot]>`_ in `#438 <https://github.com/litestar-org/polyfactory/pull/438>`_ * (`1a0da0d <https://github.com/litestar-org/polyfactory/commit/1a0da0df63d694525ecd19ef990495f5765ba1ba>`_) - Bump actions/setup-python from 4 to 5 (#448) by `@dependabot[bot] <https://github.com/dependabot[bot]>`_ in `#448 <https://github.com/litestar-org/polyfactory/pull/448>`_ * (`231d311 <https://github.com/litestar-org/polyfactory/commit/231d311643b6f3bc022d7de44f58866f1edcb217>`_) - Bump github/codeql-action from 2 to 3 (#458) by `@dependabot[bot] <https://github.com/dependabot[bot]>`_ in `#458 <https://github.com/litestar-org/polyfactory/pull/458>`_ * (`2695880 <https://github.com/litestar-org/polyfactory/commit/2695880a444406c21942b80ad9472ab0212dd98c>`_) - Bump dawidd6/action-download-artifact from 2 to 3 (#459) by `@dependabot[bot] <https://github.com/dependabot[bot]>`_ in `#459 <https://github.com/litestar-org/polyfactory/pull/459>`_ * (`fe342e4 <https://github.com/litestar-org/polyfactory/commit/fe342e49f35df85db27f42444cdb7e74fae090da>`_) - Bump actions/upload-artifact from 3 to 4 (#461) by `@dependabot[bot] <https://github.com/dependabot[bot]>`_ in `#461 <https://github.com/litestar-org/polyfactory/pull/461>`_ * (`a371d7f <https://github.com/litestar-org/polyfactory/commit/a371d7fb0ac0ec323aabe85dca9bb63e41cbd36a>`_) - Bump actions/download-artifact from 3 to 4 (#462) by `@dependabot[bot] <https://github.com/dependabot[bot]>`_ in `#462 <https://github.com/litestar-org/polyfactory/pull/462>`_ * (`0e2f824 <https://github.com/litestar-org/polyfactory/commit/0e2f824e72a5f682c91f1ed0a2862d36c5661e45>`_) - Bump dependencies (#465) by `@guacs <https://github.com/guacs>`_ in `#465 <https://github.com/litestar-org/polyfactory/pull/465>`_ * (`8dc8e1a <https://github.com/litestar-org/polyfactory/commit/8dc8e1a4594a75ad9a16e1b6f5041b6044fc4f51>`_) - Bump minor version by `@guacs <https://github.com/guacs>`_ `Release [v2.12.0] - 2023-11-13 <https://github.com/litestar-org/polyfactory/releases/tag/v2.12.0>`_ ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * `See All commits in v2.12.0 <https://github.com/litestar-org/polyfactory/commits/v2.12.0>`_ `b7b88a8 <https://github.com/litestar-org/polyfactory/commit/b7b88a8a86d735c36df60b2e2af3a6322008152f>`_ ... `fe05c4e <https://github.com/litestar-org/polyfactory/commit/fe05c4e60a50d8f043e4d1dbee5ea0a0c4d9abd8>`_ | `See diff for 2.12.0 <https://github.com/litestar-org/polyfactory/compare/b7b88a8a86d735c36df60b2e2af3a6322008152f...fe05c4e60a50d8f043e4d1dbee5ea0a0c4d9abd8>`_ Bug Fixes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`70d49fd <https://github.com/litestar-org/polyfactory/commit/70d49fdf6cde700a403a807d26d0d3ea5c86cd44>`_) - Handle cases where 'init=False' for dataclasses and attrs models (#433) by `@guacs <https://github.com/guacs>`_ in `#433 <https://github.com/litestar-org/polyfactory/pull/433>`_ * (`6b7512d <https://github.com/litestar-org/polyfactory/commit/6b7512d7b3d0c1b9b90dbc94e1667b40aba5bf87>`_) - Correctly handle collections with constrained items (#436) by `@guacs <https://github.com/guacs>`_ in `#436 <https://github.com/litestar-org/polyfactory/pull/436>`_ Documentation ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`2bad951 <https://github.com/litestar-org/polyfactory/commit/2bad951dc90c6acfb7f88efab0222873ba903191>`_) - Add g0di as a contributor for code, doc, and test (#432) by `@allcontributors[bot] <https://github.com/allcontributors[bot]>`_ in `#432 <https://github.com/litestar-org/polyfactory/pull/432>`_ Features ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`155f4a4 <https://github.com/litestar-org/polyfactory/commit/155f4a44d14290dce18edd2c5999f38915c3039b>`_) - Autofill ``model`` argument when calling ``create_factory`` with receiving factory ``__model__`` (#429) by `@g0di <https://github.com/g0di>`_ in `#429 <https://github.com/litestar-org/polyfactory/pull/429>`_ * (`b1e8b5e <https://github.com/litestar-org/polyfactory/commit/b1e8b5ec02fdfb37c179cf6e37bb0772e61de1aa>`_) - Model type coverage batch generation (#390) by `@sam-or <https://github.com/sam-or>`_ in `#390 <https://github.com/litestar-org/polyfactory/pull/390>`_ `Release [v2.11.0] - 2023-10-23 <https://github.com/litestar-org/polyfactory/releases/tag/v2.11.0>`_ ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * `See All commits in v2.11.0 <https://github.com/litestar-org/polyfactory/commits/v2.11.0>`_ `63aa272 <https://github.com/litestar-org/polyfactory/commit/63aa2729df553f49ed137e8e33c6a1a80387ca2b>`_ ... `b7b88a8 <https://github.com/litestar-org/polyfactory/commit/b7b88a8a86d735c36df60b2e2af3a6322008152f>`_ | `See diff for 2.11.0 <https://github.com/litestar-org/polyfactory/compare/63aa2729df553f49ed137e8e33c6a1a80387ca2b...b7b88a8a86d735c36df60b2e2af3a6322008152f>`_ Bug Fixes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`caaee0f <https://github.com/litestar-org/polyfactory/commit/caaee0f4ca372bc29763979be56f8c13ed7fec28>`_) - Handle Required and NonRequired annotations (#422) by `@guacs <https://github.com/guacs>`_ in `#422 <https://github.com/litestar-org/polyfactory/pull/422>`_ * (`5d64bde <https://github.com/litestar-org/polyfactory/commit/5d64bde08134fb30be60a3596a268c23dcd1837e>`_) - Respect override of optional nested model fields (#420) by `@julioolvr <https://github.com/julioolvr>`_ in `#420 <https://github.com/litestar-org/polyfactory/pull/420>`_ Documentation ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`e819c2f <https://github.com/litestar-org/polyfactory/commit/e819c2fe9451f92e6e175fe9c261aaf34c97eda8>`_) - Add johnraz as a contributor for code, doc, and test (#413) by `@allcontributors[bot] <https://github.com/allcontributors[bot]>`_ in `#413 <https://github.com/litestar-org/polyfactory/pull/413>`_ * (`0631d80 <https://github.com/litestar-org/polyfactory/commit/0631d808c4d984ad70cac199be2312b77a12fcb0>`_) - Update installation (#414) by `@adhtruong <https://github.com/adhtruong>`_ in `#414 <https://github.com/litestar-org/polyfactory/pull/414>`_ * (`11f234c <https://github.com/litestar-org/polyfactory/commit/11f234c030d1d2546ffbeb062ed736753bc7417c>`_) - Reorder docs and add docs on factories as fields (#418) by `@adhtruong <https://github.com/adhtruong>`_ in `#418 <https://github.com/litestar-org/polyfactory/pull/418>`_ * (`a0465c6 <https://github.com/litestar-org/polyfactory/commit/a0465c6aba403263835551dae314975631e26248>`_) - Add julioolvr as a contributor for code, and test (#425) by `@allcontributors[bot] <https://github.com/allcontributors[bot]>`_ in `#425 <https://github.com/litestar-org/polyfactory/pull/425>`_ Features ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`5fefa41 <https://github.com/litestar-org/polyfactory/commit/5fefa4142940019ebd20703663a6888766cc49ad>`_) - Check if fields declared on the factory belong to the model (#405) by `@johnraz <https://github.com/johnraz>`_ in `#405 <https://github.com/litestar-org/polyfactory/pull/405>`_ * (`e1f7a47 <https://github.com/litestar-org/polyfactory/commit/e1f7a47c6e3c979f8f43ce6ee612f417d2f3c03b>`_) - Support annotation with Constraints (#411) by `@guacs <https://github.com/guacs>`_ in `#411 <https://github.com/litestar-org/polyfactory/pull/411>`_ * (`0717951 <https://github.com/litestar-org/polyfactory/commit/07179513fc4e27b7466f5627cf252be535b81b61>`_) - Deprecate FieldMeta collection params (#417) by `@adhtruong <https://github.com/adhtruong>`_ in `#417 <https://github.com/litestar-org/polyfactory/pull/417>`_ Miscellaneous Tasks ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`b7b88a8 <https://github.com/litestar-org/polyfactory/commit/b7b88a8a86d735c36df60b2e2af3a6322008152f>`_) - Prepare for releasing v2.11 (#427) by `@guacs <https://github.com/guacs>`_ in `#427 <https://github.com/litestar-org/polyfactory/pull/427>`_ `Release [v2.10.0] - 2023-10-16 <https://github.com/litestar-org/polyfactory/releases/tag/v2.10.0>`_ ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * `See All commits in v2.10.0 <https://github.com/litestar-org/polyfactory/commits/v2.10.0>`_ `f2c6fe1 <https://github.com/litestar-org/polyfactory/commit/f2c6fe19eb632b04b0efa20b909df96e6d9c6c68>`_ ... `63aa272 <https://github.com/litestar-org/polyfactory/commit/63aa2729df553f49ed137e8e33c6a1a80387ca2b>`_ | `See diff for 2.10.0 <https://github.com/litestar-org/polyfactory/compare/f2c6fe19eb632b04b0efa20b909df96e6d9c6c68...63aa2729df553f49ed137e8e33c6a1a80387ca2b>`_ Bug Fixes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`8c88293 <https://github.com/litestar-org/polyfactory/commit/8c88293e71045fb94c2e5657ab2b8062cb84dbd2>`_) - Properly resolve dataclass forward references (#383) by `@guacs <https://github.com/guacs>`_ in `#383 <https://github.com/litestar-org/polyfactory/pull/383>`_ * (`0064240 <https://github.com/litestar-org/polyfactory/commit/00642404e0a1a61052cbf9c1c901d6aee241ff70>`_) - Update makefile (#399) by `@JacobCoffee <https://github.com/JacobCoffee>`_ in `#399 <https://github.com/litestar-org/polyfactory/pull/399>`_ * (`89cd351 <https://github.com/litestar-org/polyfactory/commit/89cd35186a6dd7fd6b86e32e83caa2fad36ee194>`_) - Decouple the handling of collection length configuration from ``FieldMeta`` (#407) by `@guacs <https://github.com/guacs>`_ in `#407 <https://github.com/litestar-org/polyfactory/pull/407>`_ Documentation ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`c1edfd5 <https://github.com/litestar-org/polyfactory/commit/c1edfd5b135d9042caa02a4dd4d50b276a0ca829>`_) - Install all dependencies for docs build (#404) by `@adhtruong <https://github.com/adhtruong>`_ in `#404 <https://github.com/litestar-org/polyfactory/pull/404>`_ Features ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`cabe03c <https://github.com/litestar-org/polyfactory/commit/cabe03c29cae8ac09c9d51e7f355d324e6740bd9>`_) - Support sqlalchemy 1.4 (#385) by `@adhtruong <https://github.com/adhtruong>`_ in `#385 <https://github.com/litestar-org/polyfactory/pull/385>`_ Miscellaneous Tasks ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`63aa272 <https://github.com/litestar-org/polyfactory/commit/63aa2729df553f49ed137e8e33c6a1a80387ca2b>`_) - Prepare for releasing v2.10 (#410) by `@guacs <https://github.com/guacs>`_ in `#410 <https://github.com/litestar-org/polyfactory/pull/410>`_ Refactor ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`79360f1 <https://github.com/litestar-org/polyfactory/commit/79360f18340da6ab67808a4a177349b206432bc9>`_) - Move creation of pydantic provider map (#396) by `@guacs <https://github.com/guacs>`_ in `#396 <https://github.com/litestar-org/polyfactory/pull/396>`_ * (`f555636 <https://github.com/litestar-org/polyfactory/commit/f555636bee6aa0ebf2c4f2c05cdb24a2e143ff75>`_) - Refactor the msgspec factory to use the fields API (#409) by `@guacs <https://github.com/guacs>`_ in `#409 <https://github.com/litestar-org/polyfactory/pull/409>`_ Ci ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`8ef78b8 <https://github.com/litestar-org/polyfactory/commit/8ef78b8c3eb9d18a9f88b05f02e86378bc3769bf>`_) - Fix alternative version installation (#389) by `@adhtruong <https://github.com/adhtruong>`_ in `#389 <https://github.com/litestar-org/polyfactory/pull/389>`_ Infra ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`eddb978 <https://github.com/litestar-org/polyfactory/commit/eddb9789b45836c3619d97d03b85c90f66ed1099>`_) - Migrate to pdm and full ruff (#384) by `@JacobCoffee <https://github.com/JacobCoffee>`_ in `#384 <https://github.com/litestar-org/polyfactory/pull/384>`_ `Release [v2.9.0] - 2023-09-19 <https://github.com/litestar-org/polyfactory/releases/tag/v2.9.0>`_ ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * `See All commits in v2.9.0 <https://github.com/litestar-org/polyfactory/commits/v2.9.0>`_ `ebf30ff <https://github.com/litestar-org/polyfactory/commit/ebf30ff6e05807ee6073f1fb04667f17498424d5>`_ ... `f2c6fe1 <https://github.com/litestar-org/polyfactory/commit/f2c6fe19eb632b04b0efa20b909df96e6d9c6c68>`_ | `See diff for 2.9.0 <https://github.com/litestar-org/polyfactory/compare/ebf30ff6e05807ee6073f1fb04667f17498424d5...f2c6fe19eb632b04b0efa20b909df96e6d9c6c68>`_ Bug Fixes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`2a20513 <https://github.com/litestar-org/polyfactory/commit/2a20513621e1c7c7c1f53c66ad43880b4695ea07>`_) - Properly type hint create_factory (#360) by `@guacs <https://github.com/guacs>`_ in `#360 <https://github.com/litestar-org/polyfactory/pull/360>`_ * (`6cc7b03 <https://github.com/litestar-org/polyfactory/commit/6cc7b03067463e1b4d8a8a007b78a44265e6de36>`_) - ``AttrsFactory`` fixes (#370) by `@guacs <https://github.com/guacs>`_ in `#370 <https://github.com/litestar-org/polyfactory/pull/370>`_ * (`8e41372 <https://github.com/litestar-org/polyfactory/commit/8e41372f0fc1ae7abfbd41c074e8bb5246f3e188>`_) - Update fixture size handling (#373) by `@adhtruong <https://github.com/adhtruong>`_ in `#373 <https://github.com/litestar-org/polyfactory/pull/373>`_ * (`87a6749 <https://github.com/litestar-org/polyfactory/commit/87a67493d839a5a61ea2df2b31eb909a60426a58>`_) - Dataclass field type not used correctly (#371) by `@anthonyjgraff <https://github.com/anthonyjgraff>`_ in `#371 <https://github.com/litestar-org/polyfactory/pull/371>`_ Documentation ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`6f4b712 <https://github.com/litestar-org/polyfactory/commit/6f4b7127091967bbcbcd561611309d926eb1dcbe>`_) - Add adhtruong as a contributor for doc, test, and code (#375) by `@allcontributors[bot] <https://github.com/allcontributors[bot]>`_ in `#375 <https://github.com/litestar-org/polyfactory/pull/375>`_ * (`64c4e6c <https://github.com/litestar-org/polyfactory/commit/64c4e6cfadd8bdbd6b2fa6af812448c3ba537fb6>`_) - Add anthonyjgraff as a contributor for code (#374) by `@allcontributors[bot] <https://github.com/allcontributors[bot]>`_ in `#374 <https://github.com/litestar-org/polyfactory/pull/374>`_ * (`f2c6fe1 <https://github.com/litestar-org/polyfactory/commit/f2c6fe19eb632b04b0efa20b909df96e6d9c6c68>`_) - Add guacs as a contributor for infra, code, and 2 more (#380) by `@allcontributors[bot] <https://github.com/allcontributors[bot]>`_ in `#380 <https://github.com/litestar-org/polyfactory/pull/380>`_ Features ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`c76ffc9 <https://github.com/litestar-org/polyfactory/commit/c76ffc9e181128d26b448622792f9876bd6f3bac>`_) - Implement SQLA factory (#369) by `@adhtruong <https://github.com/adhtruong>`_ in `#369 <https://github.com/litestar-org/polyfactory/pull/369>`_ Miscellaneous Tasks ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`fc0bf61 <https://github.com/litestar-org/polyfactory/commit/fc0bf6131af6d4480da6e9b0102f1df67180d92a>`_) - Update maintainers by `@provinzkraut <https://github.com/provinzkraut>`_ * (`f67f36e <https://github.com/litestar-org/polyfactory/commit/f67f36e45f67a80bfe63e7df88310f97196e6830>`_) - Ignore .all-contributorsrc for in .pre-commit (#377) by `@adhtruong <https://github.com/adhtruong>`_ in `#377 <https://github.com/litestar-org/polyfactory/pull/377>`_ * (`66e9db1 <https://github.com/litestar-org/polyfactory/commit/66e9db170958d89648df64593e02d43196493f42>`_) - Fix all-contributors config by `@JacobCoffee <https://github.com/JacobCoffee>`_ Testing ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`ec177ec <https://github.com/litestar-org/polyfactory/commit/ec177ec2d0e12bddb37af285982b0b453e2cbd06>`_) - Make ``pytest`` configuration stricter (#363) by `@sobolevn <https://github.com/sobolevn>`_ in `#363 <https://github.com/litestar-org/polyfactory/pull/363>`_ * (`95d24cb <https://github.com/litestar-org/polyfactory/commit/95d24cb193e2e6fbfa87c642266f0ae907e3ccdd>`_) - Skip variable length dict test for odmantic (#372) by `@guacs <https://github.com/guacs>`_ in `#372 <https://github.com/litestar-org/polyfactory/pull/372>`_ Infra ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`adccaf0 <https://github.com/litestar-org/polyfactory/commit/adccaf0a5d6261e088b1bd58f54efdd2c1b54147>`_) - Enable publishing with PyPI trusted publishers (#368) by `@provinzkraut <https://github.com/provinzkraut>`_ in `#368 <https://github.com/litestar-org/polyfactory/pull/368>`_ `Release [v2.8.2] - 2023-09-15 <https://github.com/litestar-org/polyfactory/releases/tag/v2.8.2>`_ ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * `See All commits in v2.8.2 <https://github.com/litestar-org/polyfactory/commits/v2.8.2>`_ `7af5469 <https://github.com/litestar-org/polyfactory/commit/7af5469440fb2450fdfb68403985f1b67d6e4a92>`_ ... `ebf30ff <https://github.com/litestar-org/polyfactory/commit/ebf30ff6e05807ee6073f1fb04667f17498424d5>`_ | `See diff for 2.8.2 <https://github.com/litestar-org/polyfactory/compare/7af5469440fb2450fdfb68403985f1b67d6e4a92...ebf30ff6e05807ee6073f1fb04667f17498424d5>`_ Bug Fixes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`f639c26 <https://github.com/litestar-org/polyfactory/commit/f639c26b630788c3dbcb9c7186d22f20eb59796b>`_) - Properly set annotation in union with nested Annotated (#355) by `@guacs <https://github.com/guacs>`_ in `#355 <https://github.com/litestar-org/polyfactory/pull/355>`_ * (`ebf30ff <https://github.com/litestar-org/polyfactory/commit/ebf30ff6e05807ee6073f1fb04667f17498424d5>`_) - Add minimum version constraint to attrs (#359) by `@guacs <https://github.com/guacs>`_ in `#359 <https://github.com/litestar-org/polyfactory/pull/359>`_ Documentation ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`091ee36 <https://github.com/litestar-org/polyfactory/commit/091ee36f6ee7e51f73fe6bebabb1bda442faed35>`_) - Change the comment length in "Handling custom types" docs (#361) by `@sobolevn <https://github.com/sobolevn>`_ in `#361 <https://github.com/litestar-org/polyfactory/pull/361>`_ `Release [v2.8.1] - 2023-09-10 <https://github.com/litestar-org/polyfactory/releases/tag/v2.8.1>`_ ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * `See All commits in v2.8.1 <https://github.com/litestar-org/polyfactory/commits/v2.8.1>`_ `7b46b57 <https://github.com/litestar-org/polyfactory/commit/7b46b572a71b347ac650658fe066641e631cedd6>`_ ... `7af5469 <https://github.com/litestar-org/polyfactory/commit/7af5469440fb2450fdfb68403985f1b67d6e4a92>`_ | `See diff for 2.8.1 <https://github.com/litestar-org/polyfactory/compare/7b46b572a71b347ac650658fe066641e631cedd6...7af5469440fb2450fdfb68403985f1b67d6e4a92>`_ Bug Fixes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`3dba4be <https://github.com/litestar-org/polyfactory/commit/3dba4be756d1d4e2b132f1650949bc9e0cdaa3ec>`_) - Use full Python version for venv cache (#352) by `@guacs <https://github.com/guacs>`_ in `#352 <https://github.com/litestar-org/polyfactory/pull/352>`_ * (`257852a <https://github.com/litestar-org/polyfactory/commit/257852af883c7a34e7a8be4494139f36825be08b>`_) - Add missing factories to builtin registration (#351) by `@guacs <https://github.com/guacs>`_ in `#351 <https://github.com/litestar-org/polyfactory/pull/351>`_ Documentation ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`e4daf5f <https://github.com/litestar-org/polyfactory/commit/e4daf5f6e4f7e17cad6bb75d8ff81fbb3145958a>`_) - Add adhtruong as a contributor for code (#346) by `@allcontributors[bot] <https://github.com/allcontributors[bot]>`_ in `#346 <https://github.com/litestar-org/polyfactory/pull/346>`_ * (`9ffe596 <https://github.com/litestar-org/polyfactory/commit/9ffe596836271a86ae2a8d0fdb06b2b94d287f54>`_) - Expose all options (#350) by `@adhtruong <https://github.com/adhtruong>`_ in `#350 <https://github.com/litestar-org/polyfactory/pull/350>`_ * (`7a5a1c9 <https://github.com/litestar-org/polyfactory/commit/7a5a1c9a228feaf29ce8211a130daf354725a5ee>`_) - Add adhtruong as a contributor for doc (#353) by `@allcontributors[bot] <https://github.com/allcontributors[bot]>`_ in `#353 <https://github.com/litestar-org/polyfactory/pull/353>`_ Miscellaneous Tasks ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`4f2e5d8 <https://github.com/litestar-org/polyfactory/commit/4f2e5d84d7b2c837a21295f886c9bc04f4ed3534>`_) - Updated dependencies by `@Goldziher <https://github.com/Goldziher>`_ * (`161c0f6 <https://github.com/litestar-org/polyfactory/commit/161c0f69344105a827ee4701e91da159b70b1c08>`_) - Bump actions/checkout from 3 to 4 (#349) by `@dependabot[bot] <https://github.com/dependabot[bot]>`_ in `#349 <https://github.com/litestar-org/polyfactory/pull/349>`_ * (`7af5469 <https://github.com/litestar-org/polyfactory/commit/7af5469440fb2450fdfb68403985f1b67d6e4a92>`_) - Prepare v2.8.1 (#354) by `@guacs <https://github.com/guacs>`_ in `#354 <https://github.com/litestar-org/polyfactory/pull/354>`_ `Release [v2.8.0] - 2023-08-26 <https://github.com/litestar-org/polyfactory/releases/tag/v2.8.0>`_ ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * `See All commits in v2.8.0 <https://github.com/litestar-org/polyfactory/commits/v2.8.0>`_ `710d3ce <https://github.com/litestar-org/polyfactory/commit/710d3ce48e72e36b7e4fabc3a739dd0afc34d317>`_ ... `7b46b57 <https://github.com/litestar-org/polyfactory/commit/7b46b572a71b347ac650658fe066641e631cedd6>`_ | `See diff for 2.8.0 <https://github.com/litestar-org/polyfactory/compare/710d3ce48e72e36b7e4fabc3a739dd0afc34d317...7b46b572a71b347ac650658fe066641e631cedd6>`_ Bug Fixes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`3ec7de8 <https://github.com/litestar-org/polyfactory/commit/3ec7de8693efa8a0d16abda0d7a17d4cf5d840ee>`_) - Ensure no override of Faker instance (#331) by `@guacs <https://github.com/guacs>`_ in `#331 <https://github.com/litestar-org/polyfactory/pull/331>`_ Documentation ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`ea41bbe <https://github.com/litestar-org/polyfactory/commit/ea41bbe6097813de9354e75fff33c785f5c54de2>`_) - Add 185504a9 as a contributor for code (#339) by `@allcontributors[bot] <https://github.com/allcontributors[bot]>`_ in `#339 <https://github.com/litestar-org/polyfactory/pull/339>`_ Features ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`510fabd <https://github.com/litestar-org/polyfactory/commit/510fabdffec6b3f0147a136b8cdd50c0337d09a9>`_) - Support constraints for mapping types (#337) by `@guacs <https://github.com/guacs>`_ in `#337 <https://github.com/litestar-org/polyfactory/pull/337>`_ * (`0228d3d <https://github.com/litestar-org/polyfactory/commit/0228d3dd81015bb3dfc1add6f3f4b7d1b5f2b6a1>`_) - Add pydantic's AwareDatetime to the mock map (#333) by `@185504a9 <https://github.com/185504a9>`_ in `#333 <https://github.com/litestar-org/polyfactory/pull/333>`_ Miscellaneous Tasks ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`bf04fa6 <https://github.com/litestar-org/polyfactory/commit/bf04fa625e3457d81059d754d10e36642a160e8a>`_) - Updated dependencies (#338) by `@Goldziher <https://github.com/Goldziher>`_ in `#338 <https://github.com/litestar-org/polyfactory/pull/338>`_ `Release [v2.7.2] - 2023-08-09 <https://github.com/litestar-org/polyfactory/releases/tag/v2.7.2>`_ ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * `See All commits in v2.7.2 <https://github.com/litestar-org/polyfactory/commits/v2.7.2>`_ `04a504b <https://github.com/litestar-org/polyfactory/commit/04a504b7db5713d5e6027c230313ff383bcba252>`_ ... `710d3ce <https://github.com/litestar-org/polyfactory/commit/710d3ce48e72e36b7e4fabc3a739dd0afc34d317>`_ | `See diff for 2.7.2 <https://github.com/litestar-org/polyfactory/compare/04a504b7db5713d5e6027c230313ff383bcba252...710d3ce48e72e36b7e4fabc3a739dd0afc34d317>`_ Bug Fixes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`725835e <https://github.com/litestar-org/polyfactory/commit/725835edf8f3c4a4e6e6741ba4f4deeb24192a11>`_) - Fix pydantic core import (#329) by `@guacs <https://github.com/guacs>`_ in `#329 <https://github.com/litestar-org/polyfactory/pull/329>`_ `Release [v2.7.1] - 2023-08-08 <https://github.com/litestar-org/polyfactory/releases/tag/v2.7.1>`_ ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * `See All commits in v2.7.1 <https://github.com/litestar-org/polyfactory/commits/v2.7.1>`_ `3e45f8f <https://github.com/litestar-org/polyfactory/commit/3e45f8f331d12ae395779567f5127b1bc18af23e>`_ ... `04a504b <https://github.com/litestar-org/polyfactory/commit/04a504b7db5713d5e6027c230313ff383bcba252>`_ | `See diff for 2.7.1 <https://github.com/litestar-org/polyfactory/compare/3e45f8f331d12ae395779567f5127b1bc18af23e...04a504b7db5713d5e6027c230313ff383bcba252>`_ Bug Fixes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`2733497 <https://github.com/litestar-org/polyfactory/commit/2733497369a065cf7c50006921967b93a02e0434>`_) - Add support for Json type in Pydantic factory (#315) by `@guacs <https://github.com/guacs>`_ in `#315 <https://github.com/litestar-org/polyfactory/pull/315>`_ * (`3aeaa0c <https://github.com/litestar-org/polyfactory/commit/3aeaa0cb290225e912ddda3d242b280839e04582>`_) - Constrained strings not deterministic with seed because urandom not seedable (#319) by `@klimantje <https://github.com/klimantje>`_ in `#319 <https://github.com/litestar-org/polyfactory/pull/319>`_ * (`61f1e2e <https://github.com/litestar-org/polyfactory/commit/61f1e2e0d857ffd111ab8c8d7cfbab6f67230ae1>`_) - Random seed configuration (#321) by `@guacs <https://github.com/guacs>`_ in `#321 <https://github.com/litestar-org/polyfactory/pull/321>`_ * (`2400fbe <https://github.com/litestar-org/polyfactory/commit/2400fbeb756deb5cdc32c666f2e27df31dff9387>`_) - Include pydantic Field constraints when using Optional type (#323) by `@tcrasset <https://github.com/tcrasset>`_ in `#323 <https://github.com/litestar-org/polyfactory/pull/323>`_ Documentation ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`8ff7e0f <https://github.com/litestar-org/polyfactory/commit/8ff7e0fbc3552869b7fcbcb1c8b71cfdf6c46dda>`_) - Add klimantje as a contributor for code (#320) by `@allcontributors[bot] <https://github.com/allcontributors[bot]>`_ in `#320 <https://github.com/litestar-org/polyfactory/pull/320>`_ * (`9def5b1 <https://github.com/litestar-org/polyfactory/commit/9def5b1f2a95470659db0bd2b80d742b6195c2da>`_) - Add tcrasset as a contributor for code (#324) by `@allcontributors[bot] <https://github.com/allcontributors[bot]>`_ in `#324 <https://github.com/litestar-org/polyfactory/pull/324>`_ Infra ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`5543e66 <https://github.com/litestar-org/polyfactory/commit/5543e66b1296cf3db8b1f66f0722fa05114ba266>`_) - Fix health files (#322) by `@JacobCoffee <https://github.com/JacobCoffee>`_ in `#322 <https://github.com/litestar-org/polyfactory/pull/322>`_ Meta ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`5abe4b3 <https://github.com/litestar-org/polyfactory/commit/5abe4b3df7dd9d3623d33332e8b6143b3806ccde>`_) - Update issue template config by `@JacobCoffee <https://github.com/JacobCoffee>`_ `Release [v2.7.0] - 2023-07-28 <https://github.com/litestar-org/polyfactory/releases/tag/v2.7.0>`_ ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * `See All commits in v2.7.0 <https://github.com/litestar-org/polyfactory/commits/v2.7.0>`_ `e703593 <https://github.com/litestar-org/polyfactory/commit/e703593658e94b6aed938fbff161936f916d0e02>`_ ... `3e45f8f <https://github.com/litestar-org/polyfactory/commit/3e45f8f331d12ae395779567f5127b1bc18af23e>`_ | `See diff for 2.7.0 <https://github.com/litestar-org/polyfactory/compare/e703593658e94b6aed938fbff161936f916d0e02...3e45f8f331d12ae395779567f5127b1bc18af23e>`_ Documentation ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`0bfa3b4 <https://github.com/litestar-org/polyfactory/commit/0bfa3b497ecfe45c21e1d700e1c2aa8ec41db391>`_) - Add litestar rename news link by `@JacobCoffee <https://github.com/JacobCoffee>`_ Features ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`96c61ae <https://github.com/litestar-org/polyfactory/commit/96c61aeabe02cb135bfa5225c0dbe6459df41a8c>`_) - Implementation of Attrs Factory (#313) by `@guacs <https://github.com/guacs>`_ in `#313 <https://github.com/litestar-org/polyfactory/pull/313>`_ Infra ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`d385561 <https://github.com/litestar-org/polyfactory/commit/d38556127f40f009a8baf22e1ea5cb5f12603dd0>`_) - Update codeowners (#311) by `@JacobCoffee <https://github.com/JacobCoffee>`_ in `#311 <https://github.com/litestar-org/polyfactory/pull/311>`_ `Release [v2.6.3] - 2023-07-21 <https://github.com/litestar-org/polyfactory/releases/tag/v2.6.3>`_ ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * `See All commits in v2.6.3 <https://github.com/litestar-org/polyfactory/commits/v2.6.3>`_ `86585d0 <https://github.com/litestar-org/polyfactory/commit/86585d064393017c448918d88e00853d370274e1>`_ ... `e703593 <https://github.com/litestar-org/polyfactory/commit/e703593658e94b6aed938fbff161936f916d0e02>`_ | `See diff for 2.6.3 <https://github.com/litestar-org/polyfactory/compare/86585d064393017c448918d88e00853d370274e1...e703593658e94b6aed938fbff161936f916d0e02>`_ Bug Fixes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`7405901 <https://github.com/litestar-org/polyfactory/commit/7405901e0e861abcb3256d0f09f22180880ed4e0>`_) - Remove stray badge (#306) by `@JacobCoffee <https://github.com/JacobCoffee>`_ in `#306 <https://github.com/litestar-org/polyfactory/pull/306>`_ * (`b1f8f6e <https://github.com/litestar-org/polyfactory/commit/b1f8f6e7e05f8741a79d166fbeac862a002236d5>`_) - Remove stray character from README by `@JacobCoffee <https://github.com/JacobCoffee>`_ Miscellaneous Tasks ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`c936389 <https://github.com/litestar-org/polyfactory/commit/c9363893b50f1763ee08ccb421856c470f2d9fff>`_) - Update poetry dependencies (#308) by `@Goldziher <https://github.com/Goldziher>`_ in `#308 <https://github.com/litestar-org/polyfactory/pull/308>`_ * (`09f896c <https://github.com/litestar-org/polyfactory/commit/09f896c4d47e9232fe1870fd40f1eef73ddc4f5e>`_) - Fix CONTRIBUTING.rst (#310) by `@provinzkraut <https://github.com/provinzkraut>`_ in `#310 <https://github.com/litestar-org/polyfactory/pull/310>`_ * (`3fadfb7 <https://github.com/litestar-org/polyfactory/commit/3fadfb712b5f967ecb27719ba7f92b20788b108b>`_) - Fix annotated field resolution (#309) by `@Goldziher <https://github.com/Goldziher>`_ in `#309 <https://github.com/litestar-org/polyfactory/pull/309>`_ `Release [v2.6.2] - 2023-07-14 <https://github.com/litestar-org/polyfactory/releases/tag/v2.6.2>`_ ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * `See All commits in v2.6.2 <https://github.com/litestar-org/polyfactory/commits/v2.6.2>`_ `d331ae0 <https://github.com/litestar-org/polyfactory/commit/d331ae03a9e11733d5b2b14b4ad190f7281d663a>`_ ... `86585d0 <https://github.com/litestar-org/polyfactory/commit/86585d064393017c448918d88e00853d370274e1>`_ | `See diff for 2.6.2 <https://github.com/litestar-org/polyfactory/compare/d331ae03a9e11733d5b2b14b4ad190f7281d663a...86585d064393017c448918d88e00853d370274e1>`_ Features ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`a2be35a <https://github.com/litestar-org/polyfactory/commit/a2be35a535babbb5b6ed407e8f108f7aa9371067>`_) - Switch to using faker.seed_instance (#305) by `@Goldziher <https://github.com/Goldziher>`_ in `#305 <https://github.com/litestar-org/polyfactory/pull/305>`_ * (`86585d0 <https://github.com/litestar-org/polyfactory/commit/86585d064393017c448918d88e00853d370274e1>`_) - 2.6.2 by `@Goldziher <https://github.com/Goldziher>`_ Miscellaneous Tasks ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`f54f9f3 <https://github.com/litestar-org/polyfactory/commit/f54f9f3c0b849a2d06bf4a5332da80ccdc31d1a9>`_) - Add passing test for issue 300 (#301) by `@Goldziher <https://github.com/Goldziher>`_ in `#301 <https://github.com/litestar-org/polyfactory/pull/301>`_ `Release [v2.6.1] - 2023-07-10 <https://github.com/litestar-org/polyfactory/releases/tag/v2.6.1>`_ ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * `See All commits in v2.6.1 <https://github.com/litestar-org/polyfactory/commits/v2.6.1>`_ `79e8145 <https://github.com/litestar-org/polyfactory/commit/79e81458edd3faeacac5b5e4f1b1cece196f326f>`_ ... `d331ae0 <https://github.com/litestar-org/polyfactory/commit/d331ae03a9e11733d5b2b14b4ad190f7281d663a>`_ | `See diff for 2.6.1 <https://github.com/litestar-org/polyfactory/compare/79e81458edd3faeacac5b5e4f1b1cece196f326f...d331ae03a9e11733d5b2b14b4ad190f7281d663a>`_ Documentation ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`7761834 <https://github.com/litestar-org/polyfactory/commit/776183494c4a0480b2ea5f168378eeffc30906b5>`_) - Add abdulhaq-e as a contributor for code (#297) by `@allcontributors[bot] <https://github.com/allcontributors[bot]>`_ in `#297 <https://github.com/litestar-org/polyfactory/pull/297>`_ `Release [v2.6.0] - 2023-07-09 <https://github.com/litestar-org/polyfactory/releases/tag/v2.6.0>`_ ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * `See All commits in v2.6.0 <https://github.com/litestar-org/polyfactory/commits/v2.6.0>`_ `2b050bb <https://github.com/litestar-org/polyfactory/commit/2b050bb53552ec3dab944a8386b38e8fc104045d>`_ ... `79e8145 <https://github.com/litestar-org/polyfactory/commit/79e81458edd3faeacac5b5e4f1b1cece196f326f>`_ | `See diff for 2.6.0 <https://github.com/litestar-org/polyfactory/compare/2b050bb53552ec3dab944a8386b38e8fc104045d...79e81458edd3faeacac5b5e4f1b1cece196f326f>`_ Miscellaneous Tasks ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`16cbc99 <https://github.com/litestar-org/polyfactory/commit/16cbc9938f3c6e1ce84953e074689869a649270b>`_) - Fix pre-commit issues by `@Goldziher <https://github.com/Goldziher>`_ * (`956472c <https://github.com/litestar-org/polyfactory/commit/956472cd5bba38af012684ed75133bc63d28d562>`_) - Apply sourcery by `@Goldziher <https://github.com/Goldziher>`_ * (`5cdfed3 <https://github.com/litestar-org/polyfactory/commit/5cdfed316621d9f53d364966e150daf9dadacb8a>`_) - Updated dependencies by `@Goldziher <https://github.com/Goldziher>`_ `Release [v2.5.0] - 2023-06-30 <https://github.com/litestar-org/polyfactory/releases/tag/v2.5.0>`_ ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * `See All commits in v2.5.0 <https://github.com/litestar-org/polyfactory/commits/v2.5.0>`_ `79e50df <https://github.com/litestar-org/polyfactory/commit/79e50dfdbabca2c58eee54347edab3fc0e269bc3>`_ ... `2b050bb <https://github.com/litestar-org/polyfactory/commit/2b050bb53552ec3dab944a8386b38e8fc104045d>`_ | `See diff for 2.5.0 <https://github.com/litestar-org/polyfactory/compare/79e50dfdbabca2c58eee54347edab3fc0e269bc3...2b050bb53552ec3dab944a8386b38e8fc104045d>`_ Bug Fixes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`35e10da <https://github.com/litestar-org/polyfactory/commit/35e10daf2f2c00de3fcedf857b180741bef22302>`_) - All contributors (#263) by `@Goldziher <https://github.com/Goldziher>`_ in `#263 <https://github.com/litestar-org/polyfactory/pull/263>`_ * (`d592836 <https://github.com/litestar-org/polyfactory/commit/d592836295fd53f7d5604ffe671553a897613673>`_) - Support overriding base factories locally (v2) (#267) by `@gsakkis <https://github.com/gsakkis>`_ in `#267 <https://github.com/litestar-org/polyfactory/pull/267>`_ Documentation ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`2b8ae48 <https://github.com/litestar-org/polyfactory/commit/2b8ae487feef83143995a4765c70e53d90f270f3>`_) - Add peterschutt as a contributor for maintenance, doc, and test (#264) by `@allcontributors[bot] <https://github.com/allcontributors[bot]>`_ in `#264 <https://github.com/litestar-org/polyfactory/pull/264>`_ * (`a53c598 <https://github.com/litestar-org/polyfactory/commit/a53c598407aac551638a0f39d9a1173370e42ff6>`_) - Update pypi image, update readme (#266) by `@JacobCoffee <https://github.com/JacobCoffee>`_ in `#266 <https://github.com/litestar-org/polyfactory/pull/266>`_ * (`d0c8bfa <https://github.com/litestar-org/polyfactory/commit/d0c8bfab21f9ed0d918d51069b36359337294762>`_) - Add mdczaplicki as a contributor for test, and code (#274) by `@allcontributors[bot] <https://github.com/allcontributors[bot]>`_ in `#274 <https://github.com/litestar-org/polyfactory/pull/274>`_ Features ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`a7220f3 <https://github.com/litestar-org/polyfactory/commit/a7220f31428307b0a635216e3d9d1154b988eb91>`_) - Add ``sourcery-ai`` config (#271) by `@JacobCoffee <https://github.com/JacobCoffee>`_ in `#271 <https://github.com/litestar-org/polyfactory/pull/271>`_ Miscellaneous Tasks ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`946cf08 <https://github.com/litestar-org/polyfactory/commit/946cf08dd5401929a0d8aaeb6eee8a6607e4ac11>`_) - Updated deps by `@Goldziher <https://github.com/Goldziher>`_ * (`e932f89 <https://github.com/litestar-org/polyfactory/commit/e932f8920e786e372e185e5c068543587a4b6861>`_) - Applied sourcery (#281) by `@Goldziher <https://github.com/Goldziher>`_ in `#281 <https://github.com/litestar-org/polyfactory/pull/281>`_ * (`0c0ed22 <https://github.com/litestar-org/polyfactory/commit/0c0ed221c68b3e19951f6861cf65c4e2bd8f265e>`_) - Adjust to pydantic v2 (#284) by `@Goldziher <https://github.com/Goldziher>`_ in `#284 <https://github.com/litestar-org/polyfactory/pull/284>`_ Release ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`2b050bb <https://github.com/litestar-org/polyfactory/commit/2b050bb53552ec3dab944a8386b38e8fc104045d>`_) - Update README for v2.5.0 and pydantic v2 (#285) by `@JacobCoffee <https://github.com/JacobCoffee>`_ in `#285 <https://github.com/litestar-org/polyfactory/pull/285>`_ `Release [v2.4.0] - 2023-06-25 <https://github.com/litestar-org/polyfactory/releases/tag/v2.4.0>`_ ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * `See All commits in v2.4.0 <https://github.com/litestar-org/polyfactory/commits/v2.4.0>`_ `5013069 <https://github.com/litestar-org/polyfactory/commit/5013069b9a1d6adbdd5b1ee27bf5e4a73c00fac0>`_ ... `79e50df <https://github.com/litestar-org/polyfactory/commit/79e50dfdbabca2c58eee54347edab3fc0e269bc3>`_ | `See diff for 2.4.0 <https://github.com/litestar-org/polyfactory/compare/5013069b9a1d6adbdd5b1ee27bf5e4a73c00fac0...79e50dfdbabca2c58eee54347edab3fc0e269bc3>`_ Bug Fixes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`26073c4 <https://github.com/litestar-org/polyfactory/commit/26073c4db7b50a4dc90f60e3714b86c6db8a1def>`_) - Support overriding base factories locally (#238) by `@Goldziher <https://github.com/Goldziher>`_ in `#238 <https://github.com/litestar-org/polyfactory/pull/238>`_ Documentation ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`d625936 <https://github.com/litestar-org/polyfactory/commit/d62593698118fbfa9350b5ad0b7147ad257a0f2a>`_) - Add Simske as a contributor for code (#242) by `@allcontributors[bot] <https://github.com/allcontributors[bot]>`_ in `#242 <https://github.com/litestar-org/polyfactory/pull/242>`_ * (`2b93de6 <https://github.com/litestar-org/polyfactory/commit/2b93de6800a87b97c531162cafaec4b8dd3c2eea>`_) - Add danielkatzan as a contributor for doc (#261) by `@allcontributors[bot] <https://github.com/allcontributors[bot]>`_ in `#261 <https://github.com/litestar-org/polyfactory/pull/261>`_ * (`1511c9e <https://github.com/litestar-org/polyfactory/commit/1511c9eca5f6b97aea7a1eaadf4aac9166309069>`_) - Add gegnew as a contributor for code (#262) by `@allcontributors[bot] <https://github.com/allcontributors[bot]>`_ in `#262 <https://github.com/litestar-org/polyfactory/pull/262>`_ * (`d355511 <https://github.com/litestar-org/polyfactory/commit/d35551182759797996494ead26f054f56f77fc65>`_) - Add roeeyn as a contributor for doc (#260) by `@allcontributors[bot] <https://github.com/allcontributors[bot]>`_ in `#260 <https://github.com/litestar-org/polyfactory/pull/260>`_ * (`c686ddd <https://github.com/litestar-org/polyfactory/commit/c686ddd2a4e935b40c3f93a3c6b84ef69a04cbdf>`_) - Add gigelu as a contributor for doc (#259) by `@allcontributors[bot] <https://github.com/allcontributors[bot]>`_ in `#259 <https://github.com/litestar-org/polyfactory/pull/259>`_ * (`9101134 <https://github.com/litestar-org/polyfactory/commit/910113431cc96e01cab2a3707a05cf13b9e4579f>`_) - Add ReznikovRoman as a contributor for code (#258) by `@allcontributors[bot] <https://github.com/allcontributors[bot]>`_ in `#258 <https://github.com/litestar-org/polyfactory/pull/258>`_ * (`1e4df30 <https://github.com/litestar-org/polyfactory/commit/1e4df304212a6d3291a148aee70e3011771432f7>`_) - Add anthonyh209 as a contributor for code (#257) by `@allcontributors[bot] <https://github.com/allcontributors[bot]>`_ in `#257 <https://github.com/litestar-org/polyfactory/pull/257>`_ * (`c6657e7 <https://github.com/litestar-org/polyfactory/commit/c6657e7fdfcbcac78a9b9c032b8b5c49904cc82e>`_) - Add avihai-yosef as a contributor for code (#256) by `@allcontributors[bot] <https://github.com/allcontributors[bot]>`_ in `#256 <https://github.com/litestar-org/polyfactory/pull/256>`_ * (`97cdad2 <https://github.com/litestar-org/polyfactory/commit/97cdad2b88de1c0dc2ce9a8205e4dce4151a1d76>`_) - Add Iipin as a contributor for code (#254) by `@allcontributors[bot] <https://github.com/allcontributors[bot]>`_ in `#254 <https://github.com/litestar-org/polyfactory/pull/254>`_ * (`9156cca <https://github.com/litestar-org/polyfactory/commit/9156cca1399a27c0cd9e3d1fb9e449e6f0f9a35f>`_) - Add thorin-schiffer as a contributor for code (#253) by `@allcontributors[bot] <https://github.com/allcontributors[bot]>`_ in `#253 <https://github.com/litestar-org/polyfactory/pull/253>`_ * (`02c1daa <https://github.com/litestar-org/polyfactory/commit/02c1daa2a0bc7c90d522de62f37c15203dca7d45>`_) - Add lyz-code as a contributor for code (#252) by `@allcontributors[bot] <https://github.com/allcontributors[bot]>`_ in `#252 <https://github.com/litestar-org/polyfactory/pull/252>`_ * (`e883d58 <https://github.com/litestar-org/polyfactory/commit/e883d58cf0eaebe694b5a54e30dfce73759031fc>`_) - Add DaanRademaker as a contributor for code (#251) by `@allcontributors[bot] <https://github.com/allcontributors[bot]>`_ in `#251 <https://github.com/litestar-org/polyfactory/pull/251>`_ * (`cd2e558 <https://github.com/litestar-org/polyfactory/commit/cd2e5582ca01dc1375ae7bb4f3d9e057cff91d8a>`_) - Add nguyent as a contributor for code (#250) by `@allcontributors[bot] <https://github.com/allcontributors[bot]>`_ in `#250 <https://github.com/litestar-org/polyfactory/pull/250>`_ * (`af594e3 <https://github.com/litestar-org/polyfactory/commit/af594e319db5420e0a76e7919743309987bd9d46>`_) - Add EltonChou as a contributor for code (#249) by `@allcontributors[bot] <https://github.com/allcontributors[bot]>`_ in `#249 <https://github.com/litestar-org/polyfactory/pull/249>`_ * (`bac2622 <https://github.com/litestar-org/polyfactory/commit/bac262255b656f7ec8ad2f0202f83dd3a59910de>`_) - Add Butch78 as a contributor for code (#248) by `@allcontributors[bot] <https://github.com/allcontributors[bot]>`_ in `#248 <https://github.com/litestar-org/polyfactory/pull/248>`_ * (`13e80a7 <https://github.com/litestar-org/polyfactory/commit/13e80a7b4c8cea8395c09443d561e372105f1b80>`_) - Add lindycoder as a contributor for code (#247) by `@allcontributors[bot] <https://github.com/allcontributors[bot]>`_ in `#247 <https://github.com/litestar-org/polyfactory/pull/247>`_ * (`3940de4 <https://github.com/litestar-org/polyfactory/commit/3940de43ce54d86385cf412007a7c261a5bb0590>`_) - Add peterschutt as a contributor for code (#246) by `@allcontributors[bot] <https://github.com/allcontributors[bot]>`_ in `#246 <https://github.com/litestar-org/polyfactory/pull/246>`_ * (`e598c7d <https://github.com/litestar-org/polyfactory/commit/e598c7ddcdcdef07a1cca448f898c3f8bb176cd8>`_) - Add phbernardes as a contributor for code (#245) by `@allcontributors[bot] <https://github.com/allcontributors[bot]>`_ in `#245 <https://github.com/litestar-org/polyfactory/pull/245>`_ * (`24a7766 <https://github.com/litestar-org/polyfactory/commit/24a7766a0f6888dc6548366f7af7535cb7d36fab>`_) - Add mciszczon as a contributor for code (#244) by `@allcontributors[bot] <https://github.com/allcontributors[bot]>`_ in `#244 <https://github.com/litestar-org/polyfactory/pull/244>`_ * (`b8cfe1a <https://github.com/litestar-org/polyfactory/commit/b8cfe1a3f581bf07b32a8102b9c975e88594cd6b>`_) - Add sondrelg as a contributor for code (#243) by `@allcontributors[bot] <https://github.com/allcontributors[bot]>`_ in `#243 <https://github.com/litestar-org/polyfactory/pull/243>`_ Fix ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`773b364 <https://github.com/litestar-org/polyfactory/commit/773b36460720cebd8afb246b63c0d8f09ea3faf4>`_) - URL constraints and strict pydantic v2 values (#241) by `@Goldziher <https://github.com/Goldziher>`_ in `#241 <https://github.com/litestar-org/polyfactory/pull/241>`_ Miscellaneous Tasks ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`00dce8a <https://github.com/litestar-org/polyfactory/commit/00dce8a662eaf53aa38acf47ef8586855cc891fe>`_) - Reformat readme by `@Goldziher <https://github.com/Goldziher>`_ `Release [v2.3.3] - 2023-06-22 <https://github.com/litestar-org/polyfactory/releases/tag/v2.3.3>`_ ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * `See All commits in v2.3.3 <https://github.com/litestar-org/polyfactory/commits/v2.3.3>`_ `aef7acb <https://github.com/litestar-org/polyfactory/commit/aef7acbc3c1222d351fad8bcb0a9517e1508165b>`_ ... `5013069 <https://github.com/litestar-org/polyfactory/commit/5013069b9a1d6adbdd5b1ee27bf5e4a73c00fac0>`_ | `See diff for 2.3.3 <https://github.com/litestar-org/polyfactory/compare/aef7acbc3c1222d351fad8bcb0a9517e1508165b...5013069b9a1d6adbdd5b1ee27bf5e4a73c00fac0>`_ Documentation ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`b9ea84d <https://github.com/litestar-org/polyfactory/commit/b9ea84d924942ee39d00871d4f4369a8b7a7a813>`_) - Add VSHUMILIN97 as a contributor for code (#237) by `@allcontributors[bot] <https://github.com/allcontributors[bot]>`_ in `#237 <https://github.com/litestar-org/polyfactory/pull/237>`_ `Release [v2.3.2] - 2023-06-18 <https://github.com/litestar-org/polyfactory/releases/tag/v2.3.2>`_ ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * `See All commits in v2.3.2 <https://github.com/litestar-org/polyfactory/commits/v2.3.2>`_ `36c2f2f <https://github.com/litestar-org/polyfactory/commit/36c2f2f77a546b7992ab9f95a4904b1717d86e91>`_ ... `aef7acb <https://github.com/litestar-org/polyfactory/commit/aef7acbc3c1222d351fad8bcb0a9517e1508165b>`_ | `See diff for 2.3.2 <https://github.com/litestar-org/polyfactory/compare/36c2f2f77a546b7992ab9f95a4904b1717d86e91...aef7acbc3c1222d351fad8bcb0a9517e1508165b>`_ Miscellaneous Tasks ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`5bd544f <https://github.com/litestar-org/polyfactory/commit/5bd544f41ca07cac7d45c493d6a5262d648a79ab>`_) - Fix constant constraints (#233) by `@Goldziher <https://github.com/Goldziher>`_ in `#233 <https://github.com/litestar-org/polyfactory/pull/233>`_ `Release [v2.1.2] - 2023-05-28 <https://github.com/litestar-org/polyfactory/releases/tag/v2.1.2>`_ ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * `See All commits in v2.1.2 <https://github.com/litestar-org/polyfactory/commits/v2.1.2>`_ `f2ba049 <https://github.com/litestar-org/polyfactory/commit/f2ba049b06a0bb74a14c36cc5ef885c0fc8452ab>`_ ... `2e2f11a <https://github.com/litestar-org/polyfactory/commit/2e2f11a8489c09b113a67462221adc3c1450b97b>`_ | `See diff for 2.1.2 <https://github.com/litestar-org/polyfactory/compare/f2ba049b06a0bb74a14c36cc5ef885c0fc8452ab...2e2f11a8489c09b113a67462221adc3c1450b97b>`_ Bug Fixes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`9670d27 <https://github.com/litestar-org/polyfactory/commit/9670d27391f75f9f562f0663c2a0b2497d44e990>`_) - Return the correct types in the provider map (#224) by `@guacs <https://github.com/guacs>`_ in `#224 <https://github.com/litestar-org/polyfactory/pull/224>`_ Documentation ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`02a4c97 <https://github.com/litestar-org/polyfactory/commit/02a4c971ae56758bd625ff54a151a9b4e421a9fa>`_) - Add guacs as a contributor for code (#221) by `@allcontributors[bot] <https://github.com/allcontributors[bot]>`_ in `#221 <https://github.com/litestar-org/polyfactory/pull/221>`_ Miscellaneous Tasks ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`d753504 <https://github.com/litestar-org/polyfactory/commit/d753504ada2efc91b7f7ea94ad5cc10b5ae3322e>`_) - Remove typeddict imports from typing extensions by `@Goldziher <https://github.com/Goldziher>`_ * (`2e2f11a <https://github.com/litestar-org/polyfactory/commit/2e2f11a8489c09b113a67462221adc3c1450b97b>`_) - Resolve pydantic test issues by `@Goldziher <https://github.com/Goldziher>`_ `Release [v2.1.0] - 2023-05-06 <https://github.com/litestar-org/polyfactory/releases/tag/v2.1.0>`_ ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * `See All commits in v2.1.0 <https://github.com/litestar-org/polyfactory/commits/v2.1.0>`_ `d671ac2 <https://github.com/litestar-org/polyfactory/commit/d671ac2470b03411345bf4e57f0531cfa3c4c6f6>`_ ... `47d234b <https://github.com/litestar-org/polyfactory/commit/47d234bc2f36519fc5f5527766272d1e526734f4>`_ | `See diff for 2.1.0 <https://github.com/litestar-org/polyfactory/compare/d671ac2470b03411345bf4e57f0531cfa3c4c6f6...47d234bc2f36519fc5f5527766272d1e526734f4>`_ Bug Fixes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`1d5c645 <https://github.com/litestar-org/polyfactory/commit/1d5c645291d6134d0f7f3f8b90a4db206a429a39>`_) - Fix README.md formatting (#197) by `@JacobCoffee <https://github.com/JacobCoffee>`_ in `#197 <https://github.com/litestar-org/polyfactory/pull/197>`_ Documentation ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`f767011 <https://github.com/litestar-org/polyfactory/commit/f767011835432c55c93429c298262e736d7182ac>`_) - Add sygutss as a contributor for bug (#201) by `@allcontributors[bot] <https://github.com/allcontributors[bot]>`_ in `#201 <https://github.com/litestar-org/polyfactory/pull/201>`_ * (`36ff02e <https://github.com/litestar-org/polyfactory/commit/36ff02e23a22868a0276a0614ce96015ca89b9af>`_) - Add chrisbeardy as a contributor for doc (#207) by `@allcontributors[bot] <https://github.com/allcontributors[bot]>`_ in `#207 <https://github.com/litestar-org/polyfactory/pull/207>`_ Enhancement ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`a62c976 <https://github.com/litestar-org/polyfactory/commit/a62c97672ddfcfc6c7616e6cb6e6bab7efe25b87>`_) - PostGenerated classmethods (#204) by `@gsakkis <https://github.com/gsakkis>`_ in `#204 <https://github.com/litestar-org/polyfactory/pull/204>`_ Fix ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`af36991 <https://github.com/litestar-org/polyfactory/commit/af369911b8523d796fe6be5822aeea77e2b95eeb>`_) - Random union types for dict (#200) by `@sygutss <https://github.com/sygutss>`_ in `#200 <https://github.com/litestar-org/polyfactory/pull/200>`_ `Release [v2.0.1] - 2023-04-28 <https://github.com/litestar-org/polyfactory/releases/tag/v2.0.1>`_ ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * `See All commits in v2.0.1 <https://github.com/litestar-org/polyfactory/commits/v2.0.1>`_ `1f8d94c <https://github.com/litestar-org/polyfactory/commit/1f8d94c522556d39b35b1ea0e79155b8e50ac152>`_ ... `d671ac2 <https://github.com/litestar-org/polyfactory/commit/d671ac2470b03411345bf4e57f0531cfa3c4c6f6>`_ | `See diff for 2.0.1 <https://github.com/litestar-org/polyfactory/compare/1f8d94c522556d39b35b1ea0e79155b8e50ac152...d671ac2470b03411345bf4e57f0531cfa3c4c6f6>`_ Documentation ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`60cdb30 <https://github.com/litestar-org/polyfactory/commit/60cdb30832068ad1643d71632c10490eb7b161e9>`_) - Add mdczaplicki as a contributor for code (#185) by `@allcontributors[bot] <https://github.com/allcontributors[bot]>`_ in `#185 <https://github.com/litestar-org/polyfactory/pull/185>`_ * (`8b5d903 <https://github.com/litestar-org/polyfactory/commit/8b5d90370a53743b63222cec8d210018568f2ffe>`_) - Add przybylop as a contributor for code (#187) by `@allcontributors[bot] <https://github.com/allcontributors[bot]>`_ in `#187 <https://github.com/litestar-org/polyfactory/pull/187>`_ Miscellaneous Tasks ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`16f562f <https://github.com/litestar-org/polyfactory/commit/16f562f0bdf92d991deba79ce3e75d16df776896>`_) - Update maintainers (#194) by `@JacobCoffee <https://github.com/JacobCoffee>`_ in `#194 <https://github.com/litestar-org/polyfactory/pull/194>`_ * (`d671ac2 <https://github.com/litestar-org/polyfactory/commit/d671ac2470b03411345bf4e57f0531cfa3c4c6f6>`_) - Bump release version by `@JacobCoffee <https://github.com/JacobCoffee>`_ `Release [v2.0.0] - 2023-04-16 <https://github.com/litestar-org/polyfactory/releases/tag/v2.0.0>`_ ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * `See All commits in v2.0.0 <https://github.com/litestar-org/polyfactory/commits/v2.0.0>`_ `cb71cd0 <https://github.com/litestar-org/polyfactory/commit/cb71cd0d7391cbedeaf5bd3275473fec7ef9347e>`_ ... `1f8d94c <https://github.com/litestar-org/polyfactory/commit/1f8d94c522556d39b35b1ea0e79155b8e50ac152>`_ | `See diff for 2.0.0 <https://github.com/litestar-org/polyfactory/compare/cb71cd0d7391cbedeaf5bd3275473fec7ef9347e...1f8d94c522556d39b35b1ea0e79155b8e50ac152>`_ Bug Fixes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`8097da7 <https://github.com/litestar-org/polyfactory/commit/8097da790a1d4b8c108f268b197ae0ad0c718723>`_) - Update all-contrib placement by `@JacobCoffee <https://github.com/JacobCoffee>`_ Documentation ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`0814bb8 <https://github.com/litestar-org/polyfactory/commit/0814bb8c10607aa4ade7fb9575ab65d8f04bc3d5>`_) - Add JacobCoffee as a contributor for doc (#170)Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> by `@allcontributors[bot] <https://github.com/allcontributors[bot]>`_ in `#170 <https://github.com/litestar-org/polyfactory/pull/170>`_ * (`60511c9 <https://github.com/litestar-org/polyfactory/commit/60511c970f1d548b0a498f2d20b358c6798d046c>`_) - Add Goldziher as a contributor for infra, test, and code (#171)Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> by `@allcontributors[bot] <https://github.com/allcontributors[bot]>`_ in `#171 <https://github.com/litestar-org/polyfactory/pull/171>`_ * (`3853048 <https://github.com/litestar-org/polyfactory/commit/385304873a79f394a74c4dca4048212b224d1adf>`_) - Add provinzkraut as a contributor for code, test, and 6 more (#173) by `@allcontributors[bot] <https://github.com/allcontributors[bot]>`_ in `#173 <https://github.com/litestar-org/polyfactory/pull/173>`_ `Release [v2.0.0alpha1] - 2023-04-11 <https://github.com/litestar-org/polyfactory/releases/tag/v2.0.0alpha1>`_ ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * `See All commits in v2.0.0alpha1 <https://github.com/litestar-org/polyfactory/commits/v2.0.0alpha1>`_ Docs ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`5f111e4 <https://github.com/litestar-org/polyfactory/commit/5f111e45295f63265a1f293aa3b2ab9989bcac7e>`_) - Added Create Factory Method by `@Butch78 <https://github.com/Butch78>`_ * (`b1f83b3 <https://github.com/litestar-org/polyfactory/commit/b1f83b3fdd785ab4df2e7e03e353b9e04acdac30>`_) - Improved Inheritance by `@Butch78 <https://github.com/Butch78>`_ * (`5293860 <https://github.com/litestar-org/polyfactory/commit/52938600016fe16efef8daac23841fb106d8d472>`_) - Improved notes by `@Butch78 <https://github.com/Butch78>`_ Documentation ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`7ae2678 <https://github.com/litestar-org/polyfactory/commit/7ae26782508642faab7a100dff3160fd02bacaed>`_) - Explain how to subclass ModelFactory to create your custom extensions by `@lyz-code <https://github.com/lyz-code>`_ * (`218522f <https://github.com/litestar-org/polyfactory/commit/218522f689b5b208f9f7cd6d3763d6a82cc6c442>`_) - Reorder changes in CHANGELOG (#91) by `@ReznikovRoman <https://github.com/ReznikovRoman>`_ in `#91 <https://github.com/litestar-org/polyfactory/pull/91>`_ Features ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`4c2b931 <https://github.com/litestar-org/polyfactory/commit/4c2b93166ced4b7507290dd71a77c1f83631db69>`_) - 2023 Branding by `@JacobCoffee <https://github.com/JacobCoffee>`_ Miscellaneous Tasks ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * (`25570f5 <https://github.com/litestar-org/polyfactory/commit/25570f5929dd644173a90148216c6669cfd0b79f>`_) - Update polyfactory banner logo by `@JacobCoffee <https://github.com/JacobCoffee>`_ Polyfactory Changelog ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/conf.py��������������������������������������������������������������0000664�0000000�0000000�00000017070�14721310225�0017726�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from __future__ import annotations import sys from datetime import datetime from functools import partial from typing import TYPE_CHECKING, Any from unittest import mock from polyfactory.__metadata__ import __project__, __version__ if TYPE_CHECKING: from sphinx.addnodes import document from sphinx.application import Sphinx for mod_name in ("beanie", "odmantic"): sys.modules[mod_name] = mock.Mock() PY_CLASS = "py:class" PY_RE = r"py:.*" # -- Environmental Data ------------------------------------------------------ # -- Project information ----------------------------------------------------- current_year = datetime.now().year project = __project__ copyright = f"{current_year}, Litestar Organization" release = __version__ extensions = [ "sphinx.ext.intersphinx", "sphinx.ext.autosectionlabel", "sphinx.ext.autodoc", "sphinx.ext.napoleon", "sphinx_design", "auto_pytabs.sphinx_ext", "sphinx_copybutton", "sphinx.ext.viewcode", "sphinx.ext.todo", "sphinx.ext.viewcode", "sphinx_toolbox.collapse", "sphinx_togglebutton", "sphinx_paramlinks", ] intersphinx_mapping = { "python": ("https://docs.python.org/3", None), "faker": ("https://faker.readthedocs.io/en/master/", None), "pytest": ("https://docs.pytest.org/en/latest/", None), "msgspec": ("https://jcristharif.com/msgspec/", None), } nitpicky = True nitpick_ignore = [ (PY_CLASS, "BaseModel"), (PY_CLASS, "Decimal"), (PY_CLASS, "Faker"), (PY_CLASS, "FieldInfo"), (PY_CLASS, "Random"), (PY_CLASS, "Scope"), (PY_CLASS, "T"), (PY_CLASS, "F"), (PY_CLASS, "P"), (PY_CLASS, "P.args"), (PY_CLASS, "P.kwargs"), (PY_CLASS, "Self"), (PY_CLASS, "TypeGuard"), (PY_CLASS, "date"), (PY_CLASS, "tzinfo"), (PY_CLASS, "BeanieDocumentFactory"), (PY_CLASS, "OdmanticModelFactory"), (PY_CLASS, "ModelField"), (PY_CLASS, "Session"), (PY_CLASS, "AsyncSession"), ] nitpick_ignore_regex = [ (PY_RE, r"typing_extensions.*"), (PY_RE, r"polyfactory.*\.T"), (PY_RE, r"polyfactory.*\.P"), (PY_RE, r".*TypedDictT"), (PY_RE, r"pydantic.*"), (PY_RE, r"msgspec.*"), ] suppress_warnings = [ "autosectionlabel.*", "ref.python", # TODO: remove when https://github.com/sphinx-doc/sphinx/issues/4961 is fixed "config.cache", ] napoleon_google_docstring = True napoleon_include_special_with_doc = True napoleon_use_admonition_for_examples = True napoleon_use_admonition_for_notes = True napoleon_use_admonition_for_references = False napoleon_attr_annotations = True autoclass_content = "class" autodoc_class_signature = "separated" autodoc_default_options = { "special-members": True, "show-inheritance": True, "members": True, "exclude-members": "__init_subclass__,__weakref__,__subclasshook__", } autodoc_member_order = "bysource" autodoc_typehints_format = "short" auto_pytabs_min_version = (3, 8) auto_pytabs_max_version = (3, 11) auto_pytabs_compat_mode = True autosectionlabel_prefix_document = True exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] # -- Style configuration ----------------------------------------------------- html_theme = "litestar_sphinx_theme" html_title = "Polyfactory" # pygments_style = "lightbulb" todo_include_todos = True html_static_path = ["_static"] templates_path = ["_templates"] html_js_files = ["versioning.js"] html_css_files = ["style.css"] html_show_sourcelink = True html_copy_source = True html_context = { "source_type": "github", "source_user": "litestar-org", "source_repo": "polyfactory", "current_version": "latest", "versions": [ ("latest", "/latest"), ("development", "/main"), ], "version": release, } html_theme_options = { "logo_target": "/", "github_repo_name": "polyfactory", "github_url": "https://github.com/litestar-org/polyfactory", "navigation_with_keys": True, "nav_links": [ {"title": "Home", "url": "index"}, { "title": "Community", "children": [ { "title": "Contributing", "summary": "Learn how to contribute to the Type Lens project", "url": "contribution-guide", "icon": "contributing", }, { "title": "Code of Conduct", "summary": "Review the etiquette for interacting with the Litestar community", "url": "https://github.com/litestar-org/.github?tab=coc-ov-file", "icon": "coc", }, { "title": "Security", "summary": "Overview of Litestar's security protocols", "url": "https://github.com/litestar-org/.github?tab=coc-ov-file#security-ov-file", "icon": "coc", }, ], }, { "title": "About", "children": [ { "title": "Litestar Organization", "summary": "Details about the Litestar organization", "url": "https://litestar.dev/about/organization", "icon": "org", }, { "title": "Releases", "summary": "Explore the release process, versioning, and deprecation policy for Litestar", "url": "releases", "icon": "releases", }, ], }, { "title": "Release notes", "children": [ { "title": "Changelog", "url": "changelog", "summary": "All changes in the current major version", }, ], }, { "title": "Help", "children": [ { "title": "Discord Help Forum", "summary": "Dedicated Discord help forum", "url": "https://discord.gg/litestar", "icon": "coc", }, { "title": "GitHub Discussions", "summary": "GitHub Discussions", "url": "https://github.com/litestar-org/polyfactory/discussions", "icon": "coc", }, { "title": "Stack Overflow", "summary": "We monitor the <code><b>polyfactory</b></code> tag on Stack Overflow", "url": "https://stackoverflow.com/questions/tagged/polyfactory", "icon": "coc", }, ], }, {"title": "Sponsor", "url": "https://github.com/sponsors/Litestar-Org", "icon": "heart"}, ], } def update_html_context( app: Sphinx, pagename: str, templatename: str, context: dict[str, Any], doctree: document, ) -> None: context["generate_toctree_html"] = partial(context["generate_toctree_html"], startdepth=0) def delayed_setup(app: Sphinx) -> None: """When running linkcheck Shibuya causes a build failure, and checking the builder in the initial `setup` function call is not possible, so the check and extension setup has to be delayed until the builder is initialized. """ if app.builder.name == "linkcheck": return app.setup_extension("shibuya") def setup(app: Sphinx) -> dict[str, bool]: app.connect("builder-inited", delayed_setup, priority=0) app.setup_extension("litestar_sphinx_theme") return {"parallel_read_safe": True, "parallel_write_safe": True} ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/contribution-guide.rst�����������������������������������������������0000664�0000000�0000000�00000000053�14721310225�0022764�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������:orphan: .. include:: ../CONTRIBUTING.rst �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/examples/������������������������������������������������������������0000775�0000000�0000000�00000000000�14721310225�0020240�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/examples/__init__.py�������������������������������������������������0000664�0000000�0000000�00000000000�14721310225�0022337�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/examples/configuration/����������������������������������������������0000775�0000000�0000000�00000000000�14721310225�0023107�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/examples/configuration/__init__.py�����������������������������������0000664�0000000�0000000�00000000000�14721310225�0025206�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/examples/configuration/test_example_1.py�����������������������������0000664�0000000�0000000�00000001221�14721310225�0026367�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from dataclasses import dataclass from polyfactory.factories import DataclassFactory @dataclass class Person: name: str age: float height: float weight: float class PersonFactory(DataclassFactory[Person]): __random_seed__ = 1 @classmethod def name(cls) -> str: return cls.__random__.choice(["John", "Alice", "George"]) def test_random_seed() -> None: # the outcome of 'factory.__random__.choice' is deterministic, because Random has been seeded with a set value. assert PersonFactory.build().name == "John" assert PersonFactory.build().name == "George" assert PersonFactory.build().name == "John" �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/examples/configuration/test_example_2.py�����������������������������0000664�0000000�0000000�00000001261�14721310225�0026374�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from dataclasses import dataclass from random import Random from polyfactory.factories import DataclassFactory @dataclass class Person: name: str age: float height: float weight: float class PersonFactory(DataclassFactory[Person]): __random__ = Random(10) @classmethod def name(cls) -> str: return cls.__random__.choice(["John", "Alice", "George"]) def test_setting_random() -> None: # the outcome of 'factory.__random__.choice' is deterministic, because Random is configured with a set value. assert PersonFactory.build().name == "George" assert PersonFactory.build().name == "John" assert PersonFactory.build().name == "Alice" �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/examples/configuration/test_example_3.py�����������������������������0000664�0000000�0000000�00000001123�14721310225�0026372�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from dataclasses import dataclass from faker import Faker from polyfactory.factories import DataclassFactory @dataclass class Person: name: str age: float height: float weight: float class PersonFactory(DataclassFactory[Person]): __faker__ = Faker(locale="es_ES") __random_seed__ = 10 @classmethod def name(cls) -> str: return cls.__faker__.name() def test_setting_faker() -> None: # the outcome of faker deterministic because we seeded random, and it uses a spanish locale. assert PersonFactory.build().name == "Alejandra Romeu-Tolosa" ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/examples/configuration/test_example_4.py�����������������������������0000664�0000000�0000000�00000005057�14721310225�0026405�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from asyncio import sleep from dataclasses import dataclass from typing import Dict, List from uuid import UUID from polyfactory import AsyncPersistenceProtocol, SyncPersistenceProtocol from polyfactory.factories import DataclassFactory @dataclass class Person: id: UUID name: str # we will use a dictionary to persist values for the example mock_db: Dict[UUID, Person] = {} class SyncPersistenceHandler(SyncPersistenceProtocol[Person]): def save(self, data: Person) -> Person: # do stuff here to persist the value, such as use an ORM or ODM, cache in redis etc. # in our case we simply save it in the dictionary. mock_db[data.id] = data return data def save_many(self, data: List[Person]) -> List[Person]: # same as for save, here we should store the list in persistence. # in this case, we use the same dictionary. for person in data: mock_db[person.id] = person return data class AsyncPersistenceHandler(AsyncPersistenceProtocol[Person]): async def save(self, data: Person) -> Person: # do stuff here to persist the value using an async method, such as an async ORM or ODM. # in our case we simply save it in the dictionary and add a minimal sleep to mock async. mock_db[data.id] = data await sleep(0.0001) return data async def save_many(self, data: List[Person]) -> List[Person]: # same as for the async save, here we should store the list in persistence using async logic. # we again store in dict, and mock async using sleep. for person in data: mock_db[person.id] = person await sleep(0.0001) return data class PersonFactory(DataclassFactory[Person]): __sync_persistence__ = SyncPersistenceHandler __async_persistence__ = AsyncPersistenceHandler def test_sync_persistence_build() -> None: person_instance = PersonFactory.create_sync() assert mock_db[person_instance.id] is person_instance def test_sync_persistence_batch() -> None: person_batch = PersonFactory.create_batch_sync(10) for person_instance in person_batch: assert mock_db[person_instance.id] is person_instance async def test_async_persistence_build() -> None: person_instance = await PersonFactory.create_async() assert mock_db[person_instance.id] is person_instance async def test_async_persistence_batch() -> None: person_batch = await PersonFactory.create_batch_async(10) for person_instance in person_batch: assert mock_db[person_instance.id] is person_instance ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/examples/configuration/test_example_5.py�����������������������������0000664�0000000�0000000�00000001744�14721310225�0026405�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from dataclasses import dataclass from datetime import date, datetime from enum import Enum from typing import Any, Dict, List, Union from uuid import UUID from polyfactory import Use from polyfactory.factories import DataclassFactory class Species(str, Enum): CAT = "Cat" DOG = "Dog" @dataclass class Pet: name: str species: Species sound: str @dataclass class Person: id: UUID name: str hobbies: List[str] age: Union[float, int] birthday: Union[datetime, date] pets: List[Pet] assets: List[Dict[str, Dict[str, Any]]] class PetFactory(DataclassFactory[Pet]): __set_as_default_factory_for_type__ = True name = Use(DataclassFactory.__random__.choice, ["Roxy", "Spammy", "Moshe"]) class PersonFactory(DataclassFactory[Person]): ... def test_default_pet_factory() -> None: person_instance = PersonFactory.build() assert len(person_instance.pets) > 0 assert person_instance.pets[0].name in ["Roxy", "Spammy", "Moshe"] ����������������������������python-polyfactory-2.18.1/docs/examples/configuration/test_example_6.py�����������������������������0000664�0000000�0000000�00000000672�14721310225�0026405�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from dataclasses import dataclass from typing import Tuple from polyfactory.factories import DataclassFactory @dataclass class Owner: cars: Tuple[str, ...] class OwnerFactory(DataclassFactory[Owner]): __randomize_collection_length__ = True __min_collection_length__ = 2 __max_collection_length__ = 5 def test_randomized_collection_length() -> None: owner = OwnerFactory.build() assert 2 <= len(owner.cars) <= 5 ����������������������������������������������������������������������python-polyfactory-2.18.1/docs/examples/configuration/test_example_7.py�����������������������������0000664�0000000�0000000�00000000671�14721310225�0026405�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from dataclasses import dataclass from typing import Optional from uuid import UUID from polyfactory.factories.dataclass_factory import DataclassFactory @dataclass class Person: id: UUID name: Optional[str] class PersonFactory(DataclassFactory[Person]): __allow_none_optionals__ = False def test_optional_type_ignored() -> None: person_instance = PersonFactory.build() assert isinstance(person_instance.name, str) �����������������������������������������������������������������������python-polyfactory-2.18.1/docs/examples/configuration/test_example_8.py�����������������������������0000664�0000000�0000000�00000001140�14721310225�0026376�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from dataclasses import dataclass from uuid import UUID import pytest from polyfactory import ConfigurationException, PostGenerated from polyfactory.factories.dataclass_factory import DataclassFactory @dataclass class Person: id: UUID def test_check_factory_fields() -> None: with pytest.raises( ConfigurationException, match="unknown_field is declared on the factory PersonFactory but it is not part of the model Person", ): class PersonFactory(DataclassFactory[Person]): __check_model__ = True unknown_field = PostGenerated(lambda: "foo") ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/examples/configuration/test_example_9.py�����������������������������0000664�0000000�0000000�00000000751�14721310225�0026406�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from dataclasses import dataclass from enum import Enum from polyfactory.factories import DataclassFactory class Species(str, Enum): CAT = "Cat" DOG = "Dog" @dataclass class Pet: name: str sound: str = "meow" species: Species = Species.CAT class PetFactory(DataclassFactory[Pet]): __model__ = Pet __use_defaults__ = True def test_use_default() -> None: pet = PetFactory.build() assert pet.species == Species.CAT assert pet.sound == "meow" �����������������������python-polyfactory-2.18.1/docs/examples/creating_base_factories/������������������������������������0000775�0000000�0000000�00000000000�14721310225�0025065�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/examples/creating_base_factories/__init__.py�������������������������0000664�0000000�0000000�00000000000�14721310225�0027164�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/examples/declaring_factories/����������������������������������������0000775�0000000�0000000�00000000000�14721310225�0024227�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/examples/declaring_factories/__init__.py�����������������������������0000664�0000000�0000000�00000000000�14721310225�0026326�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/examples/declaring_factories/test_example_1.py�����������������������0000664�0000000�0000000�00000001102�14721310225�0027505�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from dataclasses import dataclass from polyfactory.factories import DataclassFactory @dataclass class Person: name: str age: float height: float weight: float class PersonFactory(DataclassFactory[Person]): __model__ = Person def test_is_person() -> None: person_instance = PersonFactory.build() assert isinstance(person_instance, Person) assert isinstance(person_instance.name, str) assert isinstance(person_instance.age, float) assert isinstance(person_instance.height, float) assert isinstance(person_instance.weight, float) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/examples/declaring_factories/test_example_2.py�����������������������0000664�0000000�0000000�00000001104�14721310225�0027510�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from typing import TypedDict from polyfactory.factories import TypedDictFactory class Person(TypedDict): name: str age: float height: float weight: float class PersonFactory(TypedDictFactory[Person]): ... def test_is_person() -> None: person_instance = PersonFactory.build() assert isinstance(person_instance, dict) assert isinstance(person_instance.get("name"), str) assert isinstance(person_instance.get("age"), float) assert isinstance(person_instance.get("height"), float) assert isinstance(person_instance.get("weight"), float) ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/examples/declaring_factories/test_example_3.py�����������������������0000664�0000000�0000000�00000001065�14721310225�0027517�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from pydantic import BaseModel from polyfactory.factories.pydantic_factory import ModelFactory class Person(BaseModel): name: str age: float height: float weight: float class PersonFactory(ModelFactory[Person]): ... def test_is_person() -> None: person_instance = PersonFactory.build() assert isinstance(person_instance, Person) assert isinstance(person_instance.name, str) assert isinstance(person_instance.age, float) assert isinstance(person_instance.height, float) assert isinstance(person_instance.weight, float) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/examples/declaring_factories/test_example_4.py�����������������������0000664�0000000�0000000�00000001070�14721310225�0027514�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from pydantic.dataclasses import dataclass from polyfactory.factories import DataclassFactory @dataclass class Person: name: str age: float height: float weight: float class PersonFactory(DataclassFactory[Person]): ... def test_is_person() -> None: person_instance = PersonFactory.build() assert isinstance(person_instance, Person) assert isinstance(person_instance.name, str) assert isinstance(person_instance.age, float) assert isinstance(person_instance.height, float) assert isinstance(person_instance.weight, float) ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/examples/declaring_factories/test_example_5.py�����������������������0000664�0000000�0000000�00000001421�14721310225�0027515�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from dataclasses import dataclass from datetime import date, datetime from enum import Enum from typing import Any, Dict, List, Union from uuid import UUID from polyfactory.factories import DataclassFactory class Species(str, Enum): CAT = "Cat" DOG = "Dog" @dataclass class Pet: name: str species: Species sound: str @dataclass class Person: id: UUID name: str hobbies: List[str] age: Union[float, int] birthday: Union[datetime, date] pets: List[Pet] assets: List[Dict[str, Dict[str, Any]]] class PersonFactory(DataclassFactory[Person]): ... def test_dynamic_factory_generation() -> None: person_instance = PersonFactory.build() assert len(person_instance.pets) > 0 assert isinstance(person_instance.pets[0], Pet) �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/examples/declaring_factories/test_example_6.py�����������������������0000664�0000000�0000000�00000000661�14721310225�0027523�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from dataclasses import dataclass from enum import Enum from polyfactory.factories import DataclassFactory class Species(str, Enum): CAT = "Cat" DOG = "Dog" @dataclass class Pet: name: str species: Species sound: str def test_imperative_factory_creation() -> None: pet_factory = DataclassFactory.create_factory(model=Pet) pet_instance = pet_factory.build() assert isinstance(pet_instance, Pet) �������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/examples/declaring_factories/test_example_7.py�����������������������0000664�0000000�0000000�00000001146�14721310225�0027523�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from datetime import date, datetime from typing import Any, Dict, List, Union from uuid import UUID import attrs from polyfactory.factories.attrs_factory import AttrsFactory @attrs.define class Person: id: UUID name: str hobbies: List[str] age: Union[float, int] # an aliased variable birthday: Union[datetime, date] = attrs.field(alias="date_of_birth") # a "private" variable _assets: List[Dict[str, Dict[str, Any]]] class PersonFactory(AttrsFactory[Person]): ... def test_person_factory() -> None: person = PersonFactory.build() assert isinstance(person, Person) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/examples/declaring_factories/test_example_8.py�����������������������0000664�0000000�0000000�00000001121�14721310225�0027515�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from dataclasses import dataclass from enum import Enum from polyfactory.factories import DataclassFactory class Species(str, Enum): CAT = "Cat" DOG = "Dog" RABBIT = "Rabbit" MOUSE = "Mouse" @dataclass class Pet: name: str species: Species sound: str def test_imperative_sub_factory_creation() -> None: pet_factory = DataclassFactory.create_factory(model=Pet) cat_factory = pet_factory.create_factory(species=Species.CAT) cat_instance = cat_factory.build() assert isinstance(cat_instance, Pet) assert cat_instance.species == Species.CAT �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/examples/decorators/�������������������������������������������������0000775�0000000�0000000�00000000000�14721310225�0022405�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/examples/decorators/test_example_1.py��������������������������������0000664�0000000�0000000�00000001360�14721310225�0025671�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from dataclasses import dataclass, field from datetime import datetime, timedelta from polyfactory.decorators import post_generated from polyfactory.factories import DataclassFactory @dataclass class DatetimeRange: to_dt: datetime from_dt: datetime = field(default_factory=datetime.now) class DatetimeRangeFactory(DataclassFactory[DatetimeRange]): @post_generated @classmethod def to_dt(cls, from_dt: datetime) -> datetime: return from_dt + cls.__faker__.time_delta("+3d") def test_post_generated() -> None: date_range_instance = DatetimeRangeFactory.build() assert date_range_instance.to_dt > date_range_instance.from_dt assert date_range_instance.to_dt < date_range_instance.from_dt + timedelta(days=3) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/examples/fields/�����������������������������������������������������0000775�0000000�0000000�00000000000�14721310225�0021506�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/examples/fields/__init__.py������������������������������������������0000664�0000000�0000000�00000000000�14721310225�0023605�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/examples/fields/test_example_1.py������������������������������������0000664�0000000�0000000�00000001546�14721310225�0025000�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from dataclasses import dataclass from datetime import date, datetime from enum import Enum from typing import Any, Dict, List, Union from uuid import UUID from polyfactory.factories import DataclassFactory class Species(str, Enum): CAT = "Cat" DOG = "Dog" @dataclass class Pet: name: str species: Species sound: str @dataclass class Person: id: UUID name: str hobbies: List[str] age: Union[float, int] birthday: Union[datetime, date] pets: List[Pet] assets: List[Dict[str, Dict[str, Any]]] pet_instance = Pet(name="Roxy", sound="woof woof", species=Species.DOG) class PersonFactory(DataclassFactory[Person]): pets = [pet_instance] def test_is_pet_instance() -> None: person_instance = PersonFactory.build() assert len(person_instance.pets) == 1 assert person_instance.pets[0] == pet_instance ����������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/examples/fields/test_example_2.py������������������������������������0000664�0000000�0000000�00000002025�14721310225�0024772�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from dataclasses import dataclass from datetime import date, datetime from enum import Enum from typing import Any, Dict, List, Union from uuid import UUID from polyfactory import Use from polyfactory.factories import DataclassFactory class Species(str, Enum): CAT = "Cat" DOG = "Dog" @dataclass class Pet: name: str species: Species sound: str @dataclass class Person: id: UUID name: str hobbies: List[str] age: Union[float, int] birthday: Union[datetime, date] pets: List[Pet] assets: List[Dict[str, Dict[str, Any]]] class PetFactory(DataclassFactory[Pet]): name = Use(DataclassFactory.__random__.choice, ["Ralph", "Roxy"]) species = Use(DataclassFactory.__random__.choice, list(Species)) class PersonFactory(DataclassFactory[Person]): pets = Use(PetFactory.batch, size=2) def test_pet_choices() -> None: person_instance = PersonFactory.build() assert len(person_instance.pets) == 2 assert all(pet.name in ["Ralph", "Roxy"] for pet in person_instance.pets) �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/examples/fields/test_example_3.py������������������������������������0000664�0000000�0000000�00000002033�14721310225�0024772�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from dataclasses import dataclass from datetime import date, datetime from enum import Enum from typing import Any, Dict, List, Union from uuid import UUID from polyfactory import Use from polyfactory.factories import DataclassFactory class Species(str, Enum): CAT = "Cat" DOG = "Dog" @dataclass class Pet: name: str species: Species sound: str @dataclass class Person: id: UUID name: str hobbies: List[str] age: Union[float, int] birthday: Union[datetime, date] pets: List[Pet] assets: List[Dict[str, Dict[str, Any]]] class PetFactory(DataclassFactory[Pet]): name = lambda: DataclassFactory.__random__.choice(["Ralph", "Roxy"]) species = lambda: DataclassFactory.__random__.choice(list(Species)) class PersonFactory(DataclassFactory[Person]): pets = Use(PetFactory.batch, size=2) def test_pet_choices() -> None: person_instance = PersonFactory.build() assert len(person_instance.pets) == 2 assert all(pet.name in ["Ralph", "Roxy"] for pet in person_instance.pets) �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/examples/fields/test_example_4.py������������������������������������0000664�0000000�0000000�00000002120�14721310225�0024770�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from dataclasses import dataclass from datetime import date, datetime from enum import Enum from typing import Any, Dict, List, Union from uuid import UUID from polyfactory import Use from polyfactory.factories import DataclassFactory class Species(str, Enum): CAT = "Cat" DOG = "Dog" @dataclass class Pet: name: str species: Species sound: str @dataclass class Person: id: UUID name: str hobbies: List[str] age: Union[float, int] birthday: Union[datetime, date] pets: List[Pet] assets: List[Dict[str, Dict[str, Any]]] class PetFactory(DataclassFactory[Pet]): @classmethod def name(cls) -> str: return cls.__random__.choice(["Ralph", "Roxy"]) @classmethod def species(cls) -> str: return cls.__random__.choice(list(Species)) class PersonFactory(DataclassFactory[Person]): pets = Use(PetFactory.batch, size=2) def test_pet_choices() -> None: person_instance = PersonFactory.build() assert len(person_instance.pets) == 2 assert all(pet.name in ["Ralph", "Roxy"] for pet in person_instance.pets) ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/examples/fields/test_example_5.py������������������������������������0000664�0000000�0000000�00000000615�14721310225�0025000�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from typing import TypedDict from polyfactory import Ignore from polyfactory.factories import TypedDictFactory class Person(TypedDict): id: int name: str class PersonFactory(TypedDictFactory[Person]): id = Ignore() def test_id_is_ignored() -> None: person_instance = PersonFactory.build() assert person_instance.get("name") assert person_instance.get("id") is None �������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/examples/fields/test_example_6.py������������������������������������0000664�0000000�0000000�00000001230�14721310225�0024773�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from typing import TypedDict import pytest from polyfactory import Require from polyfactory.exceptions import MissingBuildKwargException from polyfactory.factories import TypedDictFactory class Person(TypedDict): id: int name: str class PersonFactory(TypedDictFactory[Person]): id = Require() def test_id_is_required() -> None: # this will not raise an exception person_instance = PersonFactory.build(id=1) assert person_instance.get("name") assert person_instance.get("id") == 1 # but when no kwarg is passed, an exception will be raised: with pytest.raises(MissingBuildKwargException): PersonFactory.build() ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/examples/fields/test_example_7.py������������������������������������0000664�0000000�0000000�00000001376�14721310225�0025007�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from dataclasses import dataclass, field from datetime import datetime, timedelta from typing import Any, Dict from polyfactory import PostGenerated from polyfactory.factories import DataclassFactory def add_timedelta(name: str, values: Dict[str, datetime], *args: Any, **kwargs: Any) -> datetime: delta = timedelta(days=1) return values["from_dt"] + delta @dataclass class DatetimeRange: to_dt: datetime from_dt: datetime = field(default_factory=datetime.now) class DatetimeRangeFactory(DataclassFactory[DatetimeRange]): to_dt = PostGenerated(add_timedelta) def test_post_generated() -> None: date_range_instance = DatetimeRangeFactory.build() assert date_range_instance.to_dt == date_range_instance.from_dt + timedelta(days=1) ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/examples/fields/test_example_8.py������������������������������������0000664�0000000�0000000�00000002035�14721310225�0025001�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from dataclasses import dataclass from datetime import date, datetime from enum import Enum from typing import Any, Dict, List, Union from uuid import UUID from polyfactory.factories import DataclassFactory class Species(str, Enum): CAT = "Cat" DOG = "Dog" @dataclass class Pet: name: str species: Species sound: str @dataclass class Person: id: UUID name: str hobbies: List[str] age: Union[float, int] birthday: Union[datetime, date] pet: Pet assets: List[Dict[str, Dict[str, Any]]] class PetFactory(DataclassFactory[Pet]): name = lambda: DataclassFactory.__random__.choice(["Ralph", "Roxy"]) class PersonFactory(DataclassFactory[Person]): pet = PetFactory def test_subfactory() -> None: person_instance = PersonFactory.build() assert isinstance(person_instance.pet, Pet) assert person_instance.pet.name in ["Ralph", "Roxy"] person_instance_with_pet_name = PersonFactory.build(pet={"name": "Winston"}) assert person_instance_with_pet_name.pet.name == "Winston" ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/examples/fixtures/���������������������������������������������������0000775�0000000�0000000�00000000000�14721310225�0022111�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/examples/fixtures/__init__.py����������������������������������������0000664�0000000�0000000�00000000000�14721310225�0024210�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/examples/fixtures/test_example_1.py����������������������������������0000664�0000000�0000000�00000001363�14721310225�0025400�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from dataclasses import dataclass from datetime import date, datetime from typing import List, Optional, Union from uuid import UUID from polyfactory.factories import DataclassFactory from polyfactory.pytest_plugin import register_fixture @dataclass class Person: id: UUID name: str hobbies: Optional[List[str]] nicks: List[str] age: Union[float, int] birthday: Union[datetime, date] @register_fixture class PersonFactory(DataclassFactory[Person]): ... # NOTE: PersonFactory is no more a factory class, it is a callable that returns the decorated factory def test_person_factory(person_factory: DataclassFactory[Person]) -> None: person_instance = person_factory.build() assert isinstance(person_instance, Person) �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/examples/fixtures/test_example_2.py����������������������������������0000664�0000000�0000000�00000001511�14721310225�0025374�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from dataclasses import dataclass from datetime import date, datetime from typing import List, Optional, Union from uuid import UUID from polyfactory.factories import DataclassFactory from polyfactory.pytest_plugin import register_fixture @dataclass class Person: id: UUID name: str hobbies: Optional[List[str]] nicks: List[str] age: Union[float, int] birthday: Union[datetime, date] class PersonFactory(DataclassFactory[Person]): ... person_factory_fixture = register_fixture(PersonFactory) def test_person_factory(person_factory: PersonFactory) -> None: person_instance = person_factory.build() assert isinstance(person_instance, Person) # we can still access the factory class itself- another_person_instance = PersonFactory.build() assert isinstance(another_person_instance, Person) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/examples/fixtures/test_example_3.py����������������������������������0000664�0000000�0000000�00000001330�14721310225�0025374�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from dataclasses import dataclass from datetime import date, datetime from typing import List, Optional, Union from uuid import UUID from polyfactory.factories import DataclassFactory from polyfactory.pytest_plugin import register_fixture @dataclass class Person: id: UUID name: str hobbies: Optional[List[str]] nicks: List[str] age: Union[float, int] birthday: Union[datetime, date] class PersonFactory(DataclassFactory[Person]): ... person_factory_fixture = register_fixture(PersonFactory, name="aliased_person_factory") def test_person_factory(aliased_person_factory: PersonFactory) -> None: person_instance = aliased_person_factory.build() assert isinstance(person_instance, Person) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/examples/fixtures/test_example_4.py����������������������������������0000664�0000000�0000000�00000001757�14721310225�0025412�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from dataclasses import dataclass from datetime import date, datetime from typing import List, Optional, Union from uuid import UUID from polyfactory import Fixture from polyfactory.factories import DataclassFactory from polyfactory.pytest_plugin import register_fixture @dataclass class Person: id: UUID name: str hobbies: Optional[List[str]] nicks: List[str] age: Union[float, int] birthday: Union[datetime, date] @dataclass class ClassRoom: teacher: Person pupils: List[Person] @register_fixture class PersonFactory(DataclassFactory[Person]): ... class ClassRoomFactory(DataclassFactory[ClassRoom]): teacher = Fixture(PersonFactory, name="Ludmilla Newman") pupils = Fixture(PersonFactory, size=20) def test_fixture_field() -> None: classroom_instance = ClassRoomFactory.build() assert isinstance(classroom_instance.teacher, Person) assert classroom_instance.teacher.name == "Ludmilla Newman" assert len(classroom_instance.pupils) == 20 �����������������python-polyfactory-2.18.1/docs/examples/handling_custom_types/��������������������������������������0000775�0000000�0000000�00000000000�14721310225�0024642�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/examples/handling_custom_types/__init__.py���������������������������0000664�0000000�0000000�00000000000�14721310225�0026741�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/examples/handling_custom_types/test_example_1.py���������������������0000664�0000000�0000000�00000002304�14721310225�0030125�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from dataclasses import dataclass from typing import Any, Dict, Type from uuid import UUID from polyfactory.factories import DataclassFactory # we created a special class we will use in our code class CustomSecret: def __init__(self, value: str) -> None: self.value = value def __repr__(self) -> str: return "*" * len(self.value) def __str__(self) -> str: return "*" * len(self.value) @dataclass class Person: id: UUID secret: CustomSecret # by default the factory class cannot handle unknown types, # so we need to override the provider map to add it: class PersonFactory(DataclassFactory[Person]): @classmethod def get_provider_map(cls) -> Dict[Type, Any]: providers_map = super().get_provider_map() return { CustomSecret: lambda: CustomSecret("jeronimo"), **providers_map, } def test_custom_secret_creation() -> None: person_instance = PersonFactory.build() assert isinstance(person_instance.secret, CustomSecret) assert repr(person_instance.secret) == "*" * len("jeronimo") assert str(person_instance.secret) == "*" * len("jeronimo") assert person_instance.secret.value == "jeronimo" ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/examples/handling_custom_types/test_example_2.py���������������������0000664�0000000�0000000�00000002605�14721310225�0030132�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from dataclasses import dataclass from typing import Any, Dict, Generic, Type, TypeVar from uuid import UUID from polyfactory.factories import DataclassFactory # we created a special class we will use in our code class CustomSecret: def __init__(self, value: str) -> None: self.value = value def __repr__(self) -> str: return "*" * len(self.value) def __str__(self) -> str: return "*" * len(self.value) T = TypeVar("T") # we create a custom base factory to handle dataclasses, with an extended provider map class CustomDataclassFactory(Generic[T], DataclassFactory[T]): __is_base_factory__ = True @classmethod def get_provider_map(cls) -> Dict[Type, Any]: providers_map = super().get_provider_map() return { CustomSecret: lambda: CustomSecret("jeronimo"), **providers_map, } @dataclass class Person: id: UUID secret: CustomSecret # we use our CustomDataclassFactory as a base for the PersonFactory class PersonFactory(CustomDataclassFactory[Person]): ... def test_custom_dataclass_base_factory() -> None: person_instance = PersonFactory.build() assert isinstance(person_instance.secret, CustomSecret) assert repr(person_instance.secret) == "*" * len("jeronimo") assert str(person_instance.secret) == "*" * len("jeronimo") assert person_instance.secret.value == "jeronimo" ���������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/examples/library_factories/������������������������������������������0000775�0000000�0000000�00000000000�14721310225�0023743�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/examples/library_factories/__init__.py�������������������������������0000664�0000000�0000000�00000000000�14721310225�0026042�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/examples/library_factories/sqlalchemy_factory/�����������������������0000775�0000000�0000000�00000000000�14721310225�0027634�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/examples/library_factories/sqlalchemy_factory/__init__.py������������0000664�0000000�0000000�00000000000�14721310225�0031733�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/examples/library_factories/sqlalchemy_factory/conftest.py������������0000664�0000000�0000000�00000000462�14721310225�0032035�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from collections.abc import Iterable import pytest from docs.examples.library_factories.sqlalchemy_factory.test_example_4 import BaseFactory @pytest.fixture(scope="module") def _remove_default_factories() -> Iterable[None]: yield BaseFactory._base_factories.remove(BaseFactory) # noqa: SLF001 ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/examples/library_factories/sqlalchemy_factory/test_example_1.py������0000664�0000000�0000000�00000000720�14721310225�0033117�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column from polyfactory.factories.sqlalchemy_factory import SQLAlchemyFactory class Base(DeclarativeBase): ... class Author(Base): __tablename__ = "authors" id: Mapped[int] = mapped_column(primary_key=True) name: Mapped[str] class AuthorFactory(SQLAlchemyFactory[Author]): ... def test_sqla_factory() -> None: author = AuthorFactory.build() assert isinstance(author, Author) ������������������������������������������������python-polyfactory-2.18.1/docs/examples/library_factories/sqlalchemy_factory/test_example_2.py������0000664�0000000�0000000�00000002041�14721310225�0033116�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from typing import List from sqlalchemy import ForeignKey from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship from polyfactory.factories.sqlalchemy_factory import SQLAlchemyFactory class Base(DeclarativeBase): ... class Author(Base): __tablename__ = "authors" id: Mapped[int] = mapped_column(primary_key=True) name: Mapped[str] books: Mapped[List["Book"]] = relationship("Book", uselist=True) class Book(Base): __tablename__ = "books" id: Mapped[int] = mapped_column(primary_key=True) author_id: Mapped[int] = mapped_column(ForeignKey(Author.id)) class AuthorFactory(SQLAlchemyFactory[Author]): ... class AuthorFactoryWithRelationship(SQLAlchemyFactory[Author]): __set_relationships__ = True def test_sqla_factory_without_relationship() -> None: author = AuthorFactory.build() assert author.books == [] def test_sqla_factory() -> None: author = AuthorFactoryWithRelationship.build() assert isinstance(author, Author) assert isinstance(author.books[0], Book) �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/examples/library_factories/sqlalchemy_factory/test_example_3.py������0000664�0000000�0000000�00000002110�14721310225�0033114�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from typing import List from sqlalchemy import ForeignKey, create_engine from sqlalchemy.orm import DeclarativeBase, Mapped, Session, mapped_column, relationship from polyfactory.factories.sqlalchemy_factory import SQLAlchemyFactory class Base(DeclarativeBase): ... class Author(Base): __tablename__ = "authors" id: Mapped[int] = mapped_column(primary_key=True) name: Mapped[str] books: Mapped[List["Book"]] = relationship("Book", uselist=True) class Book(Base): __tablename__ = "books" id: Mapped[int] = mapped_column(primary_key=True) author_id: Mapped[int] = mapped_column(ForeignKey(Author.id)) class AuthorFactory(SQLAlchemyFactory[Author]): __set_relationships__ = True def test_sqla_factory_persistence() -> None: engine = create_engine("sqlite:///:memory:") Base.metadata.create_all(engine) session = Session(engine) AuthorFactory.__session__ = session # Or using a callable that returns a session author = AuthorFactory.create_sync() assert author.id is not None assert author.id == author.books[0].author_id ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/examples/library_factories/sqlalchemy_factory/test_example_4.py������0000664�0000000�0000000�00000003001�14721310225�0033115�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from typing import List from sqlalchemy import ForeignKey, create_engine from sqlalchemy.orm import DeclarativeBase, Mapped, Session, mapped_column, relationship from polyfactory.factories.sqlalchemy_factory import SQLAlchemyFactory, T class Base(DeclarativeBase): ... class Author(Base): __tablename__ = "authors" id: Mapped[int] = mapped_column(primary_key=True) name: Mapped[str] books: Mapped[List["Book"]] = relationship( "Book", uselist=True, back_populates="author", ) class Book(Base): __tablename__ = "books" id: Mapped[int] = mapped_column(primary_key=True) author_id: Mapped[int] = mapped_column(ForeignKey(Author.id), nullable=False) author: Mapped[Author] = relationship( "Author", uselist=False, back_populates="books", ) class BaseFactory(SQLAlchemyFactory[T]): __is_base_factory__ = True __set_relationships__ = True __randomize_collection_length__ = True __min_collection_length__ = 3 def test_custom_sqla_factory() -> None: engine = create_engine("sqlite:///:memory:") Base.metadata.create_all(engine) session = Session(engine) BaseFactory.__session__ = session # Or using a callable that returns a session author = BaseFactory.create_factory(Author).create_sync() assert author.id is not None assert author.id == author.books[0].author_id book = BaseFactory.create_factory(Book).create_sync() assert book.id is not None assert book.author.books == [book] �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/examples/model_coverage/���������������������������������������������0000775�0000000�0000000�00000000000�14721310225�0023213�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/examples/model_coverage/__init__.py����������������������������������0000664�0000000�0000000�00000000000�14721310225�0025312�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/examples/model_coverage/test_example_1.py����������������������������0000664�0000000�0000000�00000001443�14721310225�0026501�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from __future__ import annotations from dataclasses import dataclass from typing import Literal from polyfactory.factories.dataclass_factory import DataclassFactory @dataclass class Car: model: str @dataclass class Boat: can_float: bool @dataclass class Profile: age: int favourite_color: Literal["red", "green", "blue"] vehicle: Car | Boat class ProfileFactory(DataclassFactory[Profile]): ... def test_profile_coverage() -> None: profiles = list(ProfileFactory.coverage()) assert profiles[0].favourite_color == "red" assert isinstance(profiles[0].vehicle, Car) assert profiles[1].favourite_color == "green" assert isinstance(profiles[1].vehicle, Boat) assert profiles[2].favourite_color == "blue" assert isinstance(profiles[2].vehicle, Car) �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/examples/model_coverage/test_example_2.py����������������������������0000664�0000000�0000000�00000002000�14721310225�0026470�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from __future__ import annotations from dataclasses import dataclass from typing import Literal from polyfactory.factories.dataclass_factory import DataclassFactory @dataclass class Car: model: str @dataclass class Boat: can_float: bool @dataclass class Profile: age: int favourite_color: Literal["red", "green", "blue"] vehicle: Car | Boat @dataclass class SocialGroup: members: list[Profile] class SocialGroupFactory(DataclassFactory[SocialGroup]): ... def test_social_group_coverage() -> None: groups = list(SocialGroupFactory.coverage()) assert len(groups) == 3 for group in groups: assert len(group.members) == 1 assert groups[0].members[0].favourite_color == "red" assert isinstance(groups[0].members[0].vehicle, Car) assert groups[1].members[0].favourite_color == "green" assert isinstance(groups[1].members[0].vehicle, Boat) assert groups[2].members[0].favourite_color == "blue" assert isinstance(groups[2].members[0].vehicle, Car) python-polyfactory-2.18.1/docs/getting-started.rst��������������������������������������������������0000664�0000000�0000000�00000003410�14721310225�0022257�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������=============== Getting Started =============== Polyfactory is a simple and powerful mock data generation library, based around type hints and supporting :doc:`dataclasses <python:library/dataclasses>`, :class:`TypedDicts <typing.TypedDict>`, Pydantic models, :class:`msgspec Struct's <msgspec.Struct>` and more. Installation ------------ .. code-block:: bash pip install polyfactory Example ------- .. literalinclude:: /examples/declaring_factories/test_example_1.py :caption: Minimal example using a dataclass :language: python That is it - with almost no work, we are able to create a mock data object fitting the ``Person`` class model definition. This is possible because of the typing information available on the dataclass, which are used as a source of truth for data generation. The factory parses the information stored in the dataclass and generates a dictionary of kwargs that are passed to the ``Person`` class constructor. Relation to ``pydantic-factories`` ---------------------------------- Prior to version 2, this library was known as `pydantic-factories <https://pypi.org/project/pydantic-factories/>`_, a name under which it gained quite a bit of popularity. A main motivator for the 2.0 release was that we wanted to support more than just Pydantic models, something which also required a change to its core architecture. As this library would no longer be directly tied to Pydantic, ``polyfactory`` was chosen as its new name to reflect its capabilities; It can generate mock data for :doc:`dataclasses <python:library/dataclasses>`, :class:`TypedDicts <typing.TypedDict>`, `Pydantic <https://docs.pydantic.dev/latest/>`_, `Odmantic <https://art049.github.io/odmantic/>`_, and `Beanie ODM <https://beanie-odm.dev/>`_ models, as well as custom factories. ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/index.rst������������������������������������������������������������0000664�0000000�0000000�00000013112�14721310225�0020261�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������:layout: landing :description: Polyfactory is a simple and powerful mock data generation library. .. container:: :name: home-head .. image:: https://raw.githubusercontent.com/litestar-org/branding/main/assets/Branding%20-%20SVG%20-%20Transparent/Badge%20-%20Blue%20and%20Yellow.svg :alt: Litestar Framework :width: 400 :height: 400 .. container:: .. raw:: html <h1>Polyfactory</h1> .. container:: badges :name: badges .. image:: https://img.shields.io/github/actions/workflow/status/litestar-org/polyfactory/publish.yml?labelColor=202235&logo=github&logoColor=edb641 :alt: GitHub Actions Latest Release Workflow Status .. image:: https://img.shields.io/github/actions/workflow/status/litestar-org/polyfactory/ci.yml?labelColor=202235&logo=github&logoColor=edb641 :alt: GitHub Actions CI Workflow Status .. image:: https://img.shields.io/github/actions/workflow/status/litestar-org/polyfactory/docs.yml?labelColor=202235&logo=github&logoColor=edb641 :alt: GitHub Actions Docs Build Workflow Status .. image:: https://img.shields.io/codecov/c/github/litestar-org/polyfactory?labelColor=202235&logo=codecov&logoColor=edb641 :alt: Coverage .. image:: https://img.shields.io/pypi/v/polyfactory?labelColor=202235&color=edb641&logo=python&logoColor=edb641 :alt: PyPI Version .. image:: https://img.shields.io/github/all-contributors/litestar-org/polyfactory?labelColor=202235&color=edb641&logoColor=edb641 :alt: Contributor Count .. image:: https://img.shields.io/pypi/dm/polyfactory?logo=python&label=polyfactory%20downloads&labelColor=202235&color=edb641&logoColor=edb641 :alt: PyPI Downloads .. image:: https://img.shields.io/pypi/pyversions/polyfactory?labelColor=202235&color=edb641&logo=python&logoColor=edb641 :alt: Supported Python Versions .. rst-class:: lead Polyfactory is a simple and powerful mock data generation library, based around type hints and supporting :doc:`dataclasses <python:library/dataclasses>`, :class:`TypedDicts <typing.TypedDict>`, Pydantic models, :class:`msgspec Struct's <msgspec.Struct>` and more. .. container:: buttons :doc:`Get Started <getting-started>` `Usage Docs <usage>`_ `API Docs <reference>`_ `Blog <https://blog.litestar.dev>`_ .. grid:: 1 1 2 2 :padding: 0 :gutter: 2 .. grid-item-card:: :octicon:`versions` Changelog :link: changelog :link-type: doc The latest updates and enhancements to Polyfactory .. grid-item-card:: :octicon:`comment-discussion` Discussions :link: https://github.com/litestar-org/polyfactory/discussions Join discussions, pose questions, or share insights. .. grid-item-card:: :octicon:`issue-opened` Issues :link: https://github.com/litestar-org/polyfactory/issues Report issues or suggest new features. .. grid-item-card:: :octicon:`beaker` Contributing :link: contribution-guide :link-type: doc Contribute to Litestar's growth with code, docs, and more. Sponsors -------- .. rst-class:: lead Litestar is a community-driven, open-source initiative that thrives on the generous contributions of our sponsors, enabling us to pursue innovative developments and continue our mission to provide exceptional tools and resources to our users. A huge thank you to our current sponsors: .. container:: :name: sponsors-section .. grid:: 3 :class-row: surface :padding: 0 :gutter: 2 .. grid-item-card:: :link: https://github.com/scalar/scalar .. image:: https://raw.githubusercontent.com/litestar-org/branding/main/assets/sponsors/scalar.svg :alt: Scalar.com :class: sponsor `Scalar.com <https://github.com/scalar/scalar>`_ .. grid-item-card:: :link: https://telemetrysports.com/ .. image:: https://raw.githubusercontent.com/litestar-org/branding/main/assets/sponsors/telemetry-sports/unofficial-telemetry-whitebg.svg :alt: Telemetry Sports :class: sponsor `Telemetry Sports <https://telemetrysports.com/>`_ .. grid-item-card:: :link: https://www.stok.kr/ .. image:: https://avatars.githubusercontent.com/u/144093421 :alt: Stok :class: sponsor `Stok <https://www.stok.kr/>`_ We invite organizations and individuals to join our sponsorship program. By becoming a sponsor on platforms like `Polar <sponsor-polar_>`_, `GitHub <sponsor-github_>`_ and `Open Collective <sponsor-oc_>`_, you can play a pivotal role in our project's growth. On top of regular sponsorship, we engage in pledge-based sponsorship opportunities through `Polar <sponsor-polar_>`_, where you can pledge an amount towards an issue or feature you would like to see implemented. .. _sponsor-github: https://github.com/sponsors/litestar-org .. _sponsor-oc: https://opencollective.com/litestar .. _sponsor-polar: https://polar.sh/litestar-org .. toctree:: :titlesonly: :caption: Documentation :hidden: getting-started usage/index reference/index .. toctree:: :titlesonly: :caption: Contributing :hidden: changelog contribution-guide Available Issues <https://github.com/search?q=user%3Alitestar-org+state%3Aopen+label%3A%22good+first+issue%22+++no%3Aassignee+repo%3A%22polyfactory%22&type=issues> Code of Conduct <https://github.com/litestar-org/.github?tab=coc-ov-file#readme> ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/reference/�����������������������������������������������������������0000775�0000000�0000000�00000000000�14721310225�0020360�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/reference/constants.rst����������������������������������������������0000664�0000000�0000000�00000000277�14721310225�0023134�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������constants ========= .. note:: Mapping of type annotations into concrete types. This is used to normalize Python <= 3.9 annotations. .. automodule:: polyfactory.constants :members: ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/reference/decorators.rst���������������������������������������������0000664�0000000�0000000�00000000114�14721310225�0023253�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������decorators ========== .. automodule:: polyfactory.decorators :members: ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/reference/exceptions.rst���������������������������������������������0000664�0000000�0000000�00000000114�14721310225�0023267�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������exceptions ========== .. automodule:: polyfactory.exceptions :members: ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/reference/factories/�������������������������������������������������0000775�0000000�0000000�00000000000�14721310225�0022337�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/reference/factories/attrs_factory.rst��������������������������������0000664�0000000�0000000�00000000142�14721310225�0025752�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������attrs_factory ================ .. automodule:: polyfactory.factories.attrs_factory :members: ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/reference/factories/base.rst�����������������������������������������0000664�0000000�0000000�00000000106�14721310225�0024000�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������base_factory ============ .. automodule:: polyfactory.factories.base ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/reference/factories/beanie_odm_factory.rst���������������������������0000664�0000000�0000000�00000000156�14721310225�0026704�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������beanie_odm_factory ================== .. automodule:: polyfactory.factories.beanie_odm_factory :members: ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/reference/factories/dataclass_factory.rst����������������������������0000664�0000000�0000000�00000000136�14721310225�0026557�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������dataclass_factory ================== .. automodule:: polyfactory.factories.dataclass_factory ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/reference/factories/index.rst����������������������������������������0000664�0000000�0000000�00000000357�14721310225�0024205�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������factories ========= .. toctree:: :maxdepth: 1 base dataclass_factory typed_dict_factory pydantic_factory msgspec_factory odmantic_odm_factory beanie_odm_factory attrs_factory sqlalchemy_factory ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/reference/factories/msgspec_factory.rst������������������������������0000664�0000000�0000000�00000000146�14721310225�0026262�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������msgspec_factory ================ .. automodule:: polyfactory.factories.msgspec_factory :members: ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/reference/factories/odmantic_odm_factory.rst�������������������������0000664�0000000�0000000�00000000164�14721310225�0027256�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������odmantic_odm_factory ==================== .. automodule:: polyfactory.factories.odmantic_odm_factory :members: ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/reference/factories/pydantic_factory.rst�����������������������������0000664�0000000�0000000�00000000150�14721310225�0026427�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������pydantic_factory ================ .. automodule:: polyfactory.factories.pydantic_factory :members: ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/reference/factories/sqlalchemy_factory.rst���������������������������0000664�0000000�0000000�00000000140�14721310225�0026755�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������sqlalchemy_factory ================== .. automodule:: polyfactory.factories.sqlalchemy_factory ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/reference/factories/typed_dict_factory.rst���������������������������0000664�0000000�0000000�00000000140�14721310225�0026743�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������typed_dict_factory ================== .. automodule:: polyfactory.factories.typed_dict_factory ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/reference/field_meta.rst���������������������������������������������0000664�0000000�0000000�00000000114�14721310225�0023177�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������field_meta ========== .. automodule:: polyfactory.field_meta :members: ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/reference/fields.rst�������������������������������������������������0000664�0000000�0000000�00000000100�14721310225�0022347�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������fields ====== .. automodule:: polyfactory.fields :members: ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/reference/index.rst��������������������������������������������������0000664�0000000�0000000�00000000534�14721310225�0022223�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������API Reference ============= This section contains sections for API reference documentation for the ``polyfactory`` package. .. toctree:: :titlesonly: :maxdepth: 1 :caption: Articles constants exceptions factories/index field_meta fields decorators persistence pytest_plugin value_generators/index ��������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/reference/persistence.rst��������������������������������������������0000664�0000000�0000000�00000000117�14721310225�0023435�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������persistence =========== .. automodule:: polyfactory.persistence :members: �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/reference/pytest_plugin.rst������������������������������������������0000664�0000000�0000000�00000000125�14721310225�0024016�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������pytest_plugin ============= .. automodule:: polyfactory.pytest_plugin :members: �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/reference/value_generators/������������������������������������������0000775�0000000�0000000�00000000000�14721310225�0023725�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/reference/value_generators/complex_types.rst�������������������������0000664�0000000�0000000�00000000146�14721310225�0027353�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������complex_types ============= .. automodule:: polyfactory.value_generators.complex_types :members: ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/reference/value_generators/constrained_collections.rst���������������0000664�0000000�0000000�00000000205�14721310225�0031363�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������constrained_collections ======================== .. automodule:: polyfactory.value_generators.constrained_collections :members: �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/reference/value_generators/constrained_dates.rst���������������������0000664�0000000�0000000�00000000163�14721310225�0030150�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������constrained_dates ================== .. automodule:: polyfactory.value_generators.constrained_dates :members: �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/reference/value_generators/constrained_numbers.rst�������������������0000664�0000000�0000000�00000000170�14721310225�0030521�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������constrained_numbers =================== .. automodule:: polyfactory.value_generators.constrained_numbers :members: ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/reference/value_generators/constrained_strings.rst�������������������0000664�0000000�0000000�00000000170�14721310225�0030537�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������constrained_strings =================== .. automodule:: polyfactory.value_generators.constrained_strings :members: ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/reference/value_generators/index.rst���������������������������������0000664�0000000�0000000�00000000305�14721310225�0025564�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������value_generators ================ .. toctree:: :maxdepth: 1 complex_types constrained_collections constrained_dates constrained_numbers constrained_strings primitives ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/reference/value_generators/primitives.rst����������������������������0000664�0000000�0000000�00000000135�14721310225�0026651�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������primitives ========== .. automodule:: polyfactory.value_generators.primitives :members: �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/releases.rst���������������������������������������������������������0000664�0000000�0000000�00000005504�14721310225�0020763�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������:orphan: ==================== Polyfactory Releases ==================== This document outlines the release structure, versioning, and stability guarantees for the Polyfactory library. Version Numbering ----------------- This library follows the `Semantic Versioning standard <https://semver.org/>`_, using the ``<major>.<minor>.<patch>`` schema: **Major** Backwards incompatible changes have been made **Minor** Functionality was added in a backwards compatible manner **Patch** Bugfixes were applied in a backwards compatible manner Pre-release Versions ++++++++++++++++++++ Before a new major release, we will make ``alpha``, ``beta``, and release candidate (``rc``) releases, numbered as ``<major>.<minor>.<patch><release_type><number>``. For example, ``2.0.0alpha1``, ``2.0.0beta1``, ``2.0.0rc1``. - ``alpha`` Early developer preview. Features may not be complete and breaking changes can occur. - ``beta`` More stable preview release. Feature complete, no major breaking changes expected. - ``rc`` Release candidate. Feature freeze, only bugfixes until final release. Suitable for testing migration to the upcoming major release. Long-term Support Releases (LTS) -------------------------------- Major releases are designated as LTS releases for the life of that major release series. These releases will receive bugfixes for a guaranteed period of time as defined in `Supported Versions <#supported-versions>`_. Deprecation Policy ------------------ When a feature is going to be removed, a deprecation warning will be added in a **minor** release. The feature will continue to work for all releases in that major series, and will be removed in the next major release. For example, if a deprecation warning is added in ``1.1``, the feature will work throughout all ``1.x`` releases, and be removed in ``2.0``. Supported Versions ------------------ At any time, the Litestar organization will actively support: - The current major release series - The previous major release series - Any other designated LTS releases (Special cases) For example, if the current release is ``2.0``, we will actively support ``2.x`` and ``1.x``. When ``3.0`` is released, we will drop support for ``1.x``. Bugfixes will be applied to the current major release, and selectively backported to older supported versions based on severity and feasibility. Release Process --------------- Each major release cycle consists of a few phases: #. **Planning**: Define roadmap, spec out major features. Work should begin on implementation. #. **Development**: Active development on planned features. Ends with an alpha release and branch of ``A.B.x`` branch from `main`. #. **Bugfixes**: Only bugfixes, no new features. Progressively release beta, release candidates. Feature freeze at RC. Become more selective with backports to avoid regressions. ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/usage/���������������������������������������������������������������0000775�0000000�0000000�00000000000�14721310225�0017526�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/usage/configuration.rst����������������������������������������������0000664�0000000�0000000�00000012554�14721310225�0023136�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������Factory Configuration ===================== Factories can be configured by setting special dunder (double underscore) class attributes. You can read the reference for these in the API reference for :class:`BaseFactory <polyfactory.factories.base.BaseFactory>`. Below we discuss some configuration options in some depth. Seeding Randomness ------------------ .. literalinclude:: /examples/configuration/test_example_1.py :caption: Seeding the factory's 'random.Random' :language: python Seeding randomness allows you to control the random generation of values produced by the factory. This affects all :class:`random.Random` methods as well as faker. Setting Random -------------- .. literalinclude:: /examples/configuration/test_example_2.py :caption: Setting the factory's 'random.Random' :language: python This configuration option is functionally identical to the previous, with the difference being that here we are setting the actual instance of :class:`random.Random`. This is useful when embedding factories inside more complex logic, such as in other libraries, as well as when factories are being dynamically generated. Setting Faker ------------- .. literalinclude:: /examples/configuration/test_example_3.py :caption: Setting the factory's 'Faker' :language: python In the above example we are setting the factory's instance of ``Faker`` and configure its locale to Spanish. Because we are also setting the random seed value, the results of the test are deterministic. .. note:: To understand why we are using a classmethod here, see the documentation about :doc:`factory fields </usage/fields>`. Persistence Handlers -------------------- Factory classes have four optional persistence methods: - ``.create_sync(**kwargs)`` - builds and persists a single instance of the factory's model synchronously - ``.create_batch_sync(size: int, **kwargs)`` - builds and persists a list of size n instances synchronously - ``.create_async(**kwargs)`` - builds and persists a single instance of the factory's model asynchronously - ``.create_batch_async(size: int, **kwargs)`` - builds and persists a list of size n instances asynchronously To use these methods, you must first specify a sync and/or async persistence handlers for the factory: .. literalinclude:: /examples/configuration/test_example_4.py :caption: Defining and using persistence handlers. :language: python With the persistence handlers in place, you can now use all persistence methods. .. note:: You do not need to define both persistence handlers. If you will only use sync or async persistence, you only need to define the respective handler to use these methods. Defining Default Factories -------------------------- As explained in the section about dynamic factory generation in :doc:`declaring factories </usage/declaring_factories>`, factories generate new factories for supported types dynamically. This process requires no intervention from the user. Once a factory is generated, it is then cached and reused - when the same type is used. For example, when build is called for the ``PersonFactory`` below, a ``PetFactory`` will be dynamically generated and reused: .. literalinclude:: /examples/declaring_factories/test_example_5.py :caption: Dynamic factory generation :language: python You can also control the default factory for a type by declaring a factory as the type default: .. literalinclude:: /examples/configuration/test_example_5.py :caption: Setting a factory as a type default. :language: python Randomized Collection Length ---------------------------- Set of fields that allow you to generate a collection with random lengths. By default only one item is generated. .. literalinclude:: /examples/configuration/test_example_6.py :caption: Randomized collection length :language: python Allow None Optionals -------------------- Allow `None` to be generated as a value for types marked as optional. When set to `True`, the outputted value will be randomly chosen between `None` and other allowed types. By default, this is set to `True`. By setting to `False`, then optional types will always be treated as the wrapped type: .. literalinclude:: /examples/configuration/test_example_7.py :caption: Disable Allow None Optionals :language: python Check Factory Fields -------------------- When `__check_model__` is set to `True`, declaring fields on the factory that don't exist on the model will trigger an exception. This is only true when fields are declared with ``Use``, ``PostGenerated``, ``Ignore`` and ``Require``. Any other field definition will not be checked. .. literalinclude:: /examples/configuration/test_example_8.py :caption: Enable Check Factory Fields :language: python Use Default Values ------------------ If ``__use_defaults__`` is set to ``True``, then the default value will be used instead of creating a random value for a given field, provided there's a default value for that field. By default, ``__use_defaults__`` is set to ``False.`` If you need more fine grained control, you can override the :meth:`~polyfactory.factories.base.BaseFactory.should_use_default_value` classmethod. .. note:: Setting ``__use_defaults__`` has no effect for ``TypedDictFactory`` since you cannot set default values for ``TypedDict``. .. literalinclude:: /examples/configuration/test_example_9.py :caption: Use Default Values :language: python ����������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/usage/declaring_factories.rst����������������������������������������0000664�0000000�0000000�00000005725�14721310225�0024260�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������Declaring Factories =================== Defining factories is done using a declarative syntax. That is - users declare factory classes, which are subclasses of base factories. .. literalinclude:: /examples/declaring_factories/test_example_1.py :caption: Declaring a factory for a dataclass :language: python You can also specify the model type by only specifying the factory generic type parameter. .. code-block:: python @dataclass class Person: name: str age: float height: float weight: float class PersonFactory(DataclassFactory[Person]): ... .. note:: The syntax with the ``__model__`` class attribute omitting is only available since version 2.13.0. The same applies to the other factories exported by this library, for example: .. literalinclude:: /examples/declaring_factories/test_example_2.py :caption: Declaring a factory for a typed-dict :language: python Or for pydantic models: .. literalinclude:: /examples/declaring_factories/test_example_3.py :caption: Declaring a factory for a pydantic model :language: python .. note:: You can also define factories for any 3rd party implementation of dataclasses, as long as it fulfills the stdlib dataclasses interface. For example, this is using the pydantic ``@dataclass`` decorator: .. literalinclude:: /examples/declaring_factories/test_example_4.py :caption: Declaring a factory for a pydantic dataclass :language: python Or for attrs models: .. literalinclude:: /examples/declaring_factories/test_example_7.py :caption: Declaring a factory for a attrs model :language: python .. note:: Validators are not currently supported - neither the built in validators that come with `attrs` nor custom validators. Imperative Factory Creation --------------------------- Although the definition of factories is primarily meant to be done declaratively, factories expose the :meth:`create_factory <polyfactory.factories.base.BaseFactory.create_factory>` method. This method is used internally inside factories to dynamically create factories for models. For example, below the ``PersonFactory`` will dynamically create a ``PetFactory``: .. literalinclude:: /examples/declaring_factories/test_example_5.py :caption: Dynamic factory generation :language: python You can also use this method to create factories imperatively: .. literalinclude:: /examples/declaring_factories/test_example_6.py :caption: Imperative factory creation :language: python Eventually you can use this method on an existing concrete factory to create a sub factory overriding some parent configuration: .. literalinclude:: /examples/declaring_factories/test_example_8.py :caption: Imperative sub factory creation :language: python In this case you don't need to specify the `model` argument to the :meth:`create_factory <polyfactory.factories.base.BaseFactory.create_factory>` method. The one from the parent factory will be used. �������������������������������������������python-polyfactory-2.18.1/docs/usage/decorators.rst�������������������������������������������������0000664�0000000�0000000�00000001171�14721310225�0022425�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������The ``post_generated`` decorator -------------------------------- The :class:`post_generated <polyfactory.decorators.post_generated>` decorator wraps a ``classmethod`` into a :class:`PostGenerated <polyfactory.fields.PostGenerated>` field. This is useful when the post generated field depends on the current factory, usually its ``__faker__`` and/or ``__random__`` attribute. For example: .. literalinclude:: /examples/decorators/test_example_1.py :caption: Using the ``post_generated`` decorator :language: python All classmethod parameters after ``cls`` must be named as the fields this post generated field depends on. �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/usage/fields.rst�����������������������������������������������������0000664�0000000�0000000�00000010041�14721310225�0021522�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������Factory Fields ============== The factory api is designed to be as semantic and simple as possible, and by default it requires no customization to mock data. Nonetheless, when you do need to customize and control the data being generated, polyfactory has you covered. Lets look at a few examples: .. literalinclude:: /examples/fields/test_example_1.py :caption: Declaring a PersonFactory with hardcoded pets :language: python In the example above, the call to ``PersonFactory.build()`` results in a ``Person`` where all values are randomly generated, except the ``pets`` list, which will be the hardcoded value we defined. The ``Use`` Field ----------------- This though is often not desirable. We could instead, define a factory for Pet where we restrict the choices to a range we like. For example: .. literalinclude:: /examples/fields/test_example_2.py :caption: Using the ``Use`` field with a custom PetFactory to control the generation of a Person's pets list :language: python The :class:`Use <polyfactory.fields.Use>` class is merely a semantic abstraction that makes the factory cleaner and simpler to understand, you can in fact use any callable (including classes) as values for a factory's attribute directly, and these will be invoked at build-time. Thus, you could for example re-write the above PetFactory like so: .. literalinclude:: /examples/fields/test_example_3.py :caption: Using simple lambda functions to declare custom fields :language: python Or you can use a class method, which will give you easy and nice access to the factory itself: .. literalinclude:: /examples/fields/test_example_4.py :caption: Using class methods to declare custom fields :language: python .. note:: All the above examples used ``DataclassFactory.__random__.choice``, and this is intentional. While you can use ``random.choice`` or any other function exported from the stdlib random library, the factory class has its own instance of ``random.Random`` attached under ``cls.__random__``. This instance can be affected by random seeding in several ways, e.g. calling the factory seeding method, which will be scoped only to this instance. Thus, for consistent results when seeding randomness, its important to use the factory ``random.Random`` instance rather than the global one from the stdlib. The ``Ignore`` Field -------------------- :class:`Ignore <polyfactory.fields.Ignore>` is used to designate an attribute as ignored, which means it will be completely ignored by the factory: .. literalinclude:: /examples/fields/test_example_5.py :caption: Using the ``Ignore`` field :language: python The ``Require`` Field --------------------- The :class:`Require <polyfactory.fields.Require>` class is used to designate a given attribute as a required kwarg. This means that the factory will require passing a value for this attribute as a kwarg to the build method, or an exception will be raised: .. literalinclude:: /examples/fields/test_example_6.py :caption: Using the ``Require`` field :language: python The ``PostGenerated`` Field --------------------------- The :class:`PostGenerated <polyfactory.fields.PostGenerated>` class allows for post generating fields based on already generated values of other (non post generated) fields. In most cases this pattern is best avoided, but for the few valid cases the PostGenerated helper is provided. For example: .. literalinclude:: /examples/fields/test_example_7.py :caption: Using the ``PostGenerated`` field :language: python The signature for use is: ``cb: Callable, *args, **defaults`` it can receive any sync callable. The signature for the callable should be: ``name: str, values: dict[str, Any], *args, **defaults``. The already generated values are mapped by name in the values dictionary. Factories as Fields --------------------------- Factories themselves can be used as fields. In this usage, build parameters will be passed to the declared factory. .. literalinclude:: /examples/fields/test_example_8.py :caption: Using a factory as a field :language: python �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/usage/fixtures.rst���������������������������������������������������0000664�0000000�0000000�00000002655�14721310225�0022141�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������Pytest fixtures =============== Polyfactory support registering factories as pytest fixtures using the :func:`register_fixture <polyfactory.pytest_plugin.register_fixture>` decorator: .. literalinclude:: /examples/fixtures/test_example_1.py :caption: Using the ``register_fixture_decorator`` field. :language: python In the above example the ``PersonFactory`` is wrapped as a pytest fixture. As a result it cannot be used as a normal factory,because pytest fixtures are callables that must be called by pytest. To overcome this restriction, you can declare the fixture separately from the declaration of the class: .. literalinclude:: /examples/fixtures/test_example_2.py :caption: Using the ``register_fixture_decorator`` field without wrapping the factory class. :language: python You can also control the name of the fixture using the optional ``name`` kwarg: .. literalinclude:: /examples/fixtures/test_example_3.py :caption: Aliasing a factory fixture using the `name` kwarg. :language: python The ``Fixture`` Field --------------------- You can also use factory fixtures as factory fields using the :class:`Fixture <polyfactory.pytest_plugin.FactoryFixture>`: .. literalinclude:: /examples/fixtures/test_example_4.py :caption: Using the ``Fixture`` field. :language: python ``Fixture`` is similar to ``Use`` in that it accepts kwargs that are propagated the to the build or batch methods of the factory. �����������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/usage/handling_custom_types.rst��������������������������������������0000664�0000000�0000000�00000002437�14721310225�0024670�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������Handling Custom Types ===================== Sometimes you need to handle custom types, either from 3rd party libraries or from your own codebase. To achieve this, you can extend what's referred as the `providers_map`: .. literalinclude:: /examples/handling_custom_types/test_example_1.py :caption: Extending the provider map :language: python In the above example we override the `get_provider_map` class method, which maps types to callables. Each callable in the map returns an appropriate mock value for the type. In the above example, an instance of `CustomSecret` with the hardcoded string 'jeronimo'. Creating Custom Base Factories ------------------------------ The above works great when you need to do this in a localised fashion, but if you need to use some custom types in many places it will lead to unnecessary duplication. The solution for this is to create a custom base factory, in this case for handling dataclasses: .. literalinclude:: /examples/handling_custom_types/test_example_2.py :caption: Creating a custom dataclass factory with extended provider map :language: python .. note:: If extra configs values are defined for custom base classes, then ``__config_keys__`` should be extended so that these values are correctly passed onto to concrete factories. ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/usage/index.rst������������������������������������������������������0000664�0000000�0000000�00000000477�14721310225�0021377�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������Usage Guide =========== This section contains articles that explain how to use Polyfactory. .. toctree:: :titlesonly: :maxdepth: 1 :caption: Articles declaring_factories library_factories/index configuration fields decorators fixtures handling_custom_types model_coverage �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/usage/library_factories/���������������������������������������������0000775�0000000�0000000�00000000000�14721310225�0023231�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/usage/library_factories/index.rst������������������������������������0000664�0000000�0000000�00000004044�14721310225�0025074�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������Polyfactory Factories ===================== The factories exported by this library are classes that extend the Abstract Base Class (ABC) :class:`BaseFactory <polyfactory.factories.base.BaseFactory>`. These include: :class:`DataclassFactory <polyfactory.factories.dataclass_factory.DataclassFactory>` a base factory for dataclasses :class:`TypedDictFactory <polyfactory.factories.typed_dict_factory.TypedDictFactory>` a base factory for typed-dicts :class:`ModelFactory <polyfactory.factories.pydantic_factory.ModelFactory>` a base factory for `pydantic <https://docs.pydantic.dev/>`_ models :class:`BeanieDocumentFactory <polyfactory.factories.beanie_odm_factory.BeanieDocumentFactory>` a base factory for `beanie <https://beanie-odm.dev/>`_ documents :class:`OdmanticModelFactory <polyfactory.factories.odmantic_odm_factory.OdmanticModelFactory>` a base factory for `odmantic <https://art049.github.io/odmantic/>`_ models. :class:`MsgspecFactory <polyfactory.factories.msgspec_factory.MsgspecFactory>` a base factory for `msgspec <https://jcristharif.com/msgspec/>`_ Structs :class:`AttrsFactory <polyfactory.factories.attrs_factory.AttrsFactory>` a base factory for `attrs <https://www.attrs.org/en/stable/index.html>`_ models. :class:`SQLAlchemyFactory <polyfactory.factories.sqlalchemy_factory.SQLAlchemyFactory>` a base factory for `SQLAlchemy <https://www.sqlalchemy.org/>`_ models. .. note:: All factories exported from ``polyfactory.factories`` do not require any additional dependencies. The other factories, such as :class:`ModelFactory <polyfactory.factories.pydantic_factory.ModelFactory>`, require an additional but optional dependency, in this case `pydantic <https://docs.pydantic.dev/>`_. As such, they are exported only from their respective namespaced module, e.g. ``polyfactory.factories.pydantic_factory.ModelFactory``. .. note:: We will be adding additional factories to this package, so make sure to checkout the above list from time to time. .. toctree:: :maxdepth: 1 sqlalchemy_factory ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/usage/library_factories/sqlalchemy_factory.rst�����������������������0000664�0000000�0000000�00000003464�14721310225�0027663�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������SQLAlchemyFactory =================== Basic usage is like other factories .. literalinclude:: /examples/library_factories/sqlalchemy_factory/test_example_1.py :caption: Declaring a factory for a SQLAlchemy model :language: python .. note:: The examples here require SQLAlchemy 2 to be installed. The factory itself supports both 1.4 and 2. Configuration ------------------------------ By default, relationships will not be set. This can be overridden via ``__set_relationships__``. .. literalinclude:: /examples/library_factories/sqlalchemy_factory/test_example_2.py :caption: Setting relationships :language: python .. note:: In general, foreign keys are not automatically generated by ``.build``. This can be resolved by setting the fields yourself and/or using ``create_sync``/ ``create_async`` so models can be added to a SQLA session so these are set. Persistence ------------------------------ A handler is provided to allow persistence. This can be used by setting ``__session__`` attribute on a factory. .. literalinclude:: /examples/library_factories/sqlalchemy_factory/test_example_3.py :caption: Using persistence :language: python By default, this will add generated models to the session and then commit. This can be customised further by setting ``__sync_persistence__``. Similarly for ``__async_session__`` and ``create_async``. Adding global overrides ------------------------------ By combining the above and using other settings, a global base factory can be set up for other factories. .. literalinclude:: /examples/library_factories/sqlalchemy_factory/test_example_4.py :caption: Using persistence :language: python API reference ------------------------------ Full API docs are available :class:`here <polyfactory.factories.sqlalchemy_factory.SQLAlchemyFactory>`. ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/docs/usage/model_coverage.rst���������������������������������������������0000664�0000000�0000000�00000003265�14721310225�0023241�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������Model coverage generation ========================= The ``BaseFactory.coverage()`` function is an alternative approach to ``BaseFactory.batch()``, where the examples that are generated attempt to provide full coverage of all the forms a model can take with the minimum number of instances. For example: .. literalinclude:: /examples/model_coverage/test_example_1.py :caption: Defining a factory and generating examples with coverage :language: python As you can see in the above example, the ``Profile`` model has 3 options for ``favourite_color``, and 2 options for ``vehicle``. In the output you can expect to see instances of ``Profile`` that have each of these options. The largest variance dictates the length of the output, in this case ``favourite_color`` has the most, at 3 options, so expect to see 3 ``Profile`` instances. .. note:: Notice that the same ``Car`` instance is used in the first and final generated example. When the coverage examples for a field are exhausted before another field, values for that field are re-used. Notes on collection types ------------------------- When generating coverage for models with fields that are collections, in particular collections that contain sub-models, the contents of the collection will be the all coverage examples for that sub-model. For example: .. literalinclude:: /examples/model_coverage/test_example_2.py :caption: Coverage output for the SocialGroup model :language: python Known Limitations ----------------- - Recursive models will cause an error: ``RecursionError: maximum recursion depth exceeded``. - ``__min_collection_length__`` and ``__max_collection_length__`` are currently ignored in coverage generation. �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/pdm.lock������������������������������������������������������������������0000664�0000000�0000000�00000516557�14721310225�0017147�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# This file is @generated by PDM. # It is not intended for manual editing. [metadata] groups = ["default", "attrs", "beanie", "dev", "docs", "full", "lint", "msgspec", "odmantic", "pydantic", "sqlalchemy", "test"] strategy = ["cross_platform"] lock_version = "4.5.0" content_hash = "sha256:54bd033197dd25efe127f05772bce9f32c8a3f875f9b763d9d9b41d1da0376f8" [[metadata.targets]] requires_python = "~=3.8" [[package]] name = "aiosqlite" version = "0.20.0" requires_python = ">=3.8" summary = "asyncio bridge to the standard sqlite3 module" dependencies = [ "typing-extensions>=4.0", ] files = [ {file = "aiosqlite-0.20.0-py3-none-any.whl", hash = "sha256:36a1deaca0cac40ebe32aac9977a6e2bbc7f5189f23f4a54d5908986729e5bd6"}, {file = "aiosqlite-0.20.0.tar.gz", hash = "sha256:6d35c8c256637f4672f843c31021464090805bf925385ac39473fb16eaaca3d7"}, ] [[package]] name = "alabaster" version = "0.7.13" requires_python = ">=3.6" summary = "A configurable sidebar-enabled Sphinx theme" files = [ {file = "alabaster-0.7.13-py3-none-any.whl", hash = "sha256:1ee19aca801bbabb5ba3f5f258e4422dfa86f82f3e9cefb0859b283cdd7f62a3"}, {file = "alabaster-0.7.13.tar.gz", hash = "sha256:a27a4a084d5e690e16e01e03ad2b2e552c61a65469419b907243193de1a84ae2"}, ] [[package]] name = "annotated-types" version = "0.7.0" requires_python = ">=3.8" summary = "Reusable constraint types to use with typing.Annotated" dependencies = [ "typing-extensions>=4.0.0; python_version < \"3.9\"", ] files = [ {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"}, {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, ] [[package]] name = "apeye" version = "1.4.1" requires_python = ">=3.6.1" summary = "Handy tools for working with URLs and APIs." dependencies = [ "apeye-core>=1.0.0b2", "domdf-python-tools>=2.6.0", "platformdirs>=2.3.0", "requests>=2.24.0", ] files = [ {file = "apeye-1.4.1-py3-none-any.whl", hash = "sha256:44e58a9104ec189bf42e76b3a7fe91e2b2879d96d48e9a77e5e32ff699c9204e"}, {file = "apeye-1.4.1.tar.gz", hash = "sha256:14ea542fad689e3bfdbda2189a354a4908e90aee4bf84c15ab75d68453d76a36"}, ] [[package]] name = "apeye-core" version = "1.1.5" requires_python = ">=3.6.1" summary = "Core (offline) functionality for the apeye library." dependencies = [ "domdf-python-tools>=2.6.0", "idna>=2.5", ] files = [ {file = "apeye_core-1.1.5-py3-none-any.whl", hash = "sha256:dc27a93f8c9e246b3b238c5ea51edf6115ab2618ef029b9f2d9a190ec8228fbf"}, {file = "apeye_core-1.1.5.tar.gz", hash = "sha256:5de72ed3d00cc9b20fea55e54b7ab8f5ef8500eb33a5368bc162a5585e238a55"}, ] [[package]] name = "attrs" version = "23.2.0" requires_python = ">=3.7" summary = "Classes Without Boilerplate" dependencies = [ "importlib-metadata; python_version < \"3.8\"", ] files = [ {file = "attrs-23.2.0-py3-none-any.whl", hash = "sha256:99b87a485a5820b23b879f04c2305b44b951b502fd64be915879d77a7e8fc6f1"}, {file = "attrs-23.2.0.tar.gz", hash = "sha256:935dc3b529c262f6cf76e50877d35a4bd3c1de194fd41f47a2b7ae8f19971f30"}, ] [[package]] name = "auto-pytabs" version = "0.4.0" requires_python = ">=3.8,<4.0" summary = "Automatically generate code examples for different Python versions in mkdocs or Sphinx based documentations" dependencies = [ "ruff>=0.0.260", ] files = [ {file = "auto_pytabs-0.4.0-py3-none-any.whl", hash = "sha256:941ca4f21b218249ee4d026ebaf4a8a7788a066fdb223571f1f7b93d44ac6a74"}, {file = "auto_pytabs-0.4.0.tar.gz", hash = "sha256:4c596aa02ea20c6c85809e5f60a22aa60499dcaa637e52d6313d07c58c5bb61e"}, ] [[package]] name = "autodocsumm" version = "0.2.12" requires_python = ">=3.7" summary = "Extended sphinx autodoc including automatic autosummaries" dependencies = [ "Sphinx<8.0,>=2.2", ] files = [ {file = "autodocsumm-0.2.12-py3-none-any.whl", hash = "sha256:b842b53c686c07a4f174721ca4e729b027367703dbf42e2508863a3c6d6c049c"}, {file = "autodocsumm-0.2.12.tar.gz", hash = "sha256:848fe8c38df433c6635489499b969cb47cc389ed3d7b6e75c8ccbc94d4b3bf9e"}, ] [[package]] name = "babel" version = "2.14.0" requires_python = ">=3.7" summary = "Internationalization utilities" dependencies = [ "pytz>=2015.7; python_version < \"3.9\"", ] files = [ {file = "Babel-2.14.0-py3-none-any.whl", hash = "sha256:efb1a25b7118e67ce3a259bed20545c29cb68be8ad2c784c83689981b7a57287"}, {file = "Babel-2.14.0.tar.gz", hash = "sha256:6919867db036398ba21eb5c7a0f6b28ab8cbc3ae7a73a44ebe34ae74a4e7d363"}, ] [[package]] name = "beanie" version = "1.26.0" requires_python = "<4.0,>=3.7" summary = "Asynchronous Python ODM for MongoDB" dependencies = [ "click>=7", "lazy-model==0.2.0", "motor<4.0.0,>=2.5.0", "pydantic<3.0,>=1.10", "toml", "typing-extensions>=4.7; python_version < \"3.11\"", ] files = [ {file = "beanie-1.26.0-py3-none-any.whl", hash = "sha256:b45926c01d4a899c519c665c2a5f230990717e99f7fd68172a389ca33e7693b9"}, {file = "beanie-1.26.0.tar.gz", hash = "sha256:54016f4ec71ed0ea6ce0c7946a395090c45687f254dbbe1cf06eec608383f790"}, ] [[package]] name = "beautifulsoup4" version = "4.12.3" requires_python = ">=3.6.0" summary = "Screen-scraping library" dependencies = [ "soupsieve>1.2", ] files = [ {file = "beautifulsoup4-4.12.3-py3-none-any.whl", hash = "sha256:b80878c9f40111313e55da8ba20bdba06d8fa3969fc68304167741bbf9e082ed"}, {file = "beautifulsoup4-4.12.3.tar.gz", hash = "sha256:74e3d1928edc070d21748185c46e3fb33490f22f52a3addee9aee0f4f7781051"}, ] [[package]] name = "black" version = "24.4.2" requires_python = ">=3.8" summary = "The uncompromising code formatter." dependencies = [ "click>=8.0.0", "mypy-extensions>=0.4.3", "packaging>=22.0", "pathspec>=0.9.0", "platformdirs>=2", "tomli>=1.1.0; python_version < \"3.11\"", "typing-extensions>=4.0.1; python_version < \"3.11\"", ] files = [ {file = "black-24.4.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:dd1b5a14e417189db4c7b64a6540f31730713d173f0b63e55fabd52d61d8fdce"}, {file = "black-24.4.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8e537d281831ad0e71007dcdcbe50a71470b978c453fa41ce77186bbe0ed6021"}, {file = "black-24.4.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eaea3008c281f1038edb473c1aa8ed8143a5535ff18f978a318f10302b254063"}, {file = "black-24.4.2-cp310-cp310-win_amd64.whl", hash = "sha256:7768a0dbf16a39aa5e9a3ded568bb545c8c2727396d063bbaf847df05b08cd96"}, {file = "black-24.4.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:257d724c2c9b1660f353b36c802ccece186a30accc7742c176d29c146df6e474"}, {file = "black-24.4.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:bdde6f877a18f24844e381d45e9947a49e97933573ac9d4345399be37621e26c"}, {file = "black-24.4.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e151054aa00bad1f4e1f04919542885f89f5f7d086b8a59e5000e6c616896ffb"}, {file = "black-24.4.2-cp311-cp311-win_amd64.whl", hash = "sha256:7e122b1c4fb252fd85df3ca93578732b4749d9be076593076ef4d07a0233c3e1"}, {file = "black-24.4.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:accf49e151c8ed2c0cdc528691838afd217c50412534e876a19270fea1e28e2d"}, {file = "black-24.4.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:88c57dc656038f1ab9f92b3eb5335ee9b021412feaa46330d5eba4e51fe49b04"}, {file = "black-24.4.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:be8bef99eb46d5021bf053114442914baeb3649a89dc5f3a555c88737e5e98fc"}, {file = "black-24.4.2-cp312-cp312-win_amd64.whl", hash = "sha256:415e686e87dbbe6f4cd5ef0fbf764af7b89f9057b97c908742b6008cc554b9c0"}, {file = "black-24.4.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:bf10f7310db693bb62692609b397e8d67257c55f949abde4c67f9cc574492cc7"}, {file = "black-24.4.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:98e123f1d5cfd42f886624d84464f7756f60ff6eab89ae845210631714f6db94"}, {file = "black-24.4.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:48a85f2cb5e6799a9ef05347b476cce6c182d6c71ee36925a6c194d074336ef8"}, {file = "black-24.4.2-cp38-cp38-win_amd64.whl", hash = "sha256:b1530ae42e9d6d5b670a34db49a94115a64596bc77710b1d05e9801e62ca0a7c"}, {file = "black-24.4.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:37aae07b029fa0174d39daf02748b379399b909652a806e5708199bd93899da1"}, {file = "black-24.4.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:da33a1a5e49c4122ccdfd56cd021ff1ebc4a1ec4e2d01594fef9b6f267a9e741"}, {file = "black-24.4.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ef703f83fc32e131e9bcc0a5094cfe85599e7109f896fe8bc96cc402f3eb4b6e"}, {file = "black-24.4.2-cp39-cp39-win_amd64.whl", hash = "sha256:b9176b9832e84308818a99a561e90aa479e73c523b3f77afd07913380ae2eab7"}, {file = "black-24.4.2-py3-none-any.whl", hash = "sha256:d36ed1124bb81b32f8614555b34cc4259c3fbc7eec17870e8ff8ded335b58d8c"}, {file = "black-24.4.2.tar.gz", hash = "sha256:c872b53057f000085da66a19c55d68f6f8ddcac2642392ad3a355878406fbd4d"}, ] [[package]] name = "blacken-docs" version = "1.16.0" requires_python = ">=3.8" summary = "Run Black on Python code blocks in documentation files." dependencies = [ "black>=22.1.0", ] files = [ {file = "blacken_docs-1.16.0-py3-none-any.whl", hash = "sha256:b0dcb84b28ebfb352a2539202d396f50e15a54211e204a8005798f1d1edb7df8"}, {file = "blacken_docs-1.16.0.tar.gz", hash = "sha256:b4bdc3f3d73898dfbf0166f292c6ccfe343e65fc22ddef5319c95d1a8dcc6c1c"}, ] [[package]] name = "cachecontrol" version = "0.14.0" requires_python = ">=3.7" summary = "httplib2 caching for requests" dependencies = [ "msgpack<2.0.0,>=0.5.2", "requests>=2.16.0", ] files = [ {file = "cachecontrol-0.14.0-py3-none-any.whl", hash = "sha256:f5bf3f0620c38db2e5122c0726bdebb0d16869de966ea6a2befe92470b740ea0"}, {file = "cachecontrol-0.14.0.tar.gz", hash = "sha256:7db1195b41c81f8274a7bbd97c956f44e8348265a1bc7641c37dfebc39f0c938"}, ] [[package]] name = "cachecontrol" version = "0.14.0" extras = ["filecache"] requires_python = ">=3.7" summary = "httplib2 caching for requests" dependencies = [ "cachecontrol==0.14.0", "filelock>=3.8.0", ] files = [ {file = "cachecontrol-0.14.0-py3-none-any.whl", hash = "sha256:f5bf3f0620c38db2e5122c0726bdebb0d16869de966ea6a2befe92470b740ea0"}, {file = "cachecontrol-0.14.0.tar.gz", hash = "sha256:7db1195b41c81f8274a7bbd97c956f44e8348265a1bc7641c37dfebc39f0c938"}, ] [[package]] name = "certifi" version = "2024.2.2" requires_python = ">=3.6" summary = "Python package for providing Mozilla's CA Bundle." files = [ {file = "certifi-2024.2.2-py3-none-any.whl", hash = "sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1"}, {file = "certifi-2024.2.2.tar.gz", hash = "sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f"}, ] [[package]] name = "cfgv" version = "3.4.0" requires_python = ">=3.8" summary = "Validate configuration and produce human readable error messages." files = [ {file = "cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9"}, {file = "cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560"}, ] [[package]] name = "charset-normalizer" version = "3.3.2" requires_python = ">=3.7.0" summary = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." files = [ {file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"}, {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3"}, {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027"}, {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03"}, {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d"}, {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e"}, {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6"}, {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5"}, {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537"}, {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c"}, {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12"}, {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f"}, {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269"}, {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519"}, {file = "charset_normalizer-3.3.2-cp310-cp310-win32.whl", hash = "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73"}, {file = "charset_normalizer-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09"}, {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db"}, {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96"}, {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e"}, {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f"}, {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574"}, {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4"}, {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8"}, {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc"}, {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae"}, {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887"}, {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae"}, {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce"}, {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f"}, {file = "charset_normalizer-3.3.2-cp311-cp311-win32.whl", hash = "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab"}, {file = "charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77"}, {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8"}, {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b"}, {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6"}, {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a"}, {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389"}, {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa"}, {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b"}, {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed"}, {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26"}, {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d"}, {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068"}, {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143"}, {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4"}, {file = "charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7"}, {file = "charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001"}, {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a"}, {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac"}, {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a"}, {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33"}, {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238"}, {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a"}, {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2"}, {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8"}, {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898"}, {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99"}, {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d"}, {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04"}, {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087"}, {file = "charset_normalizer-3.3.2-cp38-cp38-win32.whl", hash = "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25"}, {file = "charset_normalizer-3.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b"}, {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4"}, {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d"}, {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0"}, {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269"}, {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c"}, {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519"}, {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796"}, {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185"}, {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c"}, {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458"}, {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2"}, {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8"}, {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"}, {file = "charset_normalizer-3.3.2-cp39-cp39-win32.whl", hash = "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f"}, {file = "charset_normalizer-3.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d"}, {file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"}, ] [[package]] name = "click" version = "8.1.7" requires_python = ">=3.7" summary = "Composable command line interface toolkit" dependencies = [ "colorama; platform_system == \"Windows\"", "importlib-metadata; python_version < \"3.8\"", ] files = [ {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"}, {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"}, ] [[package]] name = "codespell" version = "2.3.0" requires_python = ">=3.8" summary = "Codespell" files = [ {file = "codespell-2.3.0-py3-none-any.whl", hash = "sha256:a9c7cef2501c9cfede2110fd6d4e5e62296920efe9abfb84648df866e47f58d1"}, {file = "codespell-2.3.0.tar.gz", hash = "sha256:360c7d10f75e65f67bad720af7007e1060a5d395670ec11a7ed1fed9dd17471f"}, ] [[package]] name = "colorama" version = "0.4.6" requires_python = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" summary = "Cross-platform colored terminal text." files = [ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] [[package]] name = "coverage" version = "7.5.0" requires_python = ">=3.8" summary = "Code coverage measurement for Python" files = [ {file = "coverage-7.5.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:432949a32c3e3f820af808db1833d6d1631664d53dd3ce487aa25d574e18ad1c"}, {file = "coverage-7.5.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2bd7065249703cbeb6d4ce679c734bef0ee69baa7bff9724361ada04a15b7e3b"}, {file = "coverage-7.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bbfe6389c5522b99768a93d89aca52ef92310a96b99782973b9d11e80511f932"}, {file = "coverage-7.5.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:39793731182c4be939b4be0cdecde074b833f6171313cf53481f869937129ed3"}, {file = "coverage-7.5.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85a5dbe1ba1bf38d6c63b6d2c42132d45cbee6d9f0c51b52c59aa4afba057517"}, {file = "coverage-7.5.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:357754dcdfd811462a725e7501a9b4556388e8ecf66e79df6f4b988fa3d0b39a"}, {file = "coverage-7.5.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:a81eb64feded34f40c8986869a2f764f0fe2db58c0530d3a4afbcde50f314880"}, {file = "coverage-7.5.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:51431d0abbed3a868e967f8257c5faf283d41ec882f58413cf295a389bb22e58"}, {file = "coverage-7.5.0-cp310-cp310-win32.whl", hash = "sha256:f609ebcb0242d84b7adeee2b06c11a2ddaec5464d21888b2c8255f5fd6a98ae4"}, {file = "coverage-7.5.0-cp310-cp310-win_amd64.whl", hash = "sha256:6782cd6216fab5a83216cc39f13ebe30adfac2fa72688c5a4d8d180cd52e8f6a"}, {file = "coverage-7.5.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e768d870801f68c74c2b669fc909839660180c366501d4cc4b87efd6b0eee375"}, {file = "coverage-7.5.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:84921b10aeb2dd453247fd10de22907984eaf80901b578a5cf0bb1e279a587cb"}, {file = "coverage-7.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:710c62b6e35a9a766b99b15cdc56d5aeda0914edae8bb467e9c355f75d14ee95"}, {file = "coverage-7.5.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c379cdd3efc0658e652a14112d51a7668f6bfca7445c5a10dee7eabecabba19d"}, {file = "coverage-7.5.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fea9d3ca80bcf17edb2c08a4704259dadac196fe5e9274067e7a20511fad1743"}, {file = "coverage-7.5.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:41327143c5b1d715f5f98a397608f90ab9ebba606ae4e6f3389c2145410c52b1"}, {file = "coverage-7.5.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:565b2e82d0968c977e0b0f7cbf25fd06d78d4856289abc79694c8edcce6eb2de"}, {file = "coverage-7.5.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cf3539007202ebfe03923128fedfdd245db5860a36810136ad95a564a2fdffff"}, {file = "coverage-7.5.0-cp311-cp311-win32.whl", hash = "sha256:bf0b4b8d9caa8d64df838e0f8dcf68fb570c5733b726d1494b87f3da85db3a2d"}, {file = "coverage-7.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:9c6384cc90e37cfb60435bbbe0488444e54b98700f727f16f64d8bfda0b84656"}, {file = "coverage-7.5.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:fed7a72d54bd52f4aeb6c6e951f363903bd7d70bc1cad64dd1f087980d309ab9"}, {file = "coverage-7.5.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:cbe6581fcff7c8e262eb574244f81f5faaea539e712a058e6707a9d272fe5b64"}, {file = "coverage-7.5.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ad97ec0da94b378e593ef532b980c15e377df9b9608c7c6da3506953182398af"}, {file = "coverage-7.5.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bd4bacd62aa2f1a1627352fe68885d6ee694bdaebb16038b6e680f2924a9b2cc"}, {file = "coverage-7.5.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:adf032b6c105881f9d77fa17d9eebe0ad1f9bfb2ad25777811f97c5362aa07f2"}, {file = "coverage-7.5.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:4ba01d9ba112b55bfa4b24808ec431197bb34f09f66f7cb4fd0258ff9d3711b1"}, {file = "coverage-7.5.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:f0bfe42523893c188e9616d853c47685e1c575fe25f737adf473d0405dcfa7eb"}, {file = "coverage-7.5.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a9a7ef30a1b02547c1b23fa9a5564f03c9982fc71eb2ecb7f98c96d7a0db5cf2"}, {file = "coverage-7.5.0-cp312-cp312-win32.whl", hash = "sha256:3c2b77f295edb9fcdb6a250f83e6481c679335ca7e6e4a955e4290350f2d22a4"}, {file = "coverage-7.5.0-cp312-cp312-win_amd64.whl", hash = "sha256:427e1e627b0963ac02d7c8730ca6d935df10280d230508c0ba059505e9233475"}, {file = "coverage-7.5.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9dd88fce54abbdbf4c42fb1fea0e498973d07816f24c0e27a1ecaf91883ce69e"}, {file = "coverage-7.5.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a898c11dca8f8c97b467138004a30133974aacd572818c383596f8d5b2eb04a9"}, {file = "coverage-7.5.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:07dfdd492d645eea1bd70fb1d6febdcf47db178b0d99161d8e4eed18e7f62fe7"}, {file = "coverage-7.5.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d3d117890b6eee85887b1eed41eefe2e598ad6e40523d9f94c4c4b213258e4a4"}, {file = "coverage-7.5.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6afd2e84e7da40fe23ca588379f815fb6dbbb1b757c883935ed11647205111cb"}, {file = "coverage-7.5.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:a9960dd1891b2ddf13a7fe45339cd59ecee3abb6b8326d8b932d0c5da208104f"}, {file = "coverage-7.5.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ced268e82af993d7801a9db2dbc1d2322e786c5dc76295d8e89473d46c6b84d4"}, {file = "coverage-7.5.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:e7c211f25777746d468d76f11719e64acb40eed410d81c26cefac641975beb88"}, {file = "coverage-7.5.0-cp38-cp38-win32.whl", hash = "sha256:262fffc1f6c1a26125d5d573e1ec379285a3723363f3bd9c83923c9593a2ac25"}, {file = "coverage-7.5.0-cp38-cp38-win_amd64.whl", hash = "sha256:eed462b4541c540d63ab57b3fc69e7d8c84d5957668854ee4e408b50e92ce26a"}, {file = "coverage-7.5.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d0194d654e360b3e6cc9b774e83235bae6b9b2cac3be09040880bb0e8a88f4a1"}, {file = "coverage-7.5.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:33c020d3322662e74bc507fb11488773a96894aa82a622c35a5a28673c0c26f5"}, {file = "coverage-7.5.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0cbdf2cae14a06827bec50bd58e49249452d211d9caddd8bd80e35b53cb04631"}, {file = "coverage-7.5.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3235d7c781232e525b0761730e052388a01548bd7f67d0067a253887c6e8df46"}, {file = "coverage-7.5.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db2de4e546f0ec4b2787d625e0b16b78e99c3e21bc1722b4977c0dddf11ca84e"}, {file = "coverage-7.5.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:4d0e206259b73af35c4ec1319fd04003776e11e859936658cb6ceffdeba0f5be"}, {file = "coverage-7.5.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:2055c4fb9a6ff624253d432aa471a37202cd8f458c033d6d989be4499aed037b"}, {file = "coverage-7.5.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:075299460948cd12722a970c7eae43d25d37989da682997687b34ae6b87c0ef0"}, {file = "coverage-7.5.0-cp39-cp39-win32.whl", hash = "sha256:280132aada3bc2f0fac939a5771db4fbb84f245cb35b94fae4994d4c1f80dae7"}, {file = "coverage-7.5.0-cp39-cp39-win_amd64.whl", hash = "sha256:c58536f6892559e030e6924896a44098bc1290663ea12532c78cef71d0df8493"}, {file = "coverage-7.5.0-pp38.pp39.pp310-none-any.whl", hash = "sha256:2b57780b51084d5223eee7b59f0d4911c31c16ee5aa12737c7a02455829ff067"}, {file = "coverage-7.5.0.tar.gz", hash = "sha256:cf62d17310f34084c59c01e027259076479128d11e4661bb6c9acb38c5e19bb8"}, ] [[package]] name = "coverage" version = "7.5.0" extras = ["toml"] requires_python = ">=3.8" summary = "Code coverage measurement for Python" dependencies = [ "coverage==7.5.0", "tomli; python_full_version <= \"3.11.0a6\"", ] files = [ {file = "coverage-7.5.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:432949a32c3e3f820af808db1833d6d1631664d53dd3ce487aa25d574e18ad1c"}, {file = "coverage-7.5.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2bd7065249703cbeb6d4ce679c734bef0ee69baa7bff9724361ada04a15b7e3b"}, {file = "coverage-7.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bbfe6389c5522b99768a93d89aca52ef92310a96b99782973b9d11e80511f932"}, {file = "coverage-7.5.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:39793731182c4be939b4be0cdecde074b833f6171313cf53481f869937129ed3"}, {file = "coverage-7.5.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85a5dbe1ba1bf38d6c63b6d2c42132d45cbee6d9f0c51b52c59aa4afba057517"}, {file = "coverage-7.5.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:357754dcdfd811462a725e7501a9b4556388e8ecf66e79df6f4b988fa3d0b39a"}, {file = "coverage-7.5.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:a81eb64feded34f40c8986869a2f764f0fe2db58c0530d3a4afbcde50f314880"}, {file = "coverage-7.5.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:51431d0abbed3a868e967f8257c5faf283d41ec882f58413cf295a389bb22e58"}, {file = "coverage-7.5.0-cp310-cp310-win32.whl", hash = "sha256:f609ebcb0242d84b7adeee2b06c11a2ddaec5464d21888b2c8255f5fd6a98ae4"}, {file = "coverage-7.5.0-cp310-cp310-win_amd64.whl", hash = "sha256:6782cd6216fab5a83216cc39f13ebe30adfac2fa72688c5a4d8d180cd52e8f6a"}, {file = "coverage-7.5.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e768d870801f68c74c2b669fc909839660180c366501d4cc4b87efd6b0eee375"}, {file = "coverage-7.5.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:84921b10aeb2dd453247fd10de22907984eaf80901b578a5cf0bb1e279a587cb"}, {file = "coverage-7.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:710c62b6e35a9a766b99b15cdc56d5aeda0914edae8bb467e9c355f75d14ee95"}, {file = "coverage-7.5.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c379cdd3efc0658e652a14112d51a7668f6bfca7445c5a10dee7eabecabba19d"}, {file = "coverage-7.5.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fea9d3ca80bcf17edb2c08a4704259dadac196fe5e9274067e7a20511fad1743"}, {file = "coverage-7.5.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:41327143c5b1d715f5f98a397608f90ab9ebba606ae4e6f3389c2145410c52b1"}, {file = "coverage-7.5.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:565b2e82d0968c977e0b0f7cbf25fd06d78d4856289abc79694c8edcce6eb2de"}, {file = "coverage-7.5.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cf3539007202ebfe03923128fedfdd245db5860a36810136ad95a564a2fdffff"}, {file = "coverage-7.5.0-cp311-cp311-win32.whl", hash = "sha256:bf0b4b8d9caa8d64df838e0f8dcf68fb570c5733b726d1494b87f3da85db3a2d"}, {file = "coverage-7.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:9c6384cc90e37cfb60435bbbe0488444e54b98700f727f16f64d8bfda0b84656"}, {file = "coverage-7.5.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:fed7a72d54bd52f4aeb6c6e951f363903bd7d70bc1cad64dd1f087980d309ab9"}, {file = "coverage-7.5.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:cbe6581fcff7c8e262eb574244f81f5faaea539e712a058e6707a9d272fe5b64"}, {file = "coverage-7.5.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ad97ec0da94b378e593ef532b980c15e377df9b9608c7c6da3506953182398af"}, {file = "coverage-7.5.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bd4bacd62aa2f1a1627352fe68885d6ee694bdaebb16038b6e680f2924a9b2cc"}, {file = "coverage-7.5.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:adf032b6c105881f9d77fa17d9eebe0ad1f9bfb2ad25777811f97c5362aa07f2"}, {file = "coverage-7.5.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:4ba01d9ba112b55bfa4b24808ec431197bb34f09f66f7cb4fd0258ff9d3711b1"}, {file = "coverage-7.5.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:f0bfe42523893c188e9616d853c47685e1c575fe25f737adf473d0405dcfa7eb"}, {file = "coverage-7.5.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a9a7ef30a1b02547c1b23fa9a5564f03c9982fc71eb2ecb7f98c96d7a0db5cf2"}, {file = "coverage-7.5.0-cp312-cp312-win32.whl", hash = "sha256:3c2b77f295edb9fcdb6a250f83e6481c679335ca7e6e4a955e4290350f2d22a4"}, {file = "coverage-7.5.0-cp312-cp312-win_amd64.whl", hash = "sha256:427e1e627b0963ac02d7c8730ca6d935df10280d230508c0ba059505e9233475"}, {file = "coverage-7.5.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9dd88fce54abbdbf4c42fb1fea0e498973d07816f24c0e27a1ecaf91883ce69e"}, {file = "coverage-7.5.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a898c11dca8f8c97b467138004a30133974aacd572818c383596f8d5b2eb04a9"}, {file = "coverage-7.5.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:07dfdd492d645eea1bd70fb1d6febdcf47db178b0d99161d8e4eed18e7f62fe7"}, {file = "coverage-7.5.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d3d117890b6eee85887b1eed41eefe2e598ad6e40523d9f94c4c4b213258e4a4"}, {file = "coverage-7.5.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6afd2e84e7da40fe23ca588379f815fb6dbbb1b757c883935ed11647205111cb"}, {file = "coverage-7.5.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:a9960dd1891b2ddf13a7fe45339cd59ecee3abb6b8326d8b932d0c5da208104f"}, {file = "coverage-7.5.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ced268e82af993d7801a9db2dbc1d2322e786c5dc76295d8e89473d46c6b84d4"}, {file = "coverage-7.5.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:e7c211f25777746d468d76f11719e64acb40eed410d81c26cefac641975beb88"}, {file = "coverage-7.5.0-cp38-cp38-win32.whl", hash = "sha256:262fffc1f6c1a26125d5d573e1ec379285a3723363f3bd9c83923c9593a2ac25"}, {file = "coverage-7.5.0-cp38-cp38-win_amd64.whl", hash = "sha256:eed462b4541c540d63ab57b3fc69e7d8c84d5957668854ee4e408b50e92ce26a"}, {file = "coverage-7.5.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d0194d654e360b3e6cc9b774e83235bae6b9b2cac3be09040880bb0e8a88f4a1"}, {file = "coverage-7.5.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:33c020d3322662e74bc507fb11488773a96894aa82a622c35a5a28673c0c26f5"}, {file = "coverage-7.5.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0cbdf2cae14a06827bec50bd58e49249452d211d9caddd8bd80e35b53cb04631"}, {file = "coverage-7.5.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3235d7c781232e525b0761730e052388a01548bd7f67d0067a253887c6e8df46"}, {file = "coverage-7.5.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db2de4e546f0ec4b2787d625e0b16b78e99c3e21bc1722b4977c0dddf11ca84e"}, {file = "coverage-7.5.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:4d0e206259b73af35c4ec1319fd04003776e11e859936658cb6ceffdeba0f5be"}, {file = "coverage-7.5.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:2055c4fb9a6ff624253d432aa471a37202cd8f458c033d6d989be4499aed037b"}, {file = "coverage-7.5.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:075299460948cd12722a970c7eae43d25d37989da682997687b34ae6b87c0ef0"}, {file = "coverage-7.5.0-cp39-cp39-win32.whl", hash = "sha256:280132aada3bc2f0fac939a5771db4fbb84f245cb35b94fae4994d4c1f80dae7"}, {file = "coverage-7.5.0-cp39-cp39-win_amd64.whl", hash = "sha256:c58536f6892559e030e6924896a44098bc1290663ea12532c78cef71d0df8493"}, {file = "coverage-7.5.0-pp38.pp39.pp310-none-any.whl", hash = "sha256:2b57780b51084d5223eee7b59f0d4911c31c16ee5aa12737c7a02455829ff067"}, {file = "coverage-7.5.0.tar.gz", hash = "sha256:cf62d17310f34084c59c01e027259076479128d11e4661bb6c9acb38c5e19bb8"}, ] [[package]] name = "cssutils" version = "2.10.2" requires_python = ">=3.8" summary = "A CSS Cascading Style Sheets library for Python" files = [ {file = "cssutils-2.10.2-py3-none-any.whl", hash = "sha256:4ad7d2f29270b22cf199f65a6b5e795f2c3130f3b9fb50c3d45e5054ef86e41a"}, {file = "cssutils-2.10.2.tar.gz", hash = "sha256:93cf92a350b1c123b17feff042e212f94d960975a3ed145743d84ebe8ccec7ab"}, ] [[package]] name = "dict2css" version = "0.3.0.post1" requires_python = ">=3.6" summary = "A μ-library for constructing cascading style sheets from Python dictionaries." dependencies = [ "cssutils>=2.2.0", "domdf-python-tools>=2.2.0", ] files = [ {file = "dict2css-0.3.0.post1-py3-none-any.whl", hash = "sha256:f006a6b774c3e31869015122ae82c491fd25e7de4a75607a62aa3e798f837e0d"}, {file = "dict2css-0.3.0.post1.tar.gz", hash = "sha256:89c544c21c4ca7472c3fffb9d37d3d926f606329afdb751dc1de67a411b70719"}, ] [[package]] name = "distlib" version = "0.3.8" summary = "Distribution utilities" files = [ {file = "distlib-0.3.8-py2.py3-none-any.whl", hash = "sha256:034db59a0b96f8ca18035f36290806a9a6e6bd9d1ff91e45a7f172eb17e51784"}, {file = "distlib-0.3.8.tar.gz", hash = "sha256:1530ea13e350031b6312d8580ddb6b27a104275a31106523b8f123787f494f64"}, ] [[package]] name = "dnspython" version = "2.6.1" requires_python = ">=3.8" summary = "DNS toolkit" files = [ {file = "dnspython-2.6.1-py3-none-any.whl", hash = "sha256:5ef3b9680161f6fa89daf8ad451b5f1a33b18ae8a1c6778cdf4b43f08c0a6e50"}, {file = "dnspython-2.6.1.tar.gz", hash = "sha256:e8f0f9c23a7b7cb99ded64e6c3a6f3e701d78f50c55e002b839dea7225cff7cc"}, ] [[package]] name = "docutils" version = "0.20.1" requires_python = ">=3.7" summary = "Docutils -- Python Documentation Utilities" files = [ {file = "docutils-0.20.1-py3-none-any.whl", hash = "sha256:96f387a2c5562db4476f09f13bbab2192e764cac08ebbf3a34a95d9b1e4a59d6"}, {file = "docutils-0.20.1.tar.gz", hash = "sha256:f08a4e276c3a1583a86dce3e34aba3fe04d02bba2dd51ed16106244e8a923e3b"}, ] [[package]] name = "domdf-python-tools" version = "3.8.0.post2" requires_python = ">=3.6" summary = "Helpful functions for Python 🐍 🛠️" dependencies = [ "importlib-metadata>=3.6.0; python_version < \"3.9\"", "importlib-resources>=3.0.0; python_version < \"3.7\"", "natsort>=7.0.1", "typing-extensions>=3.7.4.1", ] files = [ {file = "domdf_python_tools-3.8.0.post2-py3-none-any.whl", hash = "sha256:ad2c763c8d00850a7fa92ad95e9891a1918281ea25322c4dbb1734fd32f905dd"}, {file = "domdf_python_tools-3.8.0.post2.tar.gz", hash = "sha256:a1fd255ea29f767b08de462d2da39d360262304389227d980bc307ee8aa3366a"}, ] [[package]] name = "email-validator" version = "2.1.0.post1" requires_python = ">=3.8" summary = "A robust email address syntax and deliverability validation library." dependencies = [ "dnspython>=2.0.0", "idna>=2.0.0", ] files = [ {file = "email_validator-2.1.0.post1-py3-none-any.whl", hash = "sha256:c973053efbeddfef924dc0bd93f6e77a1ea7ee0fce935aea7103c7a3d6d2d637"}, {file = "email_validator-2.1.0.post1.tar.gz", hash = "sha256:a4b0bd1cf55f073b924258d19321b1f3aa74b4b5a71a42c305575dba920e1a44"}, ] [[package]] name = "exceptiongroup" version = "1.2.1" requires_python = ">=3.7" summary = "Backport of PEP 654 (exception groups)" files = [ {file = "exceptiongroup-1.2.1-py3-none-any.whl", hash = "sha256:5258b9ed329c5bbdd31a309f53cbfb0b155341807f6ff7606a1e801a891b29ad"}, {file = "exceptiongroup-1.2.1.tar.gz", hash = "sha256:a4785e48b045528f5bfe627b6ad554ff32def154f42372786903b7abcfe1aa16"}, ] [[package]] name = "faker" version = "25.2.0" requires_python = ">=3.8" summary = "Faker is a Python package that generates fake data for you." dependencies = [ "python-dateutil>=2.4", ] files = [ {file = "Faker-25.2.0-py3-none-any.whl", hash = "sha256:cfe97c4857c4c36ee32ea4aaabef884895992e209bae4cbd26807cf3e05c6918"}, {file = "Faker-25.2.0.tar.gz", hash = "sha256:45b84f47ff1ef86e3d1a8d11583ca871ecf6730fad0660edadc02576583a2423"}, ] [[package]] name = "filelock" version = "3.14.0" requires_python = ">=3.8" summary = "A platform independent file lock." files = [ {file = "filelock-3.14.0-py3-none-any.whl", hash = "sha256:43339835842f110ca7ae60f1e1c160714c5a6afd15a2873419ab185334975c0f"}, {file = "filelock-3.14.0.tar.gz", hash = "sha256:6ea72da3be9b8c82afd3edcf99f2fffbb5076335a5ae4d03248bb5b6c3eae78a"}, ] [[package]] name = "git-cliff" version = "2.2.2" requires_python = ">=3.7" summary = "A highly customizable changelog generator ⛰️" files = [ {file = "git_cliff-2.2.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:3a3af4cb34b11875c9c2939d5eae41def33e1cc2bb837069ab61ac2bdec47ad2"}, {file = "git_cliff-2.2.2-py3-none-macosx_11_0_arm64.whl", hash = "sha256:8f631e193ea668d4527cf50a258a8e1597058e46021e3ec44a33b4c343e0fee9"}, {file = "git_cliff-2.2.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:65e7aac3357c75aaaccfe737a38772cada41d734ca86c2ca496ca60fa1e3f2ee"}, {file = "git_cliff-2.2.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a59730f49e212c4583a967e9ddea7f6c507cee01d461f4c4602a366999e3be73"}, {file = "git_cliff-2.2.2-py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:0f411a58df635ce779d0048db19d347a0eeb37f3d061e08335659c587518b4cc"}, {file = "git_cliff-2.2.2-py3-none-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6def651f6c44b527f33822c8e063383f2596eab7f0796d06213a31c22302d2c4"}, {file = "git_cliff-2.2.2-py3-none-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:aa3888fc975a0d55a8434ef0ad0d481e918ad761c191a64b29f3ed9337843538"}, {file = "git_cliff-2.2.2-py3-none-win32.whl", hash = "sha256:96155b457dec726dcebed2c5a3fecb3994c7991a4ce0779515907fd53945c13d"}, {file = "git_cliff-2.2.2-py3-none-win_amd64.whl", hash = "sha256:fa5017b3e204f5cc7c7b4442a082fa9ae6f40736e55353649fcc12e6bb7632be"}, {file = "git_cliff-2.2.2.tar.gz", hash = "sha256:1ff34e6659cac3f9fa01645e1edf5bce333d22738a6579be7b8e79c636a6c25f"}, ] [[package]] name = "greenlet" version = "3.0.3" requires_python = ">=3.7" summary = "Lightweight in-process concurrent programming" files = [ {file = "greenlet-3.0.3-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:9da2bd29ed9e4f15955dd1595ad7bc9320308a3b766ef7f837e23ad4b4aac31a"}, {file = "greenlet-3.0.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d353cadd6083fdb056bb46ed07e4340b0869c305c8ca54ef9da3421acbdf6881"}, {file = "greenlet-3.0.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dca1e2f3ca00b84a396bc1bce13dd21f680f035314d2379c4160c98153b2059b"}, {file = "greenlet-3.0.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3ed7fb269f15dc662787f4119ec300ad0702fa1b19d2135a37c2c4de6fadfd4a"}, {file = "greenlet-3.0.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd4f49ae60e10adbc94b45c0b5e6a179acc1736cf7a90160b404076ee283cf83"}, {file = "greenlet-3.0.3-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:73a411ef564e0e097dbe7e866bb2dda0f027e072b04da387282b02c308807405"}, {file = "greenlet-3.0.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:7f362975f2d179f9e26928c5b517524e89dd48530a0202570d55ad6ca5d8a56f"}, {file = "greenlet-3.0.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:649dde7de1a5eceb258f9cb00bdf50e978c9db1b996964cd80703614c86495eb"}, {file = "greenlet-3.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:68834da854554926fbedd38c76e60c4a2e3198c6fbed520b106a8986445caaf9"}, {file = "greenlet-3.0.3-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:b1b5667cced97081bf57b8fa1d6bfca67814b0afd38208d52538316e9422fc61"}, {file = "greenlet-3.0.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:52f59dd9c96ad2fc0d5724107444f76eb20aaccb675bf825df6435acb7703559"}, {file = "greenlet-3.0.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:afaff6cf5200befd5cec055b07d1c0a5a06c040fe5ad148abcd11ba6ab9b114e"}, {file = "greenlet-3.0.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fe754d231288e1e64323cfad462fcee8f0288654c10bdf4f603a39ed923bef33"}, {file = "greenlet-3.0.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2797aa5aedac23af156bbb5a6aa2cd3427ada2972c828244eb7d1b9255846379"}, {file = "greenlet-3.0.3-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b7f009caad047246ed379e1c4dbcb8b020f0a390667ea74d2387be2998f58a22"}, {file = "greenlet-3.0.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:c5e1536de2aad7bf62e27baf79225d0d64360d4168cf2e6becb91baf1ed074f3"}, {file = "greenlet-3.0.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:894393ce10ceac937e56ec00bb71c4c2f8209ad516e96033e4b3b1de270e200d"}, {file = "greenlet-3.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:1ea188d4f49089fc6fb283845ab18a2518d279c7cd9da1065d7a84e991748728"}, {file = "greenlet-3.0.3-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:70fb482fdf2c707765ab5f0b6655e9cfcf3780d8d87355a063547b41177599be"}, {file = "greenlet-3.0.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d4d1ac74f5c0c0524e4a24335350edad7e5f03b9532da7ea4d3c54d527784f2e"}, {file = "greenlet-3.0.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:149e94a2dd82d19838fe4b2259f1b6b9957d5ba1b25640d2380bea9c5df37676"}, {file = "greenlet-3.0.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:15d79dd26056573940fcb8c7413d84118086f2ec1a8acdfa854631084393efcc"}, {file = "greenlet-3.0.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:881b7db1ebff4ba09aaaeae6aa491daeb226c8150fc20e836ad00041bcb11230"}, {file = "greenlet-3.0.3-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fcd2469d6a2cf298f198f0487e0a5b1a47a42ca0fa4dfd1b6862c999f018ebbf"}, {file = "greenlet-3.0.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:1f672519db1796ca0d8753f9e78ec02355e862d0998193038c7073045899f305"}, {file = "greenlet-3.0.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2516a9957eed41dd8f1ec0c604f1cdc86758b587d964668b5b196a9db5bfcde6"}, {file = "greenlet-3.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:bba5387a6975598857d86de9eac14210a49d554a77eb8261cc68b7d082f78ce2"}, {file = "greenlet-3.0.3-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:1996cb9306c8595335bb157d133daf5cf9f693ef413e7673cb07e3e5871379ca"}, {file = "greenlet-3.0.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3ddc0f794e6ad661e321caa8d2f0a55ce01213c74722587256fb6566049a8b04"}, {file = "greenlet-3.0.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c9db1c18f0eaad2f804728c67d6c610778456e3e1cc4ab4bbd5eeb8e6053c6fc"}, {file = "greenlet-3.0.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7170375bcc99f1a2fbd9c306f5be8764eaf3ac6b5cb968862cad4c7057756506"}, {file = "greenlet-3.0.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b66c9c1e7ccabad3a7d037b2bcb740122a7b17a53734b7d72a344ce39882a1b"}, {file = "greenlet-3.0.3-cp38-cp38-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:098d86f528c855ead3479afe84b49242e174ed262456c342d70fc7f972bc13c4"}, {file = "greenlet-3.0.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:81bb9c6d52e8321f09c3d165b2a78c680506d9af285bfccbad9fb7ad5a5da3e5"}, {file = "greenlet-3.0.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:fd096eb7ffef17c456cfa587523c5f92321ae02427ff955bebe9e3c63bc9f0da"}, {file = "greenlet-3.0.3-cp38-cp38-win32.whl", hash = "sha256:d46677c85c5ba00a9cb6f7a00b2bfa6f812192d2c9f7d9c4f6a55b60216712f3"}, {file = "greenlet-3.0.3-cp38-cp38-win_amd64.whl", hash = "sha256:419b386f84949bf0e7c73e6032e3457b82a787c1ab4a0e43732898a761cc9dbf"}, {file = "greenlet-3.0.3-cp39-cp39-macosx_11_0_universal2.whl", hash = "sha256:da70d4d51c8b306bb7a031d5cff6cc25ad253affe89b70352af5f1cb68e74b53"}, {file = "greenlet-3.0.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:086152f8fbc5955df88382e8a75984e2bb1c892ad2e3c80a2508954e52295257"}, {file = "greenlet-3.0.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d73a9fe764d77f87f8ec26a0c85144d6a951a6c438dfe50487df5595c6373eac"}, {file = "greenlet-3.0.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b7dcbe92cc99f08c8dd11f930de4d99ef756c3591a5377d1d9cd7dd5e896da71"}, {file = "greenlet-3.0.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1551a8195c0d4a68fac7a4325efac0d541b48def35feb49d803674ac32582f61"}, {file = "greenlet-3.0.3-cp39-cp39-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:64d7675ad83578e3fc149b617a444fab8efdafc9385471f868eb5ff83e446b8b"}, {file = "greenlet-3.0.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b37eef18ea55f2ffd8f00ff8fe7c8d3818abd3e25fb73fae2ca3b672e333a7a6"}, {file = "greenlet-3.0.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:77457465d89b8263bca14759d7c1684df840b6811b2499838cc5b040a8b5b113"}, {file = "greenlet-3.0.3-cp39-cp39-win32.whl", hash = "sha256:57e8974f23e47dac22b83436bdcf23080ade568ce77df33159e019d161ce1d1e"}, {file = "greenlet-3.0.3-cp39-cp39-win_amd64.whl", hash = "sha256:c5ee858cfe08f34712f548c3c363e807e7186f03ad7a5039ebadb29e8c6be067"}, {file = "greenlet-3.0.3.tar.gz", hash = "sha256:43374442353259554ce33599da8b692d5aa96f8976d567d4badf263371fbe491"}, ] [[package]] name = "html5lib" version = "1.1" requires_python = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" summary = "HTML parser based on the WHATWG HTML specification" dependencies = [ "six>=1.9", "webencodings", ] files = [ {file = "html5lib-1.1-py2.py3-none-any.whl", hash = "sha256:0d78f8fde1c230e99fe37986a60526d7049ed4bf8a9fadbad5f00e22e58e041d"}, {file = "html5lib-1.1.tar.gz", hash = "sha256:b2e5b40261e20f354d198eae92afc10d750afb487ed5e50f9c4eaf07c184146f"}, ] [[package]] name = "hypothesis" version = "6.102.6" requires_python = ">=3.8" summary = "A library for property-based testing" dependencies = [ "attrs>=22.2.0", "exceptiongroup>=1.0.0; python_version < \"3.11\"", "sortedcontainers<3.0.0,>=2.1.0", ] files = [ {file = "hypothesis-6.102.6-py3-none-any.whl", hash = "sha256:ef281ba8b2626ebade9f463fbe8851ae6ff6ae4a8621a9e54c7c2477a97ccff0"}, {file = "hypothesis-6.102.6.tar.gz", hash = "sha256:ef5655b4ca349082241ab55f899a34ea6d75cc336a7b07356680909059db1349"}, ] [[package]] name = "identify" version = "2.5.36" requires_python = ">=3.8" summary = "File identification library for Python" files = [ {file = "identify-2.5.36-py2.py3-none-any.whl", hash = "sha256:37d93f380f4de590500d9dba7db359d0d3da95ffe7f9de1753faa159e71e7dfa"}, {file = "identify-2.5.36.tar.gz", hash = "sha256:e5e00f54165f9047fbebeb4a560f9acfb8af4c88232be60a488e9b68d122745d"}, ] [[package]] name = "idna" version = "3.7" requires_python = ">=3.5" summary = "Internationalized Domain Names in Applications (IDNA)" files = [ {file = "idna-3.7-py3-none-any.whl", hash = "sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0"}, {file = "idna-3.7.tar.gz", hash = "sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc"}, ] [[package]] name = "imagesize" version = "1.4.1" requires_python = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" summary = "Getting image size from png/jpeg/jpeg2000/gif file" files = [ {file = "imagesize-1.4.1-py2.py3-none-any.whl", hash = "sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b"}, {file = "imagesize-1.4.1.tar.gz", hash = "sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a"}, ] [[package]] name = "importlib-metadata" version = "7.1.0" requires_python = ">=3.8" summary = "Read metadata from Python packages" dependencies = [ "typing-extensions>=3.6.4; python_version < \"3.8\"", "zipp>=0.5", ] files = [ {file = "importlib_metadata-7.1.0-py3-none-any.whl", hash = "sha256:30962b96c0c223483ed6cc7280e7f0199feb01a0e40cfae4d4450fc6fab1f570"}, {file = "importlib_metadata-7.1.0.tar.gz", hash = "sha256:b78938b926ee8d5f020fc4772d487045805a55ddbad2ecf21c6d60938dc7fcd2"}, ] [[package]] name = "iniconfig" version = "2.0.0" requires_python = ">=3.7" summary = "brain-dead simple config-ini parsing" files = [ {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, ] [[package]] name = "jinja2" version = "3.1.3" requires_python = ">=3.7" summary = "A very fast and expressive template engine." dependencies = [ "MarkupSafe>=2.0", ] files = [ {file = "Jinja2-3.1.3-py3-none-any.whl", hash = "sha256:7d6d50dd97d52cbc355597bd845fabfbac3f551e1f99619e39a35ce8c370b5fa"}, {file = "Jinja2-3.1.3.tar.gz", hash = "sha256:ac8bd6544d4bb2c9792bf3a159e80bba8fda7f07e81bc3aed565432d5925ba90"}, ] [[package]] name = "lazy-model" version = "0.2.0" requires_python = ">=3.7,<4.0" summary = "" dependencies = [ "pydantic>=1.9.0", ] files = [ {file = "lazy-model-0.2.0.tar.gz", hash = "sha256:57c0e91e171530c4fca7aebc3ac05a163a85cddd941bf7527cc46c0ddafca47c"}, {file = "lazy_model-0.2.0-py3-none-any.whl", hash = "sha256:5a3241775c253e36d9069d236be8378288a93d4fc53805211fd152e04cc9c342"}, ] [[package]] name = "litestar-sphinx-theme" version = "0.3.1" requires_python = "<4.0,>=3.8" git = "https://github.com/litestar-org/litestar-sphinx-theme.git" ref = "v3" revision = "4799f935c3023afb222058cba8c849e8fa9ae3ba" summary = "A Sphinx theme for the Litestar organization" dependencies = [ "blacken-docs>=1.16.0", "shibuya>=2024.4.4", "sphinx-autobuild>=2021.3.14", "sphinx-copybutton>=0.5.2", "sphinx-design<1.0.0,>=0.3.0", "sphinx-togglebutton", "sphinx-toolbox>=3.5.0", ] [[package]] name = "livereload" version = "2.6.3" summary = "Python LiveReload is an awesome tool for web developers" dependencies = [ "six", "tornado; python_version > \"2.7\"", "tornado<6; python_version == \"2.7\"", ] files = [ {file = "livereload-2.6.3-py2.py3-none-any.whl", hash = "sha256:ad4ac6f53b2d62bb6ce1a5e6e96f1f00976a32348afedcb4b6d68df2a1d346e4"}, {file = "livereload-2.6.3.tar.gz", hash = "sha256:776f2f865e59fde56490a56bcc6773b6917366bce0c267c60ee8aaf1a0959869"}, ] [[package]] name = "markupsafe" version = "2.1.5" requires_python = ">=3.7" summary = "Safely add untrusted strings to HTML/XML markup." files = [ {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a17a92de5231666cfbe003f0e4b9b3a7ae3afb1ec2845aadc2bacc93ff85febc"}, {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:72b6be590cc35924b02c78ef34b467da4ba07e4e0f0454a2c5907f473fc50ce5"}, {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e61659ba32cf2cf1481e575d0462554625196a1f2fc06a1c777d3f48e8865d46"}, {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2174c595a0d73a3080ca3257b40096db99799265e1c27cc5a610743acd86d62f"}, {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae2ad8ae6ebee9d2d94b17fb62763125f3f374c25618198f40cbb8b525411900"}, {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:075202fa5b72c86ad32dc7d0b56024ebdbcf2048c0ba09f1cde31bfdd57bcfff"}, {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:598e3276b64aff0e7b3451b72e94fa3c238d452e7ddcd893c3ab324717456bad"}, {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fce659a462a1be54d2ffcacea5e3ba2d74daa74f30f5f143fe0c58636e355fdd"}, {file = "MarkupSafe-2.1.5-cp310-cp310-win32.whl", hash = "sha256:d9fad5155d72433c921b782e58892377c44bd6252b5af2f67f16b194987338a4"}, {file = "MarkupSafe-2.1.5-cp310-cp310-win_amd64.whl", hash = "sha256:bf50cd79a75d181c9181df03572cdce0fbb75cc353bc350712073108cba98de5"}, {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f"}, {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2"}, {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced"}, {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5"}, {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7502934a33b54030eaf1194c21c692a534196063db72176b0c4028e140f8f32c"}, {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0e397ac966fdf721b2c528cf028494e86172b4feba51d65f81ffd65c63798f3f"}, {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c061bb86a71b42465156a3ee7bd58c8c2ceacdbeb95d05a99893e08b8467359a"}, {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3a57fdd7ce31c7ff06cdfbf31dafa96cc533c21e443d57f5b1ecc6cdc668ec7f"}, {file = "MarkupSafe-2.1.5-cp311-cp311-win32.whl", hash = "sha256:397081c1a0bfb5124355710fe79478cdbeb39626492b15d399526ae53422b906"}, {file = "MarkupSafe-2.1.5-cp311-cp311-win_amd64.whl", hash = "sha256:2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617"}, {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:8dec4936e9c3100156f8a2dc89c4b88d5c435175ff03413b443469c7c8c5f4d1"}, {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4"}, {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac07bad82163452a6884fe8fa0963fb98c2346ba78d779ec06bd7a6262132aee"}, {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5dfb42c4604dddc8e4305050aa6deb084540643ed5804d7455b5df8fe16f5e5"}, {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ea3d8a3d18833cf4304cd2fc9cbb1efe188ca9b5efef2bdac7adc20594a0e46b"}, {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d050b3361367a06d752db6ead6e7edeb0009be66bc3bae0ee9d97fb326badc2a"}, {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bec0a414d016ac1a18862a519e54b2fd0fc8bbfd6890376898a6c0891dd82e9f"}, {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:58c98fee265677f63a4385256a6d7683ab1832f3ddd1e66fe948d5880c21a169"}, {file = "MarkupSafe-2.1.5-cp312-cp312-win32.whl", hash = "sha256:8590b4ae07a35970728874632fed7bd57b26b0102df2d2b233b6d9d82f6c62ad"}, {file = "MarkupSafe-2.1.5-cp312-cp312-win_amd64.whl", hash = "sha256:823b65d8706e32ad2df51ed89496147a42a2a6e01c13cfb6ffb8b1e92bc910bb"}, {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:656f7526c69fac7f600bd1f400991cc282b417d17539a1b228617081106feb4a"}, {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:97cafb1f3cbcd3fd2b6fbfb99ae11cdb14deea0736fc2b0952ee177f2b813a46"}, {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f3fbcb7ef1f16e48246f704ab79d79da8a46891e2da03f8783a5b6fa41a9532"}, {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa9db3f79de01457b03d4f01b34cf91bc0048eb2c3846ff26f66687c2f6d16ab"}, {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffee1f21e5ef0d712f9033568f8344d5da8cc2869dbd08d87c84656e6a2d2f68"}, {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5dedb4db619ba5a2787a94d877bc8ffc0566f92a01c0ef214865e54ecc9ee5e0"}, {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:30b600cf0a7ac9234b2638fbc0fb6158ba5bdcdf46aeb631ead21248b9affbc4"}, {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8dd717634f5a044f860435c1d8c16a270ddf0ef8588d4887037c5028b859b0c3"}, {file = "MarkupSafe-2.1.5-cp38-cp38-win32.whl", hash = "sha256:daa4ee5a243f0f20d528d939d06670a298dd39b1ad5f8a72a4275124a7819eff"}, {file = "MarkupSafe-2.1.5-cp38-cp38-win_amd64.whl", hash = "sha256:619bc166c4f2de5caa5a633b8b7326fbe98e0ccbfacabd87268a2b15ff73a029"}, {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7a68b554d356a91cce1236aa7682dc01df0edba8d043fd1ce607c49dd3c1edcf"}, {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:db0b55e0f3cc0be60c1f19efdde9a637c32740486004f20d1cff53c3c0ece4d2"}, {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e53af139f8579a6d5f7b76549125f0d94d7e630761a2111bc431fd820e163b8"}, {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17b950fccb810b3293638215058e432159d2b71005c74371d784862b7e4683f3"}, {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4c31f53cdae6ecfa91a77820e8b151dba54ab528ba65dfd235c80b086d68a465"}, {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:bff1b4290a66b490a2f4719358c0cdcd9bafb6b8f061e45c7a2460866bf50c2e"}, {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bc1667f8b83f48511b94671e0e441401371dfd0f0a795c7daa4a3cd1dde55bea"}, {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5049256f536511ee3f7e1b3f87d1d1209d327e818e6ae1365e8653d7e3abb6a6"}, {file = "MarkupSafe-2.1.5-cp39-cp39-win32.whl", hash = "sha256:00e046b6dd71aa03a41079792f8473dc494d564611a8f89bbbd7cb93295ebdcf"}, {file = "MarkupSafe-2.1.5-cp39-cp39-win_amd64.whl", hash = "sha256:fa173ec60341d6bb97a89f5ea19c85c5643c1e7dedebc22f5181eb73573142c5"}, {file = "MarkupSafe-2.1.5.tar.gz", hash = "sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b"}, ] [[package]] name = "mongomock" version = "4.1.2" summary = "Fake pymongo stub for testing simple MongoDB-dependent code" dependencies = [ "packaging", "sentinels", ] files = [ {file = "mongomock-4.1.2-py2.py3-none-any.whl", hash = "sha256:08a24938a05c80c69b6b8b19a09888d38d8c6e7328547f94d46cadb7f47209f2"}, {file = "mongomock-4.1.2.tar.gz", hash = "sha256:f06cd62afb8ae3ef63ba31349abd220a657ef0dd4f0243a29587c5213f931b7d"}, ] [[package]] name = "mongomock-motor" version = "0.0.29" requires_python = ">=3.6" summary = "Library for mocking AsyncIOMotorClient built on top of mongomock." dependencies = [ "mongomock<5.0.0,>=3.23.0", ] files = [ {file = "mongomock_motor-0.0.29-py3-none-any.whl", hash = "sha256:600c2f6f7c6857691b3a75fb74b22b881ab69cc992bb00296bfe5811e3470bae"}, {file = "mongomock_motor-0.0.29.tar.gz", hash = "sha256:a16c5746fad48ba5bce37aecd27729343e58e66f91652a94c0659d7f9dac4302"}, ] [[package]] name = "motor" version = "3.1.2" requires_python = ">=3.7" summary = "Non-blocking MongoDB driver for Tornado or asyncio" dependencies = [ "pymongo<5,>=4.1", ] files = [ {file = "motor-3.1.2-py3-none-any.whl", hash = "sha256:4bfc65230853ad61af447088527c1197f91c20ee957cfaea3144226907335716"}, {file = "motor-3.1.2.tar.gz", hash = "sha256:80c08477c09e70db4f85c99d484f2bafa095772f1d29b3ccb253270f9041da9a"}, ] [[package]] name = "msgpack" version = "1.0.8" requires_python = ">=3.8" summary = "MessagePack serializer" files = [ {file = "msgpack-1.0.8-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:505fe3d03856ac7d215dbe005414bc28505d26f0c128906037e66d98c4e95868"}, {file = "msgpack-1.0.8-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e6b7842518a63a9f17107eb176320960ec095a8ee3b4420b5f688e24bf50c53c"}, {file = "msgpack-1.0.8-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:376081f471a2ef24828b83a641a02c575d6103a3ad7fd7dade5486cad10ea659"}, {file = "msgpack-1.0.8-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5e390971d082dba073c05dbd56322427d3280b7cc8b53484c9377adfbae67dc2"}, {file = "msgpack-1.0.8-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00e073efcba9ea99db5acef3959efa45b52bc67b61b00823d2a1a6944bf45982"}, {file = "msgpack-1.0.8-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:82d92c773fbc6942a7a8b520d22c11cfc8fd83bba86116bfcf962c2f5c2ecdaa"}, {file = "msgpack-1.0.8-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:9ee32dcb8e531adae1f1ca568822e9b3a738369b3b686d1477cbc643c4a9c128"}, {file = "msgpack-1.0.8-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e3aa7e51d738e0ec0afbed661261513b38b3014754c9459508399baf14ae0c9d"}, {file = "msgpack-1.0.8-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:69284049d07fce531c17404fcba2bb1df472bc2dcdac642ae71a2d079d950653"}, {file = "msgpack-1.0.8-cp310-cp310-win32.whl", hash = "sha256:13577ec9e247f8741c84d06b9ece5f654920d8365a4b636ce0e44f15e07ec693"}, {file = "msgpack-1.0.8-cp310-cp310-win_amd64.whl", hash = "sha256:e532dbd6ddfe13946de050d7474e3f5fb6ec774fbb1a188aaf469b08cf04189a"}, {file = "msgpack-1.0.8-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9517004e21664f2b5a5fd6333b0731b9cf0817403a941b393d89a2f1dc2bd836"}, {file = "msgpack-1.0.8-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d16a786905034e7e34098634b184a7d81f91d4c3d246edc6bd7aefb2fd8ea6ad"}, {file = "msgpack-1.0.8-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e2872993e209f7ed04d963e4b4fbae72d034844ec66bc4ca403329db2074377b"}, {file = "msgpack-1.0.8-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c330eace3dd100bdb54b5653b966de7f51c26ec4a7d4e87132d9b4f738220ba"}, {file = "msgpack-1.0.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:83b5c044f3eff2a6534768ccfd50425939e7a8b5cf9a7261c385de1e20dcfc85"}, {file = "msgpack-1.0.8-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1876b0b653a808fcd50123b953af170c535027bf1d053b59790eebb0aeb38950"}, {file = "msgpack-1.0.8-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:dfe1f0f0ed5785c187144c46a292b8c34c1295c01da12e10ccddfc16def4448a"}, {file = "msgpack-1.0.8-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:3528807cbbb7f315bb81959d5961855e7ba52aa60a3097151cb21956fbc7502b"}, {file = "msgpack-1.0.8-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e2f879ab92ce502a1e65fce390eab619774dda6a6ff719718069ac94084098ce"}, {file = "msgpack-1.0.8-cp311-cp311-win32.whl", hash = "sha256:26ee97a8261e6e35885c2ecd2fd4a6d38252246f94a2aec23665a4e66d066305"}, {file = "msgpack-1.0.8-cp311-cp311-win_amd64.whl", hash = "sha256:eadb9f826c138e6cf3c49d6f8de88225a3c0ab181a9b4ba792e006e5292d150e"}, {file = "msgpack-1.0.8-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:114be227f5213ef8b215c22dde19532f5da9652e56e8ce969bf0a26d7c419fee"}, {file = "msgpack-1.0.8-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d661dc4785affa9d0edfdd1e59ec056a58b3dbb9f196fa43587f3ddac654ac7b"}, {file = "msgpack-1.0.8-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d56fd9f1f1cdc8227d7b7918f55091349741904d9520c65f0139a9755952c9e8"}, {file = "msgpack-1.0.8-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0726c282d188e204281ebd8de31724b7d749adebc086873a59efb8cf7ae27df3"}, {file = "msgpack-1.0.8-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8db8e423192303ed77cff4dce3a4b88dbfaf43979d280181558af5e2c3c71afc"}, {file = "msgpack-1.0.8-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:99881222f4a8c2f641f25703963a5cefb076adffd959e0558dc9f803a52d6a58"}, {file = "msgpack-1.0.8-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b5505774ea2a73a86ea176e8a9a4a7c8bf5d521050f0f6f8426afe798689243f"}, {file = "msgpack-1.0.8-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:ef254a06bcea461e65ff0373d8a0dd1ed3aa004af48839f002a0c994a6f72d04"}, {file = "msgpack-1.0.8-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:e1dd7839443592d00e96db831eddb4111a2a81a46b028f0facd60a09ebbdd543"}, {file = "msgpack-1.0.8-cp312-cp312-win32.whl", hash = "sha256:64d0fcd436c5683fdd7c907eeae5e2cbb5eb872fafbc03a43609d7941840995c"}, {file = "msgpack-1.0.8-cp312-cp312-win_amd64.whl", hash = "sha256:74398a4cf19de42e1498368c36eed45d9528f5fd0155241e82c4082b7e16cffd"}, {file = "msgpack-1.0.8-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:0ceea77719d45c839fd73abcb190b8390412a890df2f83fb8cf49b2a4b5c2f40"}, {file = "msgpack-1.0.8-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1ab0bbcd4d1f7b6991ee7c753655b481c50084294218de69365f8f1970d4c151"}, {file = "msgpack-1.0.8-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:1cce488457370ffd1f953846f82323cb6b2ad2190987cd4d70b2713e17268d24"}, {file = "msgpack-1.0.8-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3923a1778f7e5ef31865893fdca12a8d7dc03a44b33e2a5f3295416314c09f5d"}, {file = "msgpack-1.0.8-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a22e47578b30a3e199ab067a4d43d790249b3c0587d9a771921f86250c8435db"}, {file = "msgpack-1.0.8-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bd739c9251d01e0279ce729e37b39d49a08c0420d3fee7f2a4968c0576678f77"}, {file = "msgpack-1.0.8-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:d3420522057ebab1728b21ad473aa950026d07cb09da41103f8e597dfbfaeb13"}, {file = "msgpack-1.0.8-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:5845fdf5e5d5b78a49b826fcdc0eb2e2aa7191980e3d2cfd2a30303a74f212e2"}, {file = "msgpack-1.0.8-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6a0e76621f6e1f908ae52860bdcb58e1ca85231a9b0545e64509c931dd34275a"}, {file = "msgpack-1.0.8-cp38-cp38-win32.whl", hash = "sha256:374a8e88ddab84b9ada695d255679fb99c53513c0a51778796fcf0944d6c789c"}, {file = "msgpack-1.0.8-cp38-cp38-win_amd64.whl", hash = "sha256:f3709997b228685fe53e8c433e2df9f0cdb5f4542bd5114ed17ac3c0129b0480"}, {file = "msgpack-1.0.8-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:f51bab98d52739c50c56658cc303f190785f9a2cd97b823357e7aeae54c8f68a"}, {file = "msgpack-1.0.8-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:73ee792784d48aa338bba28063e19a27e8d989344f34aad14ea6e1b9bd83f596"}, {file = "msgpack-1.0.8-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f9904e24646570539a8950400602d66d2b2c492b9010ea7e965025cb71d0c86d"}, {file = "msgpack-1.0.8-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e75753aeda0ddc4c28dce4c32ba2f6ec30b1b02f6c0b14e547841ba5b24f753f"}, {file = "msgpack-1.0.8-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5dbf059fb4b7c240c873c1245ee112505be27497e90f7c6591261c7d3c3a8228"}, {file = "msgpack-1.0.8-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4916727e31c28be8beaf11cf117d6f6f188dcc36daae4e851fee88646f5b6b18"}, {file = "msgpack-1.0.8-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:7938111ed1358f536daf311be244f34df7bf3cdedb3ed883787aca97778b28d8"}, {file = "msgpack-1.0.8-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:493c5c5e44b06d6c9268ce21b302c9ca055c1fd3484c25ba41d34476c76ee746"}, {file = "msgpack-1.0.8-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5fbb160554e319f7b22ecf530a80a3ff496d38e8e07ae763b9e82fadfe96f273"}, {file = "msgpack-1.0.8-cp39-cp39-win32.whl", hash = "sha256:f9af38a89b6a5c04b7d18c492c8ccf2aee7048aff1ce8437c4683bb5a1df893d"}, {file = "msgpack-1.0.8-cp39-cp39-win_amd64.whl", hash = "sha256:ed59dd52075f8fc91da6053b12e8c89e37aa043f8986efd89e61fae69dc1b011"}, {file = "msgpack-1.0.8.tar.gz", hash = "sha256:95c02b0e27e706e48d0e5426d1710ca78e0f0628d6e89d5b5a5b91a5f12274f3"}, ] [[package]] name = "msgspec" version = "0.18.6" requires_python = ">=3.8" summary = "A fast serialization and validation library, with builtin support for JSON, MessagePack, YAML, and TOML." files = [ {file = "msgspec-0.18.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:77f30b0234eceeff0f651119b9821ce80949b4d667ad38f3bfed0d0ebf9d6d8f"}, {file = "msgspec-0.18.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1a76b60e501b3932782a9da039bd1cd552b7d8dec54ce38332b87136c64852dd"}, {file = "msgspec-0.18.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:06acbd6edf175bee0e36295d6b0302c6de3aaf61246b46f9549ca0041a9d7177"}, {file = "msgspec-0.18.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40a4df891676d9c28a67c2cc39947c33de516335680d1316a89e8f7218660410"}, {file = "msgspec-0.18.6-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:a6896f4cd5b4b7d688018805520769a8446df911eb93b421c6c68155cdf9dd5a"}, {file = "msgspec-0.18.6-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:3ac4dd63fd5309dd42a8c8c36c1563531069152be7819518be0a9d03be9788e4"}, {file = "msgspec-0.18.6-cp310-cp310-win_amd64.whl", hash = "sha256:fda4c357145cf0b760000c4ad597e19b53adf01382b711f281720a10a0fe72b7"}, {file = "msgspec-0.18.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e77e56ffe2701e83a96e35770c6adb655ffc074d530018d1b584a8e635b4f36f"}, {file = "msgspec-0.18.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d5351afb216b743df4b6b147691523697ff3a2fc5f3d54f771e91219f5c23aaa"}, {file = "msgspec-0.18.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c3232fabacef86fe8323cecbe99abbc5c02f7698e3f5f2e248e3480b66a3596b"}, {file = "msgspec-0.18.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e3b524df6ea9998bbc99ea6ee4d0276a101bcc1aa8d14887bb823914d9f60d07"}, {file = "msgspec-0.18.6-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:37f67c1d81272131895bb20d388dd8d341390acd0e192a55ab02d4d6468b434c"}, {file = "msgspec-0.18.6-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d0feb7a03d971c1c0353de1a8fe30bb6579c2dc5ccf29b5f7c7ab01172010492"}, {file = "msgspec-0.18.6-cp311-cp311-win_amd64.whl", hash = "sha256:41cf758d3f40428c235c0f27bc6f322d43063bc32da7b9643e3f805c21ed57b4"}, {file = "msgspec-0.18.6-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d86f5071fe33e19500920333c11e2267a31942d18fed4d9de5bc2fbab267d28c"}, {file = "msgspec-0.18.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce13981bfa06f5eb126a3a5a38b1976bddb49a36e4f46d8e6edecf33ccf11df1"}, {file = "msgspec-0.18.6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e97dec6932ad5e3ee1e3c14718638ba333befc45e0661caa57033cd4cc489466"}, {file = "msgspec-0.18.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad237100393f637b297926cae1868b0d500f764ccd2f0623a380e2bcfb2809ca"}, {file = "msgspec-0.18.6-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:db1d8626748fa5d29bbd15da58b2d73af25b10aa98abf85aab8028119188ed57"}, {file = "msgspec-0.18.6-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:d70cb3d00d9f4de14d0b31d38dfe60c88ae16f3182988246a9861259c6722af6"}, {file = "msgspec-0.18.6-cp312-cp312-win_amd64.whl", hash = "sha256:1003c20bfe9c6114cc16ea5db9c5466e49fae3d7f5e2e59cb70693190ad34da0"}, {file = "msgspec-0.18.6-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f7d9faed6dfff654a9ca7d9b0068456517f63dbc3aa704a527f493b9200b210a"}, {file = "msgspec-0.18.6-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:9da21f804c1a1471f26d32b5d9bc0480450ea77fbb8d9db431463ab64aaac2cf"}, {file = "msgspec-0.18.6-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:46eb2f6b22b0e61c137e65795b97dc515860bf6ec761d8fb65fdb62aa094ba61"}, {file = "msgspec-0.18.6-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c8355b55c80ac3e04885d72db515817d9fbb0def3bab936bba104e99ad22cf46"}, {file = "msgspec-0.18.6-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:9080eb12b8f59e177bd1eb5c21e24dd2ba2fa88a1dbc9a98e05ad7779b54c681"}, {file = "msgspec-0.18.6-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:cc001cf39becf8d2dcd3f413a4797c55009b3a3cdbf78a8bf5a7ca8fdb76032c"}, {file = "msgspec-0.18.6-cp38-cp38-win_amd64.whl", hash = "sha256:fac5834e14ac4da1fca373753e0c4ec9c8069d1fe5f534fa5208453b6065d5be"}, {file = "msgspec-0.18.6-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:974d3520fcc6b824a6dedbdf2b411df31a73e6e7414301abac62e6b8d03791b4"}, {file = "msgspec-0.18.6-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:fd62e5818731a66aaa8e9b0a1e5543dc979a46278da01e85c3c9a1a4f047ef7e"}, {file = "msgspec-0.18.6-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7481355a1adcf1f08dedd9311193c674ffb8bf7b79314b4314752b89a2cf7f1c"}, {file = "msgspec-0.18.6-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6aa85198f8f154cf35d6f979998f6dadd3dc46a8a8c714632f53f5d65b315c07"}, {file = "msgspec-0.18.6-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0e24539b25c85c8f0597274f11061c102ad6b0c56af053373ba4629772b407be"}, {file = "msgspec-0.18.6-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c61ee4d3be03ea9cd089f7c8e36158786cd06e51fbb62529276452bbf2d52ece"}, {file = "msgspec-0.18.6-cp39-cp39-win_amd64.whl", hash = "sha256:b5c390b0b0b7da879520d4ae26044d74aeee5144f83087eb7842ba59c02bc090"}, {file = "msgspec-0.18.6.tar.gz", hash = "sha256:a59fc3b4fcdb972d09138cb516dbde600c99d07c38fd9372a6ef500d2d031b4e"}, ] [[package]] name = "mypy" version = "1.11.1" requires_python = ">=3.8" summary = "Optional static typing for Python" dependencies = [ "mypy-extensions>=1.0.0", "tomli>=1.1.0; python_version < \"3.11\"", "typing-extensions>=4.6.0", ] files = [ {file = "mypy-1.11.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a32fc80b63de4b5b3e65f4be82b4cfa362a46702672aa6a0f443b4689af7008c"}, {file = "mypy-1.11.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c1952f5ea8a5a959b05ed5f16452fddadbaae48b5d39235ab4c3fc444d5fd411"}, {file = "mypy-1.11.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e1e30dc3bfa4e157e53c1d17a0dad20f89dc433393e7702b813c10e200843b03"}, {file = "mypy-1.11.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:2c63350af88f43a66d3dfeeeb8d77af34a4f07d760b9eb3a8697f0386c7590b4"}, {file = "mypy-1.11.1-cp310-cp310-win_amd64.whl", hash = "sha256:a831671bad47186603872a3abc19634f3011d7f83b083762c942442d51c58d58"}, {file = "mypy-1.11.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7b6343d338390bb946d449677726edf60102a1c96079b4f002dedff375953fc5"}, {file = "mypy-1.11.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e4fe9f4e5e521b458d8feb52547f4bade7ef8c93238dfb5bbc790d9ff2d770ca"}, {file = "mypy-1.11.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:886c9dbecc87b9516eff294541bf7f3655722bf22bb898ee06985cd7269898de"}, {file = "mypy-1.11.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fca4a60e1dd9fd0193ae0067eaeeb962f2d79e0d9f0f66223a0682f26ffcc809"}, {file = "mypy-1.11.1-cp311-cp311-win_amd64.whl", hash = "sha256:0bd53faf56de9643336aeea1c925012837432b5faf1701ccca7fde70166ccf72"}, {file = "mypy-1.11.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f39918a50f74dc5969807dcfaecafa804fa7f90c9d60506835036cc1bc891dc8"}, {file = "mypy-1.11.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0bc71d1fb27a428139dd78621953effe0d208aed9857cb08d002280b0422003a"}, {file = "mypy-1.11.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b868d3bcff720dd7217c383474008ddabaf048fad8d78ed948bb4b624870a417"}, {file = "mypy-1.11.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a707ec1527ffcdd1c784d0924bf5cb15cd7f22683b919668a04d2b9c34549d2e"}, {file = "mypy-1.11.1-cp312-cp312-win_amd64.whl", hash = "sha256:64f4a90e3ea07f590c5bcf9029035cf0efeae5ba8be511a8caada1a4893f5525"}, {file = "mypy-1.11.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:749fd3213916f1751fff995fccf20c6195cae941dc968f3aaadf9bb4e430e5a2"}, {file = "mypy-1.11.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b639dce63a0b19085213ec5fdd8cffd1d81988f47a2dec7100e93564f3e8fb3b"}, {file = "mypy-1.11.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4c956b49c5d865394d62941b109728c5c596a415e9c5b2be663dd26a1ff07bc0"}, {file = "mypy-1.11.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:45df906e8b6804ef4b666af29a87ad9f5921aad091c79cc38e12198e220beabd"}, {file = "mypy-1.11.1-cp38-cp38-win_amd64.whl", hash = "sha256:d44be7551689d9d47b7abc27c71257adfdb53f03880841a5db15ddb22dc63edb"}, {file = "mypy-1.11.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2684d3f693073ab89d76da8e3921883019ea8a3ec20fa5d8ecca6a2db4c54bbe"}, {file = "mypy-1.11.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:79c07eb282cb457473add5052b63925e5cc97dfab9812ee65a7c7ab5e3cb551c"}, {file = "mypy-1.11.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:11965c2f571ded6239977b14deebd3f4c3abd9a92398712d6da3a772974fad69"}, {file = "mypy-1.11.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a2b43895a0f8154df6519706d9bca8280cda52d3d9d1514b2d9c3e26792a0b74"}, {file = "mypy-1.11.1-cp39-cp39-win_amd64.whl", hash = "sha256:1a81cf05975fd61aec5ae16501a091cfb9f605dc3e3c878c0da32f250b74760b"}, {file = "mypy-1.11.1-py3-none-any.whl", hash = "sha256:0624bdb940255d2dd24e829d99a13cfeb72e4e9031f9492148f410ed30bcab54"}, {file = "mypy-1.11.1.tar.gz", hash = "sha256:f404a0b069709f18bbdb702eb3dcfe51910602995de00bd39cea3050b5772d08"}, ] [[package]] name = "mypy-extensions" version = "1.0.0" requires_python = ">=3.5" summary = "Type system extensions for programs checked with the mypy type checker." files = [ {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, ] [[package]] name = "natsort" version = "8.4.0" requires_python = ">=3.7" summary = "Simple yet flexible natural sorting in Python." files = [ {file = "natsort-8.4.0-py3-none-any.whl", hash = "sha256:4732914fb471f56b5cce04d7bae6f164a592c7712e1c85f9ef585e197299521c"}, {file = "natsort-8.4.0.tar.gz", hash = "sha256:45312c4a0e5507593da193dedd04abb1469253b601ecaf63445ad80f0a1ea581"}, ] [[package]] name = "nodeenv" version = "1.8.0" requires_python = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*" summary = "Node.js virtual environment builder" dependencies = [ "setuptools", ] files = [ {file = "nodeenv-1.8.0-py2.py3-none-any.whl", hash = "sha256:df865724bb3c3adc86b3876fa209771517b0cfe596beff01a92700e0e8be4cec"}, {file = "nodeenv-1.8.0.tar.gz", hash = "sha256:d51e0c37e64fbf47d017feac3145cdbb58836d7eee8c6f6d3b6880c5456227d2"}, ] [[package]] name = "odmantic" version = "0.9.2" requires_python = ">=3.7" summary = "ODMantic, an AsyncIO MongoDB Object Document Mapper for Python using type hints " dependencies = [ "importlib-metadata<5,>=1; python_version < \"3.8\"", "motor<3.2.0,>=2.1.0", "pydantic!=1.7,!=1.7.1,!=1.7.2,!=1.7.3,!=1.8,!=1.8.1,>=1.6.2", "pymongo<5.0.0,>=3.11.0", "typing-extensions>=4.2.0; python_version < \"3.11\"", ] files = [ {file = "odmantic-0.9.2-py3-none-any.whl", hash = "sha256:a82f4fe6a6face24cf0cd0738c9bb32564219cb5a5ed6b0a58e92a4c2048e4d8"}, {file = "odmantic-0.9.2.tar.gz", hash = "sha256:9780087e1bc2afbd0c1f16b2d18137889dbe7e0df12af0762d6b6b17dadd36be"}, ] [[package]] name = "packaging" version = "24.0" requires_python = ">=3.7" summary = "Core utilities for Python packages" files = [ {file = "packaging-24.0-py3-none-any.whl", hash = "sha256:2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5"}, {file = "packaging-24.0.tar.gz", hash = "sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9"}, ] [[package]] name = "pathspec" version = "0.12.1" requires_python = ">=3.8" summary = "Utility library for gitignore style pattern matching of file paths." files = [ {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"}, {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"}, ] [[package]] name = "platformdirs" version = "4.2.1" requires_python = ">=3.8" summary = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." files = [ {file = "platformdirs-4.2.1-py3-none-any.whl", hash = "sha256:17d5a1161b3fd67b390023cb2d3b026bbd40abde6fdb052dfbd3a29c3ba22ee1"}, {file = "platformdirs-4.2.1.tar.gz", hash = "sha256:031cd18d4ec63ec53e82dceaac0417d218a6863f7745dfcc9efe7793b7039bdf"}, ] [[package]] name = "pluggy" version = "1.5.0" requires_python = ">=3.8" summary = "plugin and hook calling mechanisms for python" files = [ {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"}, {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"}, ] [[package]] name = "pre-commit" version = "3.5.0" requires_python = ">=3.8" summary = "A framework for managing and maintaining multi-language pre-commit hooks." dependencies = [ "cfgv>=2.0.0", "identify>=1.0.0", "nodeenv>=0.11.1", "pyyaml>=5.1", "virtualenv>=20.10.0", ] files = [ {file = "pre_commit-3.5.0-py2.py3-none-any.whl", hash = "sha256:841dc9aef25daba9a0238cd27984041fa0467b4199fc4852e27950664919f660"}, {file = "pre_commit-3.5.0.tar.gz", hash = "sha256:5804465c675b659b0862f07907f96295d490822a450c4c40e747d0b1c6ebcb32"}, ] [[package]] name = "pydantic" version = "2.7.1" requires_python = ">=3.8" summary = "Data validation using Python type hints" dependencies = [ "annotated-types>=0.4.0", "pydantic-core==2.18.2", "typing-extensions>=4.6.1", ] files = [ {file = "pydantic-2.7.1-py3-none-any.whl", hash = "sha256:e029badca45266732a9a79898a15ae2e8b14840b1eabbb25844be28f0b33f3d5"}, {file = "pydantic-2.7.1.tar.gz", hash = "sha256:e9dbb5eada8abe4d9ae5f46b9939aead650cd2b68f249bb3a8139dbe125803cc"}, ] [[package]] name = "pydantic-core" version = "2.18.2" requires_python = ">=3.8" summary = "Core functionality for Pydantic validation and serialization" dependencies = [ "typing-extensions!=4.7.0,>=4.6.0", ] files = [ {file = "pydantic_core-2.18.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:9e08e867b306f525802df7cd16c44ff5ebbe747ff0ca6cf3fde7f36c05a59a81"}, {file = "pydantic_core-2.18.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f0a21cbaa69900cbe1a2e7cad2aa74ac3cf21b10c3efb0fa0b80305274c0e8a2"}, {file = "pydantic_core-2.18.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0680b1f1f11fda801397de52c36ce38ef1c1dc841a0927a94f226dea29c3ae3d"}, {file = "pydantic_core-2.18.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:95b9d5e72481d3780ba3442eac863eae92ae43a5f3adb5b4d0a1de89d42bb250"}, {file = "pydantic_core-2.18.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c4fcf5cd9c4b655ad666ca332b9a081112cd7a58a8b5a6ca7a3104bc950f2038"}, {file = "pydantic_core-2.18.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b5155ff768083cb1d62f3e143b49a8a3432e6789a3abee8acd005c3c7af1c74"}, {file = "pydantic_core-2.18.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:553ef617b6836fc7e4df130bb851e32fe357ce36336d897fd6646d6058d980af"}, {file = "pydantic_core-2.18.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b89ed9eb7d616ef5714e5590e6cf7f23b02d0d539767d33561e3675d6f9e3857"}, {file = "pydantic_core-2.18.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:75f7e9488238e920ab6204399ded280dc4c307d034f3924cd7f90a38b1829563"}, {file = "pydantic_core-2.18.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:ef26c9e94a8c04a1b2924149a9cb081836913818e55681722d7f29af88fe7b38"}, {file = "pydantic_core-2.18.2-cp310-none-win32.whl", hash = "sha256:182245ff6b0039e82b6bb585ed55a64d7c81c560715d1bad0cbad6dfa07b4027"}, {file = "pydantic_core-2.18.2-cp310-none-win_amd64.whl", hash = "sha256:e23ec367a948b6d812301afc1b13f8094ab7b2c280af66ef450efc357d2ae543"}, {file = "pydantic_core-2.18.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:219da3f096d50a157f33645a1cf31c0ad1fe829a92181dd1311022f986e5fbe3"}, {file = "pydantic_core-2.18.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:cc1cfd88a64e012b74e94cd00bbe0f9c6df57049c97f02bb07d39e9c852e19a4"}, {file = "pydantic_core-2.18.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:05b7133a6e6aeb8df37d6f413f7705a37ab4031597f64ab56384c94d98fa0e90"}, {file = "pydantic_core-2.18.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:224c421235f6102e8737032483f43c1a8cfb1d2f45740c44166219599358c2cd"}, {file = "pydantic_core-2.18.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b14d82cdb934e99dda6d9d60dc84a24379820176cc4a0d123f88df319ae9c150"}, {file = "pydantic_core-2.18.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2728b01246a3bba6de144f9e3115b532ee44bd6cf39795194fb75491824a1413"}, {file = "pydantic_core-2.18.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:470b94480bb5ee929f5acba6995251ada5e059a5ef3e0dfc63cca287283ebfa6"}, {file = "pydantic_core-2.18.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:997abc4df705d1295a42f95b4eec4950a37ad8ae46d913caeee117b6b198811c"}, {file = "pydantic_core-2.18.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:75250dbc5290e3f1a0f4618db35e51a165186f9034eff158f3d490b3fed9f8a0"}, {file = "pydantic_core-2.18.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:4456f2dca97c425231d7315737d45239b2b51a50dc2b6f0c2bb181fce6207664"}, {file = "pydantic_core-2.18.2-cp311-none-win32.whl", hash = "sha256:269322dcc3d8bdb69f054681edff86276b2ff972447863cf34c8b860f5188e2e"}, {file = "pydantic_core-2.18.2-cp311-none-win_amd64.whl", hash = "sha256:800d60565aec896f25bc3cfa56d2277d52d5182af08162f7954f938c06dc4ee3"}, {file = "pydantic_core-2.18.2-cp311-none-win_arm64.whl", hash = "sha256:1404c69d6a676245199767ba4f633cce5f4ad4181f9d0ccb0577e1f66cf4c46d"}, {file = "pydantic_core-2.18.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:fb2bd7be70c0fe4dfd32c951bc813d9fe6ebcbfdd15a07527796c8204bd36242"}, {file = "pydantic_core-2.18.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6132dd3bd52838acddca05a72aafb6eab6536aa145e923bb50f45e78b7251043"}, {file = "pydantic_core-2.18.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7d904828195733c183d20a54230c0df0eb46ec746ea1a666730787353e87182"}, {file = "pydantic_core-2.18.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c9bd70772c720142be1020eac55f8143a34ec9f82d75a8e7a07852023e46617f"}, {file = "pydantic_core-2.18.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2b8ed04b3582771764538f7ee7001b02e1170223cf9b75dff0bc698fadb00cf3"}, {file = "pydantic_core-2.18.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e6dac87ddb34aaec85f873d737e9d06a3555a1cc1a8e0c44b7f8d5daeb89d86f"}, {file = "pydantic_core-2.18.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ca4ae5a27ad7a4ee5170aebce1574b375de390bc01284f87b18d43a3984df72"}, {file = "pydantic_core-2.18.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:886eec03591b7cf058467a70a87733b35f44707bd86cf64a615584fd72488b7c"}, {file = "pydantic_core-2.18.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ca7b0c1f1c983e064caa85f3792dd2fe3526b3505378874afa84baf662e12241"}, {file = "pydantic_core-2.18.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4b4356d3538c3649337df4074e81b85f0616b79731fe22dd11b99499b2ebbdf3"}, {file = "pydantic_core-2.18.2-cp312-none-win32.whl", hash = "sha256:8b172601454f2d7701121bbec3425dd71efcb787a027edf49724c9cefc14c038"}, {file = "pydantic_core-2.18.2-cp312-none-win_amd64.whl", hash = "sha256:b1bd7e47b1558ea872bd16c8502c414f9e90dcf12f1395129d7bb42a09a95438"}, {file = "pydantic_core-2.18.2-cp312-none-win_arm64.whl", hash = "sha256:98758d627ff397e752bc339272c14c98199c613f922d4a384ddc07526c86a2ec"}, {file = "pydantic_core-2.18.2-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:9fdad8e35f278b2c3eb77cbdc5c0a49dada440657bf738d6905ce106dc1de439"}, {file = "pydantic_core-2.18.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:1d90c3265ae107f91a4f279f4d6f6f1d4907ac76c6868b27dc7fb33688cfb347"}, {file = "pydantic_core-2.18.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:390193c770399861d8df9670fb0d1874f330c79caaca4642332df7c682bf6b91"}, {file = "pydantic_core-2.18.2-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:82d5d4d78e4448683cb467897fe24e2b74bb7b973a541ea1dcfec1d3cbce39fb"}, {file = "pydantic_core-2.18.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4774f3184d2ef3e14e8693194f661dea5a4d6ca4e3dc8e39786d33a94865cefd"}, {file = "pydantic_core-2.18.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d4d938ec0adf5167cb335acb25a4ee69a8107e4984f8fbd2e897021d9e4ca21b"}, {file = "pydantic_core-2.18.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e0e8b1be28239fc64a88a8189d1df7fad8be8c1ae47fcc33e43d4be15f99cc70"}, {file = "pydantic_core-2.18.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:868649da93e5a3d5eacc2b5b3b9235c98ccdbfd443832f31e075f54419e1b96b"}, {file = "pydantic_core-2.18.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:78363590ef93d5d226ba21a90a03ea89a20738ee5b7da83d771d283fd8a56761"}, {file = "pydantic_core-2.18.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:852e966fbd035a6468fc0a3496589b45e2208ec7ca95c26470a54daed82a0788"}, {file = "pydantic_core-2.18.2-cp38-none-win32.whl", hash = "sha256:6a46e22a707e7ad4484ac9ee9f290f9d501df45954184e23fc29408dfad61350"}, {file = "pydantic_core-2.18.2-cp38-none-win_amd64.whl", hash = "sha256:d91cb5ea8b11607cc757675051f61b3d93f15eca3cefb3e6c704a5d6e8440f4e"}, {file = "pydantic_core-2.18.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:ae0a8a797a5e56c053610fa7be147993fe50960fa43609ff2a9552b0e07013e8"}, {file = "pydantic_core-2.18.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:042473b6280246b1dbf530559246f6842b56119c2926d1e52b631bdc46075f2a"}, {file = "pydantic_core-2.18.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a388a77e629b9ec814c1b1e6b3b595fe521d2cdc625fcca26fbc2d44c816804"}, {file = "pydantic_core-2.18.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e25add29b8f3b233ae90ccef2d902d0ae0432eb0d45370fe315d1a5cf231004b"}, {file = "pydantic_core-2.18.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f459a5ce8434614dfd39bbebf1041952ae01da6bed9855008cb33b875cb024c0"}, {file = "pydantic_core-2.18.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:eff2de745698eb46eeb51193a9f41d67d834d50e424aef27df2fcdee1b153845"}, {file = "pydantic_core-2.18.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8309f67285bdfe65c372ea3722b7a5642680f3dba538566340a9d36e920b5f0"}, {file = "pydantic_core-2.18.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f93a8a2e3938ff656a7c1bc57193b1319960ac015b6e87d76c76bf14fe0244b4"}, {file = "pydantic_core-2.18.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:22057013c8c1e272eb8d0eebc796701167d8377441ec894a8fed1af64a0bf399"}, {file = "pydantic_core-2.18.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:cfeecd1ac6cc1fb2692c3d5110781c965aabd4ec5d32799773ca7b1456ac636b"}, {file = "pydantic_core-2.18.2-cp39-none-win32.whl", hash = "sha256:0d69b4c2f6bb3e130dba60d34c0845ba31b69babdd3f78f7c0c8fae5021a253e"}, {file = "pydantic_core-2.18.2-cp39-none-win_amd64.whl", hash = "sha256:d9319e499827271b09b4e411905b24a426b8fb69464dfa1696258f53a3334641"}, {file = "pydantic_core-2.18.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:a1874c6dd4113308bd0eb568418e6114b252afe44319ead2b4081e9b9521fe75"}, {file = "pydantic_core-2.18.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:ccdd111c03bfd3666bd2472b674c6899550e09e9f298954cfc896ab92b5b0e6d"}, {file = "pydantic_core-2.18.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e18609ceaa6eed63753037fc06ebb16041d17d28199ae5aba0052c51449650a9"}, {file = "pydantic_core-2.18.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e5c584d357c4e2baf0ff7baf44f4994be121e16a2c88918a5817331fc7599d7"}, {file = "pydantic_core-2.18.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:43f0f463cf89ace478de71a318b1b4f05ebc456a9b9300d027b4b57c1a2064fb"}, {file = "pydantic_core-2.18.2-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:e1b395e58b10b73b07b7cf740d728dd4ff9365ac46c18751bf8b3d8cca8f625a"}, {file = "pydantic_core-2.18.2-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:0098300eebb1c837271d3d1a2cd2911e7c11b396eac9661655ee524a7f10587b"}, {file = "pydantic_core-2.18.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:36789b70d613fbac0a25bb07ab3d9dba4d2e38af609c020cf4d888d165ee0bf3"}, {file = "pydantic_core-2.18.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:3f9a801e7c8f1ef8718da265bba008fa121243dfe37c1cea17840b0944dfd72c"}, {file = "pydantic_core-2.18.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:3a6515ebc6e69d85502b4951d89131ca4e036078ea35533bb76327f8424531ce"}, {file = "pydantic_core-2.18.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20aca1e2298c56ececfd8ed159ae4dde2df0781988c97ef77d5c16ff4bd5b400"}, {file = "pydantic_core-2.18.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:223ee893d77a310a0391dca6df00f70bbc2f36a71a895cecd9a0e762dc37b349"}, {file = "pydantic_core-2.18.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2334ce8c673ee93a1d6a65bd90327588387ba073c17e61bf19b4fd97d688d63c"}, {file = "pydantic_core-2.18.2-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:cbca948f2d14b09d20268cda7b0367723d79063f26c4ffc523af9042cad95592"}, {file = "pydantic_core-2.18.2-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:b3ef08e20ec49e02d5c6717a91bb5af9b20f1805583cb0adfe9ba2c6b505b5ae"}, {file = "pydantic_core-2.18.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:c6fdc8627910eed0c01aed6a390a252fe3ea6d472ee70fdde56273f198938374"}, {file = "pydantic_core-2.18.2.tar.gz", hash = "sha256:2e29d20810dfc3043ee13ac7d9e25105799817683348823f305ab3f349b9386e"}, ] [[package]] name = "pydantic" version = "2.7.1" extras = ["email"] requires_python = ">=3.8" summary = "Data validation using Python type hints" dependencies = [ "email-validator>=2.0.0", "pydantic==2.7.1", ] files = [ {file = "pydantic-2.7.1-py3-none-any.whl", hash = "sha256:e029badca45266732a9a79898a15ae2e8b14840b1eabbb25844be28f0b33f3d5"}, {file = "pydantic-2.7.1.tar.gz", hash = "sha256:e9dbb5eada8abe4d9ae5f46b9939aead650cd2b68f249bb3a8139dbe125803cc"}, ] [[package]] name = "pygments" version = "2.17.2" requires_python = ">=3.7" summary = "Pygments is a syntax highlighting package written in Python." files = [ {file = "pygments-2.17.2-py3-none-any.whl", hash = "sha256:b27c2826c47d0f3219f29554824c30c5e8945175d888647acd804ddd04af846c"}, {file = "pygments-2.17.2.tar.gz", hash = "sha256:da46cec9fd2de5be3a8a784f434e4c4ab670b4ff54d605c4c2717e9d49c4c367"}, ] [[package]] name = "pymongo" version = "4.7.1" requires_python = ">=3.7" summary = "Python driver for MongoDB <http://www.mongodb.org>" dependencies = [ "dnspython<3.0.0,>=1.16.0", ] files = [ {file = "pymongo-4.7.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f8822614975038e0cece47d12e7634a79c2ee590a0ae78ae64c37b9c6610a14c"}, {file = "pymongo-4.7.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:57b5b485ef89270ed2e603814f43f0fdd9b8ba5d4039124d90878cdc2327000c"}, {file = "pymongo-4.7.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9e99dac3c7c2cb498937cc1767361851099da38861e921113318c87d71e3d127"}, {file = "pymongo-4.7.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:253ed8fd6e7f4b2a1caa89e6b287b9e04f42613319ee1e1240c2db2afe1637e7"}, {file = "pymongo-4.7.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8cee62188127a126f59ea45d3981868a5e35343be4ef4ad8712eaf42be37a00b"}, {file = "pymongo-4.7.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:31ed8ba3da0366346264604b3a443f5a4232cab5ed45f520bead6184cf0851a1"}, {file = "pymongo-4.7.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:887d043ecc0c7d5591925bbc7abb67caf21c94d6e6e5d442cb49eb5d9d8ee76b"}, {file = "pymongo-4.7.1-cp310-cp310-win32.whl", hash = "sha256:bfd5c7e5bb87171a5296fa32205adb50b27704a612036ec4395c3cd316fc0e91"}, {file = "pymongo-4.7.1-cp310-cp310-win_amd64.whl", hash = "sha256:5ae1aeeb405c29885266666dc7115792d647ed68cfdb6ed02e2e211d12f2e1c8"}, {file = "pymongo-4.7.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e4a63ba6813a2168ebd35ea5369f6c33f7787525986cd77668b7956acc3d2a38"}, {file = "pymongo-4.7.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:811a07bba9d35f1e34159ede632ac71dbc429b372a20004e32d6578af872db1a"}, {file = "pymongo-4.7.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4d227555be35078b53f506f6b58bd0b0e8fd4513e89e6f29e83a97efab439250"}, {file = "pymongo-4.7.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:daf35ab13b86aba7cc8c4b019882f1fa8d287a26f586ef5eaf60a5233d3eaa52"}, {file = "pymongo-4.7.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aa354933a158e57494c98b592f46d5d24d1b109e6ba05a05179cde719d9f7fd3"}, {file = "pymongo-4.7.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad360630c221aee7c0841a51851496a3ca6fdea87007098a982c1aa26e34083a"}, {file = "pymongo-4.7.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5119c66af8c4197c8757b4b7d98c443e5b127c224ac92fb657dbe2b512ae2713"}, {file = "pymongo-4.7.1-cp311-cp311-win32.whl", hash = "sha256:11f74dafde63ad2dc30c01f40b4c69d9af157f8ba5224b0c9d4de7158537266f"}, {file = "pymongo-4.7.1-cp311-cp311-win_amd64.whl", hash = "sha256:ec94d29103317aa920dae59ed385de9604cb0ef840b5b7137b5eaa7a2042580a"}, {file = "pymongo-4.7.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b8b95e2163b73d03a913efa89b0f7c5012be82efd4e9dbce8aa62010a75a277c"}, {file = "pymongo-4.7.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fb1a884b1c6aeac5ffeb8ccb696fbc242a7ae1bba36f2328c01f76fab7221b94"}, {file = "pymongo-4.7.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2ccc8dd4fe9aac18dde27c33a53271c6c90159b74c43fbdab1d33d5efc36c2f5"}, {file = "pymongo-4.7.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7247c1dc7d8eed4e24eb1dd92c4c58ebf1e5159500015652552acfdebdeed256"}, {file = "pymongo-4.7.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:45ac46f0d6bdc2baac34ced60aae27b2083170d77397330eff0ac5689ea29d38"}, {file = "pymongo-4.7.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a848249d5b4763497add62f7dd7bd0ce1538129bf42f4cb132a76d24c61bf98d"}, {file = "pymongo-4.7.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5ff6d56ca1f0cd3687a13ce90a32a8efb3cc3a53728e5ac160c4c30d10385a72"}, {file = "pymongo-4.7.1-cp312-cp312-win32.whl", hash = "sha256:e175d74c52b6c8414a4b4504a2dd42b0202d101b2eb9508a34c137357683864e"}, {file = "pymongo-4.7.1-cp312-cp312-win_amd64.whl", hash = "sha256:263c169302df636f9086b584994a51d0adfc8738fe27d7b8e2aacf46fd68b6cb"}, {file = "pymongo-4.7.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7b10603ba64af08f5af7eb9a69d6b24e3c69d91fdd48c54b95e284686c1c582d"}, {file = "pymongo-4.7.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:64b69b9cd8a6d23881a80490d575e92918f9afca43096a7d6c1013d6b3e5c75c"}, {file = "pymongo-4.7.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4c7e05454cdc5aa4702e03cad0df4205daccd6fd631bbbf0a85bbe598129a6cc"}, {file = "pymongo-4.7.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9e0a30a022ac8a9164ee5a4b761e13dbb3d10a21845f7258011e3415151fb645"}, {file = "pymongo-4.7.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:13fc201e073644acd77860d9e91ccfc27addf510563e07381cadc9a55ac3a894"}, {file = "pymongo-4.7.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4dd998e9f0f7694032c1648c7f57fccaa78903df6329b8f8ae20cfa7c4ceca34"}, {file = "pymongo-4.7.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:455f9d603ed0990a787773d5718e871300bddf585ce543baf129c9f5ca3adb02"}, {file = "pymongo-4.7.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d804eaf19a65211cc2c8c5db75be685c3f31c64cdab639794f66f13f8e258ba6"}, {file = "pymongo-4.7.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:a46c08ef0b273c415b1e8933f6739596be264ae700a4927f84e0b84e70fdf0eb"}, {file = "pymongo-4.7.1-cp38-cp38-win32.whl", hash = "sha256:58989bcb94233233a71645236b972835d4f87a6bb1b7e818d38a7e6e6d4630de"}, {file = "pymongo-4.7.1-cp38-cp38-win_amd64.whl", hash = "sha256:d63f38454a2e23c117d3ceab3b661568f2418536825787256ad24e5baaedfd27"}, {file = "pymongo-4.7.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d50969de00d3522b2c394f7e59b843871e2be4b525af92066da7f3bd02799fdc"}, {file = "pymongo-4.7.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f2a720e787c9b9b912db5bb4c3e7123ccff1352d6c3ac0cb2c7ee392cdc95c00"}, {file = "pymongo-4.7.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c808098f2cdb87d4035144e536ba5fa7709d0420c17b68e6ace5da18c38ded5f"}, {file = "pymongo-4.7.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d1829a7db720ff586aaf59c806e89e0a388548063aa844d21a570a231ad8ca87"}, {file = "pymongo-4.7.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:615c7573d7a9c4837332a673fdc5a5f214b474dd52d846bcf4cc3d011550bee1"}, {file = "pymongo-4.7.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e935712b17e7a42831022353bac91a346a792658a54e12bec907ec11695cc899"}, {file = "pymongo-4.7.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dbc32217c81d87750401fa1c2bc9450e854b23e6e30243c82d3514b8e58f39e3"}, {file = "pymongo-4.7.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5bc87db2e9563295c4e45602ab978a2fcbaba3ab89e745503b24f895cddeb755"}, {file = "pymongo-4.7.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:65c45682d5ed8c6618bde22cd6716b47a197f4ef800a025213b28d13a59e5fca"}, {file = "pymongo-4.7.1-cp39-cp39-win32.whl", hash = "sha256:67cbee427c263a4483e3249fef480788ccc16edb1a4fc330c4c6cb0cb9db94a8"}, {file = "pymongo-4.7.1-cp39-cp39-win_amd64.whl", hash = "sha256:1bd1eef70c1eda838b26397ef75c9580d7a97fd94b6324971d7f3d2ad3552e9a"}, {file = "pymongo-4.7.1.tar.gz", hash = "sha256:811c41c6227b7548afcb53e1b996c25262d837b5e5f519e2ddc2c7e59d8728a5"}, ] [[package]] name = "pyright" version = "1.1.364" requires_python = ">=3.7" summary = "Command line wrapper for pyright" dependencies = [ "nodeenv>=1.6.0", "typing-extensions>=3.7; python_version < \"3.8\"", ] files = [ {file = "pyright-1.1.364-py3-none-any.whl", hash = "sha256:865f1e02873c5dc7427c95acf53659a118574010e6fb364e27e47ec5c46a9f26"}, {file = "pyright-1.1.364.tar.gz", hash = "sha256:612a2106a4078ec57efc22b5620729e9bdf4a3c17caba013b534bd33f7d08e5a"}, ] [[package]] name = "pytest" version = "8.2.1" requires_python = ">=3.8" summary = "pytest: simple powerful testing with Python" dependencies = [ "colorama; sys_platform == \"win32\"", "exceptiongroup>=1.0.0rc8; python_version < \"3.11\"", "iniconfig", "packaging", "pluggy<2.0,>=1.5", "tomli>=1; python_version < \"3.11\"", ] files = [ {file = "pytest-8.2.1-py3-none-any.whl", hash = "sha256:faccc5d332b8c3719f40283d0d44aa5cf101cec36f88cde9ed8f2bc0538612b1"}, {file = "pytest-8.2.1.tar.gz", hash = "sha256:5046e5b46d8e4cac199c373041f26be56fdb81eb4e67dc11d4e10811fc3408fd"}, ] [[package]] name = "pytest-asyncio" version = "0.23.7" requires_python = ">=3.8" summary = "Pytest support for asyncio" dependencies = [ "pytest<9,>=7.0.0", ] files = [ {file = "pytest_asyncio-0.23.7-py3-none-any.whl", hash = "sha256:009b48127fbe44518a547bddd25611551b0e43ccdbf1e67d12479f569832c20b"}, {file = "pytest_asyncio-0.23.7.tar.gz", hash = "sha256:5f5c72948f4c49e7db4f29f2521d4031f1c27f86e57b046126654083d4770268"}, ] [[package]] name = "pytest-cov" version = "5.0.0" requires_python = ">=3.8" summary = "Pytest plugin for measuring coverage." dependencies = [ "coverage[toml]>=5.2.1", "pytest>=4.6", ] files = [ {file = "pytest-cov-5.0.0.tar.gz", hash = "sha256:5837b58e9f6ebd335b0f8060eecce69b662415b16dc503883a02f45dfeb14857"}, {file = "pytest_cov-5.0.0-py3-none-any.whl", hash = "sha256:4f0764a1219df53214206bf1feea4633c3b558a2925c8b59f144f682861ce652"}, ] [[package]] name = "python-dateutil" version = "2.9.0.post0" requires_python = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" summary = "Extensions to the standard Python datetime module" dependencies = [ "six>=1.5", ] files = [ {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, ] [[package]] name = "pytz" version = "2024.1" summary = "World timezone definitions, modern and historical" files = [ {file = "pytz-2024.1-py2.py3-none-any.whl", hash = "sha256:328171f4e3623139da4983451950b28e95ac706e13f3f2630a879749e7a8b319"}, {file = "pytz-2024.1.tar.gz", hash = "sha256:2a29735ea9c18baf14b448846bde5a48030ed267578472d8955cd0e7443a9812"}, ] [[package]] name = "pyyaml" version = "6.0.1" requires_python = ">=3.6" summary = "YAML parser and emitter for Python" files = [ {file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"}, {file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"}, {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"}, {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, {file = "PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab"}, {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"}, {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"}, {file = "PyYAML-6.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595"}, {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"}, {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, {file = "PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859"}, {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"}, {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, ] [[package]] name = "requests" version = "2.31.0" requires_python = ">=3.7" summary = "Python HTTP for Humans." dependencies = [ "certifi>=2017.4.17", "charset-normalizer<4,>=2", "idna<4,>=2.5", "urllib3<3,>=1.21.1", ] files = [ {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"}, {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"}, ] [[package]] name = "ruamel-yaml" version = "0.18.6" requires_python = ">=3.7" summary = "ruamel.yaml is a YAML parser/emitter that supports roundtrip preservation of comments, seq/map flow style, and map key order" dependencies = [ "ruamel-yaml-clib>=0.2.7; platform_python_implementation == \"CPython\" and python_version < \"3.13\"", ] files = [ {file = "ruamel.yaml-0.18.6-py3-none-any.whl", hash = "sha256:57b53ba33def16c4f3d807c0ccbc00f8a6081827e81ba2491691b76882d0c636"}, {file = "ruamel.yaml-0.18.6.tar.gz", hash = "sha256:8b27e6a217e786c6fbe5634d8f3f11bc63e0f80f6a5890f28863d9c45aac311b"}, ] [[package]] name = "ruamel-yaml-clib" version = "0.2.8" requires_python = ">=3.6" summary = "C version of reader, parser and emitter for ruamel.yaml derived from libyaml" files = [ {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:b42169467c42b692c19cf539c38d4602069d8c1505e97b86387fcf7afb766e1d"}, {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-macosx_13_0_arm64.whl", hash = "sha256:07238db9cbdf8fc1e9de2489a4f68474e70dffcb32232db7c08fa61ca0c7c462"}, {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:fff3573c2db359f091e1589c3d7c5fc2f86f5bdb6f24252c2d8e539d4e45f412"}, {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-manylinux_2_24_aarch64.whl", hash = "sha256:aa2267c6a303eb483de8d02db2871afb5c5fc15618d894300b88958f729ad74f"}, {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:840f0c7f194986a63d2c2465ca63af8ccbbc90ab1c6001b1978f05119b5e7334"}, {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:024cfe1fc7c7f4e1aff4a81e718109e13409767e4f871443cbff3dba3578203d"}, {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-win32.whl", hash = "sha256:c69212f63169ec1cfc9bb44723bf2917cbbd8f6191a00ef3410f5a7fe300722d"}, {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-win_amd64.whl", hash = "sha256:cabddb8d8ead485e255fe80429f833172b4cadf99274db39abc080e068cbcc31"}, {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:bef08cd86169d9eafb3ccb0a39edb11d8e25f3dae2b28f5c52fd997521133069"}, {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-macosx_13_0_arm64.whl", hash = "sha256:b16420e621d26fdfa949a8b4b47ade8810c56002f5389970db4ddda51dbff248"}, {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:25c515e350e5b739842fc3228d662413ef28f295791af5e5110b543cf0b57d9b"}, {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-manylinux_2_24_aarch64.whl", hash = "sha256:1707814f0d9791df063f8c19bb51b0d1278b8e9a2353abbb676c2f685dee6afe"}, {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:46d378daaac94f454b3a0e3d8d78cafd78a026b1d71443f4966c696b48a6d899"}, {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:09b055c05697b38ecacb7ac50bdab2240bfca1a0c4872b0fd309bb07dc9aa3a9"}, {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-win32.whl", hash = "sha256:53a300ed9cea38cf5a2a9b069058137c2ca1ce658a874b79baceb8f892f915a7"}, {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-win_amd64.whl", hash = "sha256:c2a72e9109ea74e511e29032f3b670835f8a59bbdc9ce692c5b4ed91ccf1eedb"}, {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:ebc06178e8821efc9692ea7544aa5644217358490145629914d8020042c24aa1"}, {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-macosx_13_0_arm64.whl", hash = "sha256:edaef1c1200c4b4cb914583150dcaa3bc30e592e907c01117c08b13a07255ec2"}, {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d176b57452ab5b7028ac47e7b3cf644bcfdc8cacfecf7e71759f7f51a59e5c92"}, {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-manylinux_2_24_aarch64.whl", hash = "sha256:1dc67314e7e1086c9fdf2680b7b6c2be1c0d8e3a8279f2e993ca2a7545fecf62"}, {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:3213ece08ea033eb159ac52ae052a4899b56ecc124bb80020d9bbceeb50258e9"}, {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:aab7fd643f71d7946f2ee58cc88c9b7bfc97debd71dcc93e03e2d174628e7e2d"}, {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-win32.whl", hash = "sha256:5c365d91c88390c8d0a8545df0b5857172824b1c604e867161e6b3d59a827eaa"}, {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-win_amd64.whl", hash = "sha256:1758ce7d8e1a29d23de54a16ae867abd370f01b5a69e1a3ba75223eaa3ca1a1b"}, {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1b617618914cb00bf5c34d4357c37aa15183fa229b24767259657746c9077615"}, {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-macosx_12_0_arm64.whl", hash = "sha256:a6a9ffd280b71ad062eae53ac1659ad86a17f59a0fdc7699fd9be40525153337"}, {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-manylinux_2_24_aarch64.whl", hash = "sha256:305889baa4043a09e5b76f8e2a51d4ffba44259f6b4c72dec8ca56207d9c6fe1"}, {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:700e4ebb569e59e16a976857c8798aee258dceac7c7d6b50cab63e080058df91"}, {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:e2b4c44b60eadec492926a7270abb100ef9f72798e18743939bdbf037aab8c28"}, {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:e79e5db08739731b0ce4850bed599235d601701d5694c36570a99a0c5ca41a9d"}, {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-win32.whl", hash = "sha256:955eae71ac26c1ab35924203fda6220f84dce57d6d7884f189743e2abe3a9fbe"}, {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-win_amd64.whl", hash = "sha256:56f4252222c067b4ce51ae12cbac231bce32aee1d33fbfc9d17e5b8d6966c312"}, {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:03d1162b6d1df1caa3a4bd27aa51ce17c9afc2046c31b0ad60a0a96ec22f8001"}, {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:bba64af9fa9cebe325a62fa398760f5c7206b215201b0ec825005f1b18b9bccf"}, {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-manylinux_2_24_aarch64.whl", hash = "sha256:a1a45e0bb052edf6a1d3a93baef85319733a888363938e1fc9924cb00c8df24c"}, {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:da09ad1c359a728e112d60116f626cc9f29730ff3e0e7db72b9a2dbc2e4beed5"}, {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:184565012b60405d93838167f425713180b949e9d8dd0bbc7b49f074407c5a8b"}, {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a75879bacf2c987c003368cf14bed0ffe99e8e85acfa6c0bfffc21a090f16880"}, {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-win32.whl", hash = "sha256:84b554931e932c46f94ab306913ad7e11bba988104c5cff26d90d03f68258cd5"}, {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-win_amd64.whl", hash = "sha256:25ac8c08322002b06fa1d49d1646181f0b2c72f5cbc15a85e80b4c30a544bb15"}, {file = "ruamel.yaml.clib-0.2.8.tar.gz", hash = "sha256:beb2e0404003de9a4cab9753a8805a8fe9320ee6673136ed7f04255fe60bb512"}, ] [[package]] name = "ruff" version = "0.5.6" requires_python = ">=3.7" summary = "An extremely fast Python linter and code formatter, written in Rust." files = [ {file = "ruff-0.5.6-py3-none-linux_armv6l.whl", hash = "sha256:a0ef5930799a05522985b9cec8290b185952f3fcd86c1772c3bdbd732667fdcd"}, {file = "ruff-0.5.6-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b652dc14f6ef5d1552821e006f747802cc32d98d5509349e168f6bf0ee9f8f42"}, {file = "ruff-0.5.6-py3-none-macosx_11_0_arm64.whl", hash = "sha256:80521b88d26a45e871f31e4b88938fd87db7011bb961d8afd2664982dfc3641a"}, {file = "ruff-0.5.6-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d9bc8f328a9f1309ae80e4d392836e7dbc77303b38ed4a7112699e63d3b066ab"}, {file = "ruff-0.5.6-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4d394940f61f7720ad371ddedf14722ee1d6250fd8d020f5ea5a86e7be217daf"}, {file = "ruff-0.5.6-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:111a99cdb02f69ddb2571e2756e017a1496c2c3a2aeefe7b988ddab38b416d36"}, {file = "ruff-0.5.6-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:e395daba77a79f6dc0d07311f94cc0560375ca20c06f354c7c99af3bf4560c5d"}, {file = "ruff-0.5.6-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c476acb43c3c51e3c614a2e878ee1589655fa02dab19fe2db0423a06d6a5b1b6"}, {file = "ruff-0.5.6-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e2ff8003f5252fd68425fd53d27c1f08b201d7ed714bb31a55c9ac1d4c13e2eb"}, {file = "ruff-0.5.6-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c94e084ba3eaa80c2172918c2ca2eb2230c3f15925f4ed8b6297260c6ef179ad"}, {file = "ruff-0.5.6-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:1f77c1c3aa0669fb230b06fb24ffa3e879391a3ba3f15e3d633a752da5a3e670"}, {file = "ruff-0.5.6-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:f908148c93c02873210a52cad75a6eda856b2cbb72250370ce3afef6fb99b1ed"}, {file = "ruff-0.5.6-py3-none-musllinux_1_2_i686.whl", hash = "sha256:563a7ae61ad284187d3071d9041c08019975693ff655438d8d4be26e492760bd"}, {file = "ruff-0.5.6-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:94fe60869bfbf0521e04fd62b74cbca21cbc5beb67cbb75ab33fe8c174f54414"}, {file = "ruff-0.5.6-py3-none-win32.whl", hash = "sha256:e6a584c1de6f8591c2570e171cc7ce482bb983d49c70ddf014393cd39e9dfaed"}, {file = "ruff-0.5.6-py3-none-win_amd64.whl", hash = "sha256:d7fe7dccb1a89dc66785d7aa0ac283b2269712d8ed19c63af908fdccca5ccc1a"}, {file = "ruff-0.5.6-py3-none-win_arm64.whl", hash = "sha256:57c6c0dd997b31b536bff49b9eee5ed3194d60605a4427f735eeb1f9c1b8d264"}, {file = "ruff-0.5.6.tar.gz", hash = "sha256:07c9e3c2a8e1fe377dd460371c3462671a728c981c3205a5217291422209f642"}, ] [[package]] name = "sentinels" version = "1.0.0" summary = "Various objects to denote special meanings in python" files = [ {file = "sentinels-1.0.0.tar.gz", hash = "sha256:7be0704d7fe1925e397e92d18669ace2f619c92b5d4eb21a89f31e026f9ff4b1"}, ] [[package]] name = "setuptools" version = "69.5.1" requires_python = ">=3.8" summary = "Easily download, build, install, upgrade, and uninstall Python packages" files = [ {file = "setuptools-69.5.1-py3-none-any.whl", hash = "sha256:c636ac361bc47580504644275c9ad802c50415c7522212252c033bd15f301f32"}, {file = "setuptools-69.5.1.tar.gz", hash = "sha256:6c1fccdac05a97e598fb0ae3bbed5904ccb317337a51139dcd51453611bbb987"}, ] [[package]] name = "shellcheck-py" version = "0.10.0.1" requires_python = ">=3.8" summary = "Python wrapper around invoking shellcheck (https://www.shellcheck.net/)" files = [ {file = "shellcheck_py-0.10.0.1-py2.py3-none-macosx_11_0_x86_64.whl", hash = "sha256:48f08965cafbb3363b265c4ef40628ffced19cb6fc7c4bb5ce72d32cbcfb4bb9"}, {file = "shellcheck_py-0.10.0.1-py2.py3-none-macosx_14_0_arm64.whl", hash = "sha256:8f3bf12ee6d0845dd5ac1a7bac8c4b1fec0379e115950986883c9488af40ada7"}, {file = "shellcheck_py-0.10.0.1-py2.py3-none-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c1c266f7f54cd286057c592ead3095f93d123acdcabf048879a7d8900c3aac7b"}, {file = "shellcheck_py-0.10.0.1-py2.py3-none-win_amd64.whl", hash = "sha256:be73a16931c05f79643ff74b6519d1e1203b394583ab8c68a48a8e7f257d1090"}, {file = "shellcheck_py-0.10.0.1.tar.gz", hash = "sha256:390826b340b8c19173922b0da5ef7b66ef34d4d087dc48aad3e01f7e77e164d9"}, ] [[package]] name = "shibuya" version = "2024.4.27" requires_python = ">=3.7" summary = "A clean, responsive, and customizable Sphinx documentation theme with light/dark mode." dependencies = [ "Sphinx", ] files = [ {file = "shibuya-2024.4.27-py3-none-any.whl", hash = "sha256:b0eaf3ae415eaefb898ca1ad07012c86f6ef12f43aaad73f0d8ef9a13d42bd5e"}, {file = "shibuya-2024.4.27.tar.gz", hash = "sha256:6c7c83d49ae3f1d56c0d4c4ccddd31f5dab4aed4e6caf8f397f4de5da5af1911"}, ] [[package]] name = "six" version = "1.16.0" requires_python = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" summary = "Python 2 and 3 compatibility utilities" files = [ {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, ] [[package]] name = "snowballstemmer" version = "2.2.0" summary = "This package provides 29 stemmers for 28 languages generated from Snowball algorithms." files = [ {file = "snowballstemmer-2.2.0-py2.py3-none-any.whl", hash = "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a"}, {file = "snowballstemmer-2.2.0.tar.gz", hash = "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1"}, ] [[package]] name = "sortedcontainers" version = "2.4.0" summary = "Sorted Containers -- Sorted List, Sorted Dict, Sorted Set" files = [ {file = "sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0"}, {file = "sortedcontainers-2.4.0.tar.gz", hash = "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88"}, ] [[package]] name = "soupsieve" version = "2.5" requires_python = ">=3.8" summary = "A modern CSS selector implementation for Beautiful Soup." files = [ {file = "soupsieve-2.5-py3-none-any.whl", hash = "sha256:eaa337ff55a1579b6549dc679565eac1e3d000563bcb1c8ab0d0fefbc0c2cdc7"}, {file = "soupsieve-2.5.tar.gz", hash = "sha256:5663d5a7b3bfaeee0bc4372e7fc48f9cff4940b3eec54a6451cc5299f1097690"}, ] [[package]] name = "sourcery" version = "1.18.0" summary = "Magically refactor Python" files = [ {file = "sourcery-1.18.0-py2.py3-none-macosx_10_9_universal2.whl", hash = "sha256:f5d35a0136a576800dffedd8537c74da16ca2c507b829d7d8b7ac17d1cc710ab"}, {file = "sourcery-1.18.0-py2.py3-none-manylinux1_x86_64.whl", hash = "sha256:c7770c031816777fbd63e213b3f225bc20d2cbef897e2759a9389332e8c3fed1"}, {file = "sourcery-1.18.0-py2.py3-none-win_amd64.whl", hash = "sha256:1c0478e2fdf7f650e8dd97ee5f7d34fd114415af22470eda3d749f2d2841d084"}, ] [[package]] name = "sphinx" version = "7.1.2" requires_python = ">=3.8" summary = "Python documentation generator" dependencies = [ "Jinja2>=3.0", "Pygments>=2.13", "alabaster<0.8,>=0.7", "babel>=2.9", "colorama>=0.4.5; sys_platform == \"win32\"", "docutils<0.21,>=0.18.1", "imagesize>=1.3", "importlib-metadata>=4.8; python_version < \"3.10\"", "packaging>=21.0", "requests>=2.25.0", "snowballstemmer>=2.0", "sphinxcontrib-applehelp", "sphinxcontrib-devhelp", "sphinxcontrib-htmlhelp>=2.0.0", "sphinxcontrib-jsmath", "sphinxcontrib-qthelp", "sphinxcontrib-serializinghtml>=1.1.5", ] files = [ {file = "sphinx-7.1.2-py3-none-any.whl", hash = "sha256:d170a81825b2fcacb6dfd5a0d7f578a053e45d3f2b153fecc948c37344eb4cbe"}, {file = "sphinx-7.1.2.tar.gz", hash = "sha256:780f4d32f1d7d1126576e0e5ecc19dc32ab76cd24e950228dcf7b1f6d3d9e22f"}, ] [[package]] name = "sphinx-autobuild" version = "2021.3.14" requires_python = ">=3.6" summary = "Rebuild Sphinx documentation on changes, with live-reload in the browser." dependencies = [ "colorama", "livereload", "sphinx", ] files = [ {file = "sphinx-autobuild-2021.3.14.tar.gz", hash = "sha256:de1ca3b66e271d2b5b5140c35034c89e47f263f2cd5db302c9217065f7443f05"}, {file = "sphinx_autobuild-2021.3.14-py3-none-any.whl", hash = "sha256:8fe8cbfdb75db04475232f05187c776f46f6e9e04cacf1e49ce81bdac649ccac"}, ] [[package]] name = "sphinx-autodoc-typehints" version = "2.0.1" requires_python = ">=3.8" summary = "Type hints (PEP 484) support for the Sphinx autodoc extension" dependencies = [ "sphinx>=7.1.2", ] files = [ {file = "sphinx_autodoc_typehints-2.0.1-py3-none-any.whl", hash = "sha256:f73ae89b43a799e587e39266672c1075b2ef783aeb382d3ebed77c38a3fc0149"}, {file = "sphinx_autodoc_typehints-2.0.1.tar.gz", hash = "sha256:60ed1e3b2c970acc0aa6e877be42d48029a9faec7378a17838716cacd8c10b12"}, ] [[package]] name = "sphinx-copybutton" version = "0.5.2" requires_python = ">=3.7" summary = "Add a copy button to each of your code cells." dependencies = [ "sphinx>=1.8", ] files = [ {file = "sphinx-copybutton-0.5.2.tar.gz", hash = "sha256:4cf17c82fb9646d1bc9ca92ac280813a3b605d8c421225fd9913154103ee1fbd"}, {file = "sphinx_copybutton-0.5.2-py3-none-any.whl", hash = "sha256:fb543fd386d917746c9a2c50360c7905b605726b9355cd26e9974857afeae06e"}, ] [[package]] name = "sphinx-design" version = "0.5.0" requires_python = ">=3.8" summary = "A sphinx extension for designing beautiful, view size responsive web components." dependencies = [ "sphinx<8,>=5", ] files = [ {file = "sphinx_design-0.5.0-py3-none-any.whl", hash = "sha256:1af1267b4cea2eedd6724614f19dcc88fe2e15aff65d06b2f6252cee9c4f4c1e"}, {file = "sphinx_design-0.5.0.tar.gz", hash = "sha256:e8e513acea6f92d15c6de3b34e954458f245b8e761b45b63950f65373352ab00"}, ] [[package]] name = "sphinx-jinja2-compat" version = "0.2.0.post1" requires_python = ">=3.6" summary = "Patches Jinja2 v3 to restore compatibility with earlier Sphinx versions." dependencies = [ "jinja2>=2.10", "markupsafe>=1", ] files = [ {file = "sphinx_jinja2_compat-0.2.0.post1-py3-none-any.whl", hash = "sha256:f9d329174bdde8db19dc12c62528367196eb2f6b46c91754eca604acd0c0f6ad"}, {file = "sphinx_jinja2_compat-0.2.0.post1.tar.gz", hash = "sha256:974289a12a9f402108dead621e9c15f7004e945d5cfcaea8d6419e94d3fa95a3"}, ] [[package]] name = "sphinx-paramlinks" version = "0.6.0" summary = "Allows param links in Sphinx function/method descriptions to be linkable" dependencies = [ "Sphinx>=4.0.0", "docutils", ] files = [ {file = "sphinx-paramlinks-0.6.0.tar.gz", hash = "sha256:746a0816860aa3fff5d8d746efcbec4deead421f152687411db1d613d29f915e"}, ] [[package]] name = "sphinx-prompt" version = "1.5.0" summary = "Sphinx directive to add unselectable prompt" dependencies = [ "Sphinx", "pygments", ] files = [ {file = "sphinx_prompt-1.5.0-py3-none-any.whl", hash = "sha256:fa4e90d8088b5a996c76087d701fc7e31175f8b9dc4aab03a507e45051067162"}, ] [[package]] name = "sphinx-tabs" version = "3.4.5" requires_python = "~=3.7" summary = "Tabbed views for Sphinx" dependencies = [ "docutils", "pygments", "sphinx", ] files = [ {file = "sphinx-tabs-3.4.5.tar.gz", hash = "sha256:ba9d0c1e3e37aaadd4b5678449eb08176770e0fc227e769b6ce747df3ceea531"}, {file = "sphinx_tabs-3.4.5-py3-none-any.whl", hash = "sha256:92cc9473e2ecf1828ca3f6617d0efc0aa8acb06b08c56ba29d1413f2f0f6cf09"}, ] [[package]] name = "sphinx-togglebutton" version = "0.3.2" summary = "Toggle page content and collapse admonitions in Sphinx." dependencies = [ "docutils", "setuptools", "sphinx", "wheel", ] files = [ {file = "sphinx-togglebutton-0.3.2.tar.gz", hash = "sha256:ab0c8b366427b01e4c89802d5d078472c427fa6e9d12d521c34fa0442559dc7a"}, {file = "sphinx_togglebutton-0.3.2-py3-none-any.whl", hash = "sha256:9647ba7874b7d1e2d43413d8497153a85edc6ac95a3fea9a75ef9c1e08aaae2b"}, ] [[package]] name = "sphinx-toolbox" version = "3.5.0" requires_python = ">=3.7" summary = "Box of handy tools for Sphinx 🧰 📔" dependencies = [ "apeye>=0.4.0", "autodocsumm>=0.2.0", "beautifulsoup4>=4.9.1", "cachecontrol[filecache]>=0.13.0", "dict2css>=0.2.3", "docutils>=0.16", "domdf-python-tools>=2.9.0", "filelock>=3.8.0", "html5lib>=1.1", "ruamel-yaml>=0.16.12", "sphinx-autodoc-typehints>=1.11.1", "sphinx-jinja2-compat>=0.1.0", "sphinx-prompt>=1.1.0", "sphinx-tabs<3.5.0,>=1.2.1", "sphinx>=3.2.0", "tabulate>=0.8.7", "typing-extensions!=3.10.0.1,>=3.7.4.3", "typing-inspect>=0.6.0; python_version < \"3.8\"", ] files = [ {file = "sphinx_toolbox-3.5.0-py3-none-any.whl", hash = "sha256:20dfd3566717db6f2da7a400a54dc4b946f064fb31250fa44802d54cfb9b8a03"}, {file = "sphinx_toolbox-3.5.0.tar.gz", hash = "sha256:e5b5a7153f1997572d71a06aaf6cec225483492ec2c60097a84f15aad6df18b7"}, ] [[package]] name = "sphinxcontrib-applehelp" version = "1.0.4" requires_python = ">=3.8" summary = "sphinxcontrib-applehelp is a Sphinx extension which outputs Apple help books" files = [ {file = "sphinxcontrib-applehelp-1.0.4.tar.gz", hash = "sha256:828f867945bbe39817c210a1abfd1bc4895c8b73fcaade56d45357a348a07d7e"}, {file = "sphinxcontrib_applehelp-1.0.4-py3-none-any.whl", hash = "sha256:29d341f67fb0f6f586b23ad80e072c8e6ad0b48417db2bde114a4c9746feb228"}, ] [[package]] name = "sphinxcontrib-devhelp" version = "1.0.2" requires_python = ">=3.5" summary = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp document." files = [ {file = "sphinxcontrib-devhelp-1.0.2.tar.gz", hash = "sha256:ff7f1afa7b9642e7060379360a67e9c41e8f3121f2ce9164266f61b9f4b338e4"}, {file = "sphinxcontrib_devhelp-1.0.2-py2.py3-none-any.whl", hash = "sha256:8165223f9a335cc1af7ffe1ed31d2871f325254c0423bc0c4c7cd1c1e4734a2e"}, ] [[package]] name = "sphinxcontrib-htmlhelp" version = "2.0.1" requires_python = ">=3.8" summary = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files" files = [ {file = "sphinxcontrib-htmlhelp-2.0.1.tar.gz", hash = "sha256:0cbdd302815330058422b98a113195c9249825d681e18f11e8b1f78a2f11efff"}, {file = "sphinxcontrib_htmlhelp-2.0.1-py3-none-any.whl", hash = "sha256:c38cb46dccf316c79de6e5515e1770414b797162b23cd3d06e67020e1d2a6903"}, ] [[package]] name = "sphinxcontrib-jsmath" version = "1.0.1" requires_python = ">=3.5" summary = "A sphinx extension which renders display math in HTML via JavaScript" files = [ {file = "sphinxcontrib-jsmath-1.0.1.tar.gz", hash = "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8"}, {file = "sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl", hash = "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178"}, ] [[package]] name = "sphinxcontrib-mermaid" version = "0.9.2" requires_python = ">=3.7" summary = "Mermaid diagrams in yours Sphinx powered docs" files = [ {file = "sphinxcontrib-mermaid-0.9.2.tar.gz", hash = "sha256:252ef13dd23164b28f16d8b0205cf184b9d8e2b714a302274d9f59eb708e77af"}, {file = "sphinxcontrib_mermaid-0.9.2-py3-none-any.whl", hash = "sha256:6795a72037ca55e65663d2a2c1a043d636dc3d30d418e56dd6087d1459d98a5d"}, ] [[package]] name = "sphinxcontrib-qthelp" version = "1.0.3" requires_python = ">=3.5" summary = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp document." files = [ {file = "sphinxcontrib-qthelp-1.0.3.tar.gz", hash = "sha256:4c33767ee058b70dba89a6fc5c1892c0d57a54be67ddd3e7875a18d14cba5a72"}, {file = "sphinxcontrib_qthelp-1.0.3-py2.py3-none-any.whl", hash = "sha256:bd9fc24bcb748a8d51fd4ecaade681350aa63009a347a8c14e637895444dfab6"}, ] [[package]] name = "sphinxcontrib-serializinghtml" version = "1.1.5" requires_python = ">=3.5" summary = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)." files = [ {file = "sphinxcontrib-serializinghtml-1.1.5.tar.gz", hash = "sha256:aa5f6de5dfdf809ef505c4895e51ef5c9eac17d0f287933eb49ec495280b6952"}, {file = "sphinxcontrib_serializinghtml-1.1.5-py2.py3-none-any.whl", hash = "sha256:352a9a00ae864471d3a7ead8d7d79f5fc0b57e8b3f95e9867eb9eb28999b92fd"}, ] [[package]] name = "sqlalchemy" version = "2.0.36" requires_python = ">=3.7" summary = "Database Abstraction Library" dependencies = [ "greenlet!=0.4.17; (platform_machine == \"win32\" or platform_machine == \"WIN32\" or platform_machine == \"AMD64\" or platform_machine == \"amd64\" or platform_machine == \"x86_64\" or platform_machine == \"ppc64le\" or platform_machine == \"aarch64\") and python_version < \"3.13\"", "importlib-metadata; python_version < \"3.8\"", "typing-extensions>=4.6.0", ] files = [ {file = "SQLAlchemy-2.0.36-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:59b8f3adb3971929a3e660337f5dacc5942c2cdb760afcabb2614ffbda9f9f72"}, {file = "SQLAlchemy-2.0.36-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:37350015056a553e442ff672c2d20e6f4b6d0b2495691fa239d8aa18bb3bc908"}, {file = "SQLAlchemy-2.0.36-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8318f4776c85abc3f40ab185e388bee7a6ea99e7fa3a30686580b209eaa35c08"}, {file = "SQLAlchemy-2.0.36-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c245b1fbade9c35e5bd3b64270ab49ce990369018289ecfde3f9c318411aaa07"}, {file = "SQLAlchemy-2.0.36-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:69f93723edbca7342624d09f6704e7126b152eaed3cdbb634cb657a54332a3c5"}, {file = "SQLAlchemy-2.0.36-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f9511d8dd4a6e9271d07d150fb2f81874a3c8c95e11ff9af3a2dfc35fe42ee44"}, {file = "SQLAlchemy-2.0.36-cp310-cp310-win32.whl", hash = "sha256:c3f3631693003d8e585d4200730616b78fafd5a01ef8b698f6967da5c605b3fa"}, {file = "SQLAlchemy-2.0.36-cp310-cp310-win_amd64.whl", hash = "sha256:a86bfab2ef46d63300c0f06936bd6e6c0105faa11d509083ba8f2f9d237fb5b5"}, {file = "SQLAlchemy-2.0.36-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:fd3a55deef00f689ce931d4d1b23fa9f04c880a48ee97af488fd215cf24e2a6c"}, {file = "SQLAlchemy-2.0.36-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4f5e9cd989b45b73bd359f693b935364f7e1f79486e29015813c338450aa5a71"}, {file = "SQLAlchemy-2.0.36-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d0ddd9db6e59c44875211bc4c7953a9f6638b937b0a88ae6d09eb46cced54eff"}, {file = "SQLAlchemy-2.0.36-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2519f3a5d0517fc159afab1015e54bb81b4406c278749779be57a569d8d1bb0d"}, {file = "SQLAlchemy-2.0.36-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:59b1ee96617135f6e1d6f275bbe988f419c5178016f3d41d3c0abb0c819f75bb"}, {file = "SQLAlchemy-2.0.36-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:39769a115f730d683b0eb7b694db9789267bcd027326cccc3125e862eb03bfd8"}, {file = "SQLAlchemy-2.0.36-cp311-cp311-win32.whl", hash = "sha256:66bffbad8d6271bb1cc2f9a4ea4f86f80fe5e2e3e501a5ae2a3dc6a76e604e6f"}, {file = "SQLAlchemy-2.0.36-cp311-cp311-win_amd64.whl", hash = "sha256:23623166bfefe1487d81b698c423f8678e80df8b54614c2bf4b4cfcd7c711959"}, {file = "SQLAlchemy-2.0.36-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f7b64e6ec3f02c35647be6b4851008b26cff592a95ecb13b6788a54ef80bbdd4"}, {file = "SQLAlchemy-2.0.36-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:46331b00096a6db1fdc052d55b101dbbfc99155a548e20a0e4a8e5e4d1362855"}, {file = "SQLAlchemy-2.0.36-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fdf3386a801ea5aba17c6410dd1dc8d39cf454ca2565541b5ac42a84e1e28f53"}, {file = "SQLAlchemy-2.0.36-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac9dfa18ff2a67b09b372d5db8743c27966abf0e5344c555d86cc7199f7ad83a"}, {file = "SQLAlchemy-2.0.36-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:90812a8933df713fdf748b355527e3af257a11e415b613dd794512461eb8a686"}, {file = "SQLAlchemy-2.0.36-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1bc330d9d29c7f06f003ab10e1eaced295e87940405afe1b110f2eb93a233588"}, {file = "SQLAlchemy-2.0.36-cp312-cp312-win32.whl", hash = "sha256:79d2e78abc26d871875b419e1fd3c0bca31a1cb0043277d0d850014599626c2e"}, {file = "SQLAlchemy-2.0.36-cp312-cp312-win_amd64.whl", hash = "sha256:b544ad1935a8541d177cb402948b94e871067656b3a0b9e91dbec136b06a2ff5"}, {file = "SQLAlchemy-2.0.36-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b5cc79df7f4bc3d11e4b542596c03826063092611e481fcf1c9dfee3c94355ef"}, {file = "SQLAlchemy-2.0.36-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:3c01117dd36800f2ecaa238c65365b7b16497adc1522bf84906e5710ee9ba0e8"}, {file = "SQLAlchemy-2.0.36-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9bc633f4ee4b4c46e7adcb3a9b5ec083bf1d9a97c1d3854b92749d935de40b9b"}, {file = "SQLAlchemy-2.0.36-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e46ed38affdfc95d2c958de328d037d87801cfcbea6d421000859e9789e61c2"}, {file = "SQLAlchemy-2.0.36-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:b2985c0b06e989c043f1dc09d4fe89e1616aadd35392aea2844f0458a989eacf"}, {file = "SQLAlchemy-2.0.36-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4a121d62ebe7d26fec9155f83f8be5189ef1405f5973ea4874a26fab9f1e262c"}, {file = "SQLAlchemy-2.0.36-cp313-cp313-win32.whl", hash = "sha256:0572f4bd6f94752167adfd7c1bed84f4b240ee6203a95e05d1e208d488d0d436"}, {file = "SQLAlchemy-2.0.36-cp313-cp313-win_amd64.whl", hash = "sha256:8c78ac40bde930c60e0f78b3cd184c580f89456dd87fc08f9e3ee3ce8765ce88"}, {file = "SQLAlchemy-2.0.36-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3d6718667da04294d7df1670d70eeddd414f313738d20a6f1d1f379e3139a545"}, {file = "SQLAlchemy-2.0.36-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:72c28b84b174ce8af8504ca28ae9347d317f9dba3999e5981a3cd441f3712e24"}, {file = "SQLAlchemy-2.0.36-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b11d0cfdd2b095e7b0686cf5fabeb9c67fae5b06d265d8180715b8cfa86522e3"}, {file = "SQLAlchemy-2.0.36-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e32092c47011d113dc01ab3e1d3ce9f006a47223b18422c5c0d150af13a00687"}, {file = "SQLAlchemy-2.0.36-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:6a440293d802d3011028e14e4226da1434b373cbaf4a4bbb63f845761a708346"}, {file = "SQLAlchemy-2.0.36-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:c54a1e53a0c308a8e8a7dffb59097bff7facda27c70c286f005327f21b2bd6b1"}, {file = "SQLAlchemy-2.0.36-cp38-cp38-win32.whl", hash = "sha256:1e0d612a17581b6616ff03c8e3d5eff7452f34655c901f75d62bd86449d9750e"}, {file = "SQLAlchemy-2.0.36-cp38-cp38-win_amd64.whl", hash = "sha256:8958b10490125124463095bbdadda5aa22ec799f91958e410438ad6c97a7b793"}, {file = "SQLAlchemy-2.0.36-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:dc022184d3e5cacc9579e41805a681187650e170eb2fd70e28b86192a479dcaa"}, {file = "SQLAlchemy-2.0.36-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b817d41d692bf286abc181f8af476c4fbef3fd05e798777492618378448ee689"}, {file = "SQLAlchemy-2.0.36-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a4e46a888b54be23d03a89be510f24a7652fe6ff660787b96cd0e57a4ebcb46d"}, {file = "SQLAlchemy-2.0.36-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c4ae3005ed83f5967f961fd091f2f8c5329161f69ce8480aa8168b2d7fe37f06"}, {file = "SQLAlchemy-2.0.36-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:03e08af7a5f9386a43919eda9de33ffda16b44eb11f3b313e6822243770e9763"}, {file = "SQLAlchemy-2.0.36-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:3dbb986bad3ed5ceaf090200eba750b5245150bd97d3e67343a3cfed06feecf7"}, {file = "SQLAlchemy-2.0.36-cp39-cp39-win32.whl", hash = "sha256:9fe53b404f24789b5ea9003fc25b9a3988feddebd7e7b369c8fac27ad6f52f28"}, {file = "SQLAlchemy-2.0.36-cp39-cp39-win_amd64.whl", hash = "sha256:af148a33ff0349f53512a049c6406923e4e02bf2f26c5fb285f143faf4f0e46a"}, {file = "SQLAlchemy-2.0.36-py3-none-any.whl", hash = "sha256:fddbe92b4760c6f5d48162aef14824add991aeda8ddadb3c31d56eb15ca69f8e"}, {file = "sqlalchemy-2.0.36.tar.gz", hash = "sha256:7f2767680b6d2398aea7082e45a774b2b0767b5c8d8ffb9c8b683088ea9b29c5"}, ] [[package]] name = "sqlalchemy" version = "2.0.36" extras = ["asyncio"] requires_python = ">=3.7" summary = "Database Abstraction Library" dependencies = [ "greenlet!=0.4.17", "sqlalchemy==2.0.36", ] files = [ {file = "SQLAlchemy-2.0.36-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:59b8f3adb3971929a3e660337f5dacc5942c2cdb760afcabb2614ffbda9f9f72"}, {file = "SQLAlchemy-2.0.36-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:37350015056a553e442ff672c2d20e6f4b6d0b2495691fa239d8aa18bb3bc908"}, {file = "SQLAlchemy-2.0.36-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8318f4776c85abc3f40ab185e388bee7a6ea99e7fa3a30686580b209eaa35c08"}, {file = "SQLAlchemy-2.0.36-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c245b1fbade9c35e5bd3b64270ab49ce990369018289ecfde3f9c318411aaa07"}, {file = "SQLAlchemy-2.0.36-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:69f93723edbca7342624d09f6704e7126b152eaed3cdbb634cb657a54332a3c5"}, {file = "SQLAlchemy-2.0.36-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f9511d8dd4a6e9271d07d150fb2f81874a3c8c95e11ff9af3a2dfc35fe42ee44"}, {file = "SQLAlchemy-2.0.36-cp310-cp310-win32.whl", hash = "sha256:c3f3631693003d8e585d4200730616b78fafd5a01ef8b698f6967da5c605b3fa"}, {file = "SQLAlchemy-2.0.36-cp310-cp310-win_amd64.whl", hash = "sha256:a86bfab2ef46d63300c0f06936bd6e6c0105faa11d509083ba8f2f9d237fb5b5"}, {file = "SQLAlchemy-2.0.36-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:fd3a55deef00f689ce931d4d1b23fa9f04c880a48ee97af488fd215cf24e2a6c"}, {file = "SQLAlchemy-2.0.36-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4f5e9cd989b45b73bd359f693b935364f7e1f79486e29015813c338450aa5a71"}, {file = "SQLAlchemy-2.0.36-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d0ddd9db6e59c44875211bc4c7953a9f6638b937b0a88ae6d09eb46cced54eff"}, {file = "SQLAlchemy-2.0.36-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2519f3a5d0517fc159afab1015e54bb81b4406c278749779be57a569d8d1bb0d"}, {file = "SQLAlchemy-2.0.36-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:59b1ee96617135f6e1d6f275bbe988f419c5178016f3d41d3c0abb0c819f75bb"}, {file = "SQLAlchemy-2.0.36-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:39769a115f730d683b0eb7b694db9789267bcd027326cccc3125e862eb03bfd8"}, {file = "SQLAlchemy-2.0.36-cp311-cp311-win32.whl", hash = "sha256:66bffbad8d6271bb1cc2f9a4ea4f86f80fe5e2e3e501a5ae2a3dc6a76e604e6f"}, {file = "SQLAlchemy-2.0.36-cp311-cp311-win_amd64.whl", hash = "sha256:23623166bfefe1487d81b698c423f8678e80df8b54614c2bf4b4cfcd7c711959"}, {file = "SQLAlchemy-2.0.36-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f7b64e6ec3f02c35647be6b4851008b26cff592a95ecb13b6788a54ef80bbdd4"}, {file = "SQLAlchemy-2.0.36-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:46331b00096a6db1fdc052d55b101dbbfc99155a548e20a0e4a8e5e4d1362855"}, {file = "SQLAlchemy-2.0.36-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fdf3386a801ea5aba17c6410dd1dc8d39cf454ca2565541b5ac42a84e1e28f53"}, {file = "SQLAlchemy-2.0.36-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac9dfa18ff2a67b09b372d5db8743c27966abf0e5344c555d86cc7199f7ad83a"}, {file = "SQLAlchemy-2.0.36-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:90812a8933df713fdf748b355527e3af257a11e415b613dd794512461eb8a686"}, {file = "SQLAlchemy-2.0.36-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1bc330d9d29c7f06f003ab10e1eaced295e87940405afe1b110f2eb93a233588"}, {file = "SQLAlchemy-2.0.36-cp312-cp312-win32.whl", hash = "sha256:79d2e78abc26d871875b419e1fd3c0bca31a1cb0043277d0d850014599626c2e"}, {file = "SQLAlchemy-2.0.36-cp312-cp312-win_amd64.whl", hash = "sha256:b544ad1935a8541d177cb402948b94e871067656b3a0b9e91dbec136b06a2ff5"}, {file = "SQLAlchemy-2.0.36-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b5cc79df7f4bc3d11e4b542596c03826063092611e481fcf1c9dfee3c94355ef"}, {file = "SQLAlchemy-2.0.36-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:3c01117dd36800f2ecaa238c65365b7b16497adc1522bf84906e5710ee9ba0e8"}, {file = "SQLAlchemy-2.0.36-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9bc633f4ee4b4c46e7adcb3a9b5ec083bf1d9a97c1d3854b92749d935de40b9b"}, {file = "SQLAlchemy-2.0.36-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e46ed38affdfc95d2c958de328d037d87801cfcbea6d421000859e9789e61c2"}, {file = "SQLAlchemy-2.0.36-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:b2985c0b06e989c043f1dc09d4fe89e1616aadd35392aea2844f0458a989eacf"}, {file = "SQLAlchemy-2.0.36-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4a121d62ebe7d26fec9155f83f8be5189ef1405f5973ea4874a26fab9f1e262c"}, {file = "SQLAlchemy-2.0.36-cp313-cp313-win32.whl", hash = "sha256:0572f4bd6f94752167adfd7c1bed84f4b240ee6203a95e05d1e208d488d0d436"}, {file = "SQLAlchemy-2.0.36-cp313-cp313-win_amd64.whl", hash = "sha256:8c78ac40bde930c60e0f78b3cd184c580f89456dd87fc08f9e3ee3ce8765ce88"}, {file = "SQLAlchemy-2.0.36-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3d6718667da04294d7df1670d70eeddd414f313738d20a6f1d1f379e3139a545"}, {file = "SQLAlchemy-2.0.36-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:72c28b84b174ce8af8504ca28ae9347d317f9dba3999e5981a3cd441f3712e24"}, {file = "SQLAlchemy-2.0.36-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b11d0cfdd2b095e7b0686cf5fabeb9c67fae5b06d265d8180715b8cfa86522e3"}, {file = "SQLAlchemy-2.0.36-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e32092c47011d113dc01ab3e1d3ce9f006a47223b18422c5c0d150af13a00687"}, {file = "SQLAlchemy-2.0.36-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:6a440293d802d3011028e14e4226da1434b373cbaf4a4bbb63f845761a708346"}, {file = "SQLAlchemy-2.0.36-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:c54a1e53a0c308a8e8a7dffb59097bff7facda27c70c286f005327f21b2bd6b1"}, {file = "SQLAlchemy-2.0.36-cp38-cp38-win32.whl", hash = "sha256:1e0d612a17581b6616ff03c8e3d5eff7452f34655c901f75d62bd86449d9750e"}, {file = "SQLAlchemy-2.0.36-cp38-cp38-win_amd64.whl", hash = "sha256:8958b10490125124463095bbdadda5aa22ec799f91958e410438ad6c97a7b793"}, {file = "SQLAlchemy-2.0.36-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:dc022184d3e5cacc9579e41805a681187650e170eb2fd70e28b86192a479dcaa"}, {file = "SQLAlchemy-2.0.36-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b817d41d692bf286abc181f8af476c4fbef3fd05e798777492618378448ee689"}, {file = "SQLAlchemy-2.0.36-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a4e46a888b54be23d03a89be510f24a7652fe6ff660787b96cd0e57a4ebcb46d"}, {file = "SQLAlchemy-2.0.36-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c4ae3005ed83f5967f961fd091f2f8c5329161f69ce8480aa8168b2d7fe37f06"}, {file = "SQLAlchemy-2.0.36-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:03e08af7a5f9386a43919eda9de33ffda16b44eb11f3b313e6822243770e9763"}, {file = "SQLAlchemy-2.0.36-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:3dbb986bad3ed5ceaf090200eba750b5245150bd97d3e67343a3cfed06feecf7"}, {file = "SQLAlchemy-2.0.36-cp39-cp39-win32.whl", hash = "sha256:9fe53b404f24789b5ea9003fc25b9a3988feddebd7e7b369c8fac27ad6f52f28"}, {file = "SQLAlchemy-2.0.36-cp39-cp39-win_amd64.whl", hash = "sha256:af148a33ff0349f53512a049c6406923e4e02bf2f26c5fb285f143faf4f0e46a"}, {file = "SQLAlchemy-2.0.36-py3-none-any.whl", hash = "sha256:fddbe92b4760c6f5d48162aef14824add991aeda8ddadb3c31d56eb15ca69f8e"}, {file = "sqlalchemy-2.0.36.tar.gz", hash = "sha256:7f2767680b6d2398aea7082e45a774b2b0767b5c8d8ffb9c8b683088ea9b29c5"}, ] [[package]] name = "tabulate" version = "0.9.0" requires_python = ">=3.7" summary = "Pretty-print tabular data" files = [ {file = "tabulate-0.9.0-py3-none-any.whl", hash = "sha256:024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f"}, {file = "tabulate-0.9.0.tar.gz", hash = "sha256:0095b12bf5966de529c0feb1fa08671671b3368eec77d7ef7ab114be2c068b3c"}, ] [[package]] name = "toml" version = "0.10.2" requires_python = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" summary = "Python Library for Tom's Obvious, Minimal Language" files = [ {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, ] [[package]] name = "tomli" version = "2.0.1" requires_python = ">=3.7" summary = "A lil' TOML parser" files = [ {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, ] [[package]] name = "tornado" version = "6.4" requires_python = ">= 3.8" summary = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed." files = [ {file = "tornado-6.4-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:02ccefc7d8211e5a7f9e8bc3f9e5b0ad6262ba2fbb683a6443ecc804e5224ce0"}, {file = "tornado-6.4-cp38-abi3-macosx_10_9_x86_64.whl", hash = "sha256:27787de946a9cffd63ce5814c33f734c627a87072ec7eed71f7fc4417bb16263"}, {file = "tornado-6.4-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f7894c581ecdcf91666a0912f18ce5e757213999e183ebfc2c3fdbf4d5bd764e"}, {file = "tornado-6.4-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e43bc2e5370a6a8e413e1e1cd0c91bedc5bd62a74a532371042a18ef19e10579"}, {file = "tornado-6.4-cp38-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f0251554cdd50b4b44362f73ad5ba7126fc5b2c2895cc62b14a1c2d7ea32f212"}, {file = "tornado-6.4-cp38-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:fd03192e287fbd0899dd8f81c6fb9cbbc69194d2074b38f384cb6fa72b80e9c2"}, {file = "tornado-6.4-cp38-abi3-musllinux_1_1_i686.whl", hash = "sha256:88b84956273fbd73420e6d4b8d5ccbe913c65d31351b4c004ae362eba06e1f78"}, {file = "tornado-6.4-cp38-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:71ddfc23a0e03ef2df1c1397d859868d158c8276a0603b96cf86892bff58149f"}, {file = "tornado-6.4-cp38-abi3-win32.whl", hash = "sha256:6f8a6c77900f5ae93d8b4ae1196472d0ccc2775cc1dfdc9e7727889145c45052"}, {file = "tornado-6.4-cp38-abi3-win_amd64.whl", hash = "sha256:10aeaa8006333433da48dec9fe417877f8bcc21f48dda8d661ae79da357b2a63"}, {file = "tornado-6.4.tar.gz", hash = "sha256:72291fa6e6bc84e626589f1c29d90a5a6d593ef5ae68052ee2ef000dfd273dee"}, ] [[package]] name = "typing-extensions" version = "4.12.0" requires_python = ">=3.8" summary = "Backported and Experimental Type Hints for Python 3.8+" files = [ {file = "typing_extensions-4.12.0-py3-none-any.whl", hash = "sha256:b349c66bea9016ac22978d800cfff206d5f9816951f12a7d0ec5578b0a819594"}, {file = "typing_extensions-4.12.0.tar.gz", hash = "sha256:8cbcdc8606ebcb0d95453ad7dc5065e6237b6aa230a31e81d0f440c30fed5fd8"}, ] [[package]] name = "urllib3" version = "2.2.1" requires_python = ">=3.8" summary = "HTTP library with thread-safe connection pooling, file post, and more." files = [ {file = "urllib3-2.2.1-py3-none-any.whl", hash = "sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d"}, {file = "urllib3-2.2.1.tar.gz", hash = "sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19"}, ] [[package]] name = "virtualenv" version = "20.26.1" requires_python = ">=3.7" summary = "Virtual Python Environment builder" dependencies = [ "distlib<1,>=0.3.7", "filelock<4,>=3.12.2", "importlib-metadata>=6.6; python_version < \"3.8\"", "platformdirs<5,>=3.9.1", ] files = [ {file = "virtualenv-20.26.1-py3-none-any.whl", hash = "sha256:7aa9982a728ae5892558bff6a2839c00b9ed145523ece2274fad6f414690ae75"}, {file = "virtualenv-20.26.1.tar.gz", hash = "sha256:604bfdceaeece392802e6ae48e69cec49168b9c5f4a44e483963f9242eb0e78b"}, ] [[package]] name = "webencodings" version = "0.5.1" summary = "Character encoding aliases for legacy web content" files = [ {file = "webencodings-0.5.1-py2.py3-none-any.whl", hash = "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78"}, {file = "webencodings-0.5.1.tar.gz", hash = "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923"}, ] [[package]] name = "wheel" version = "0.43.0" requires_python = ">=3.8" summary = "A built-package format for Python" files = [ {file = "wheel-0.43.0-py3-none-any.whl", hash = "sha256:55c570405f142630c6b9f72fe09d9b67cf1477fcf543ae5b8dcb1f5b7377da81"}, {file = "wheel-0.43.0.tar.gz", hash = "sha256:465ef92c69fa5c5da2d1cf8ac40559a8c940886afcef87dcf14b9470862f1d85"}, ] [[package]] name = "zipp" version = "3.18.1" requires_python = ">=3.8" summary = "Backport of pathlib-compatible object wrapper for zip files" files = [ {file = "zipp-3.18.1-py3-none-any.whl", hash = "sha256:206f5a15f2af3dbaee80769fb7dc6f249695e940acca08dfb2a4769fe61e538b"}, {file = "zipp-3.18.1.tar.gz", hash = "sha256:2884ed22e7d8961de1c9a05142eb69a247f120291bc0206a00a7642f09b5b715"}, ] �������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/polyfactory/��������������������������������������������������������������0000775�0000000�0000000�00000000000�14721310225�0020045�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/polyfactory/__init__.py���������������������������������������������������0000664�0000000�0000000�00000000651�14721310225�0022160�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from .exceptions import ConfigurationException from .factories import BaseFactory from .fields import Fixture, Ignore, PostGenerated, Require, Use from .persistence import AsyncPersistenceProtocol, SyncPersistenceProtocol __all__ = ( "AsyncPersistenceProtocol", "BaseFactory", "ConfigurationException", "Fixture", "Ignore", "PostGenerated", "Require", "SyncPersistenceProtocol", "Use", ) ���������������������������������������������������������������������������������������python-polyfactory-2.18.1/polyfactory/__metadata__.py�����������������������������������������������0000664�0000000�0000000�00000000474�14721310225�0023000�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������"""Metadata for the Project.""" from __future__ import annotations import importlib.metadata __all__ = ["__version__", "__project__"] __version__ = importlib.metadata.version("polyfactory") """Version of the project.""" __project__ = importlib.metadata.metadata("polyfactory")["Name"] """Name of the project.""" ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/polyfactory/collection_extender.py����������������������������������������0000664�0000000�0000000�00000005065�14721310225�0024456�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from __future__ import annotations import random from abc import ABC, abstractmethod from collections import deque from typing import Any from polyfactory.utils.predicates import is_safe_subclass class CollectionExtender(ABC): __types__: tuple[type, ...] @staticmethod @abstractmethod def _extend_type_args(type_args: tuple[Any, ...], number_of_args: int) -> tuple[Any, ...]: raise NotImplementedError @classmethod def _subclass_for_type(cls, annotation_alias: Any) -> type[CollectionExtender]: return next( ( subclass for subclass in cls.__subclasses__() if any(is_safe_subclass(annotation_alias, t) for t in subclass.__types__) ), FallbackExtender, ) @classmethod def extend_type_args( cls, annotation_alias: Any, type_args: tuple[Any, ...], number_of_args: int, ) -> tuple[Any, ...]: return cls._subclass_for_type(annotation_alias)._extend_type_args(type_args, number_of_args) class TupleExtender(CollectionExtender): __types__ = (tuple,) @staticmethod def _extend_type_args(type_args: tuple[Any, ...], number_of_args: int) -> tuple[Any, ...]: if not type_args: return type_args if type_args[-1] is not ...: return type_args type_to_extend = type_args[-2] return type_args[:-2] + (type_to_extend,) * number_of_args class ListLikeExtender(CollectionExtender): __types__ = (list, deque) @staticmethod def _extend_type_args(type_args: tuple[Any, ...], number_of_args: int) -> tuple[Any, ...]: if not type_args: return type_args return tuple(random.choice(type_args) for _ in range(number_of_args)) class SetExtender(CollectionExtender): __types__ = (set, frozenset) @staticmethod def _extend_type_args(type_args: tuple[Any, ...], number_of_args: int) -> tuple[Any, ...]: if not type_args: return type_args return tuple(random.choice(type_args) for _ in range(number_of_args)) class DictExtender(CollectionExtender): __types__ = (dict,) @staticmethod def _extend_type_args(type_args: tuple[Any, ...], number_of_args: int) -> tuple[Any, ...]: return type_args * number_of_args class FallbackExtender(CollectionExtender): __types__ = () @staticmethod def _extend_type_args( type_args: tuple[Any, ...], number_of_args: int, # noqa: ARG004 ) -> tuple[Any, ...]: # - investigate @guacs return type_args ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/polyfactory/constants.py��������������������������������������������������0000664�0000000�0000000�00000003050�14721310225�0022431�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from __future__ import annotations import sys from collections import abc, defaultdict, deque from random import Random from typing import ( DefaultDict, Deque, Dict, FrozenSet, Iterable, List, Mapping, Sequence, Set, Tuple, Union, ) try: from types import UnionType except ImportError: UnionType = Union # type: ignore[misc,assignment] PY_38 = sys.version_info.major == 3 and sys.version_info.minor == 8 # noqa: PLR2004 # Mapping of type annotations into concrete types. This is used to normalize python <= 3.9 annotations. INSTANTIABLE_TYPE_MAPPING = { DefaultDict: defaultdict, Deque: deque, Dict: dict, FrozenSet: frozenset, Iterable: list, List: list, Mapping: dict, Sequence: list, Set: set, Tuple: tuple, abc.Iterable: list, abc.Mapping: dict, abc.Sequence: list, abc.Set: set, UnionType: Union, } if not PY_38: TYPE_MAPPING = INSTANTIABLE_TYPE_MAPPING else: # For 3.8, we have to keep the types from typing since dict[str] syntax is not supported in 3.8. TYPE_MAPPING = { DefaultDict: DefaultDict, Deque: Deque, Dict: Dict, FrozenSet: FrozenSet, Iterable: List, List: List, Mapping: Dict, Sequence: List, Set: Set, Tuple: Tuple, abc.Iterable: List, abc.Mapping: Dict, abc.Sequence: List, abc.Set: Set, } DEFAULT_RANDOM = Random() RANDOMIZE_COLLECTION_LENGTH = False MIN_COLLECTION_LENGTH = 0 MAX_COLLECTION_LENGTH = 5 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/polyfactory/decorators.py�������������������������������������������������0000664�0000000�0000000�00000002176�14721310225�0022572�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from __future__ import annotations import contextlib import inspect from typing import Any, Callable from polyfactory import PostGenerated class post_generated: # noqa: N801 """Descriptor class for wrapping a classmethod into a ``PostGenerated`` field.""" __slots__ = ("method", "cache") def __init__(self, method: Callable | classmethod) -> None: if not isinstance(method, classmethod): msg = "post_generated decorator can only be used on classmethods" raise TypeError(msg) self.method = method self.cache: dict[type, PostGenerated] = {} def __get__(self, obj: Any, objtype: type) -> PostGenerated: with contextlib.suppress(KeyError): return self.cache[objtype] fn = self.method.__func__ # pyright: ignore[reportFunctionMemberAccess] fn_args = inspect.getfullargspec(fn).args[1:] def new_fn(name: str, values: dict[str, Any]) -> Any: # noqa: ARG001 - investigate @guacs return fn(objtype, **{arg: values[arg] for arg in fn_args if arg in values}) return self.cache.setdefault(objtype, PostGenerated(new_fn)) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/polyfactory/exceptions.py�������������������������������������������������0000664�0000000�0000000�00000001117�14721310225�0022600�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������class FactoryException(Exception): """Base Factory error class""" class ConfigurationException(FactoryException): """Configuration Error class - used for misconfiguration""" class ParameterException(FactoryException): """Parameter exception - used when wrong parameters are used""" class MissingBuildKwargException(FactoryException): """Missing Build Kwarg exception - used when a required build kwarg is not provided""" class MissingDependencyException(FactoryException, ImportError): """Missing dependency exception - used when a dependency is not installed""" �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/polyfactory/factories/����������������������������������������������������0000775�0000000�0000000�00000000000�14721310225�0022024�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/polyfactory/factories/__init__.py�����������������������������������������0000664�0000000�0000000�00000000401�14721310225�0024130�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from polyfactory.factories.base import BaseFactory from polyfactory.factories.dataclass_factory import DataclassFactory from polyfactory.factories.typed_dict_factory import TypedDictFactory __all__ = ("BaseFactory", "TypedDictFactory", "DataclassFactory") ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/polyfactory/factories/attrs_factory.py������������������������������������0000664�0000000�0000000�00000004662�14721310225�0025272�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from __future__ import annotations from inspect import isclass from typing import TYPE_CHECKING, Generic, TypeVar from polyfactory.exceptions import MissingDependencyException from polyfactory.factories.base import BaseFactory from polyfactory.field_meta import FieldMeta, Null if TYPE_CHECKING: from typing import Any, TypeGuard try: import attrs from attr._make import Factory from attrs import AttrsInstance except ImportError as ex: msg = "attrs is not installed" raise MissingDependencyException(msg) from ex T = TypeVar("T", bound=AttrsInstance) class AttrsFactory(Generic[T], BaseFactory[T]): """Base factory for attrs classes.""" __model__: type[T] __is_base_factory__ = True @classmethod def is_supported_type(cls, value: Any) -> TypeGuard[type[T]]: return isclass(value) and hasattr(value, "__attrs_attrs__") @classmethod def get_model_fields(cls) -> list[FieldMeta]: field_metas: list[FieldMeta] = [] none_type = type(None) cls.resolve_types(cls.__model__) fields = attrs.fields(cls.__model__) for field in fields: if not field.init: continue annotation = none_type if field.type is None else field.type default = field.default if isinstance(default, Factory): # The default value is not currently being used when generating # the field values. When that is implemented, this would need # to be handled differently since the `default.factory` could # take a `self` argument. default_value = default.factory elif default is None: default_value = Null else: default_value = default field_metas.append( FieldMeta.from_type( annotation=annotation, name=field.alias, default=default_value, random=cls.__random__, ), ) return field_metas @classmethod def resolve_types(cls, model: type[T], **kwargs: Any) -> None: """Resolve any strings and forward annotations in type annotations. :param model: The model to resolve the type annotations for. :param kwargs: Any parameters that need to be passed to `attrs.resolve_types`. """ attrs.resolve_types(model, **kwargs) ������������������������������������������������������������������������������python-polyfactory-2.18.1/polyfactory/factories/base.py���������������������������������������������0000664�0000000�0000000�00000135055�14721310225�0023321�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from __future__ import annotations import copy from abc import ABC, abstractmethod from collections import Counter, abc, deque from contextlib import suppress from datetime import date, datetime, time, timedelta from decimal import Decimal from enum import EnumMeta from functools import partial from importlib import import_module from ipaddress import ( IPv4Address, IPv4Interface, IPv4Network, IPv6Address, IPv6Interface, IPv6Network, ip_address, ip_interface, ip_network, ) from os.path import realpath from pathlib import Path from random import Random from typing import ( TYPE_CHECKING, Any, Callable, ClassVar, Collection, Generic, Hashable, Iterable, Mapping, Sequence, Type, TypedDict, TypeVar, cast, ) from uuid import UUID from faker import Faker from typing_extensions import get_args, get_origin, get_original_bases from polyfactory.constants import ( DEFAULT_RANDOM, MAX_COLLECTION_LENGTH, MIN_COLLECTION_LENGTH, RANDOMIZE_COLLECTION_LENGTH, ) from polyfactory.exceptions import ConfigurationException, MissingBuildKwargException, ParameterException from polyfactory.field_meta import Null from polyfactory.fields import Fixture, Ignore, PostGenerated, Require, Use from polyfactory.utils.helpers import ( flatten_annotation, get_collection_type, unwrap_annotation, unwrap_args, unwrap_optional, ) from polyfactory.utils.model_coverage import CoverageContainer, CoverageContainerCallable, resolve_kwargs_coverage from polyfactory.utils.predicates import get_type_origin, is_literal, is_optional, is_safe_subclass, is_union from polyfactory.utils.types import NoneType from polyfactory.value_generators.complex_types import handle_collection_type, handle_collection_type_coverage from polyfactory.value_generators.constrained_collections import ( handle_constrained_collection, handle_constrained_mapping, ) from polyfactory.value_generators.constrained_dates import handle_constrained_date from polyfactory.value_generators.constrained_numbers import ( handle_constrained_decimal, handle_constrained_float, handle_constrained_int, ) from polyfactory.value_generators.constrained_path import handle_constrained_path from polyfactory.value_generators.constrained_strings import handle_constrained_string_or_bytes from polyfactory.value_generators.constrained_url import handle_constrained_url from polyfactory.value_generators.constrained_uuid import handle_constrained_uuid from polyfactory.value_generators.primitives import create_random_boolean, create_random_bytes, create_random_string if TYPE_CHECKING: from typing_extensions import TypeGuard from polyfactory.field_meta import Constraints, FieldMeta from polyfactory.persistence import AsyncPersistenceProtocol, SyncPersistenceProtocol T = TypeVar("T") F = TypeVar("F", bound="BaseFactory[Any]") class BuildContext(TypedDict): seen_models: set[type] class BaseFactory(ABC, Generic[T]): """Base Factory class - this class holds the main logic of the library""" # configuration attributes __model__: type[T] """ The model for the factory. This attribute is required for non-base factories and an exception will be raised if it's not set. Can be automatically inferred from the factory generic argument. """ __check_model__: bool = False """ Flag dictating whether to check if fields defined on the factory exists on the model or not. If 'True', checks will be done against Use, PostGenerated, Ignore, Require constructs fields only. """ __allow_none_optionals__: ClassVar[bool] = True """ Flag dictating whether to allow 'None' for optional values. If 'True', 'None' will be randomly generated as a value for optional model fields """ __sync_persistence__: type[SyncPersistenceProtocol[T]] | SyncPersistenceProtocol[T] | None = None """A sync persistence handler. Can be a class or a class instance.""" __async_persistence__: type[AsyncPersistenceProtocol[T]] | AsyncPersistenceProtocol[T] | None = None """An async persistence handler. Can be a class or a class instance.""" __set_as_default_factory_for_type__ = False """ Flag dictating whether to set as the default factory for the given type. If 'True' the factory will be used instead of dynamically generating a factory for the type. """ __is_base_factory__: bool = False """ Flag dictating whether the factory is a 'base' factory. Base factories are registered globally as handlers for types. For example, the 'DataclassFactory', 'TypedDictFactory' and 'ModelFactory' are all base factories. """ __base_factory_overrides__: dict[Any, type[BaseFactory[Any]]] | None = None """ A base factory to override with this factory. If this value is set, the given factory will replace the given base factory. Note: this value can only be set when '__is_base_factory__' is 'True'. """ __faker__: ClassVar["Faker"] = Faker() """ A faker instance to use. Can be a user provided value. """ __random__: ClassVar["Random"] = DEFAULT_RANDOM """ An instance of 'random.Random' to use. """ __random_seed__: ClassVar[int] """ An integer to seed the factory's Faker and Random instances with. This attribute can be used to control random generation. """ __randomize_collection_length__: ClassVar[bool] = RANDOMIZE_COLLECTION_LENGTH """ Flag dictating whether to randomize collections lengths. """ __min_collection_length__: ClassVar[int] = MIN_COLLECTION_LENGTH """ An integer value that defines minimum length of a collection. """ __max_collection_length__: ClassVar[int] = MAX_COLLECTION_LENGTH """ An integer value that defines maximum length of a collection. """ __use_defaults__: ClassVar[bool] = False """ Flag indicating whether to use the default value on a specific field, if provided. """ __config_keys__: tuple[str, ...] = ( "__check_model__", "__allow_none_optionals__", "__set_as_default_factory_for_type__", "__faker__", "__random__", "__randomize_collection_length__", "__min_collection_length__", "__max_collection_length__", "__use_defaults__", ) """Keys to be considered as config values to pass on to dynamically created factories.""" # cached attributes _fields_metadata: list[FieldMeta] # BaseFactory only attributes _factory_type_mapping: ClassVar[dict[Any, type[BaseFactory[Any]]]] _base_factories: ClassVar[list[type[BaseFactory[Any]]]] # Non-public attributes _extra_providers: dict[Any, Callable[[], Any]] | None = None def __init_subclass__(cls, *args: Any, **kwargs: Any) -> None: # noqa: C901 super().__init_subclass__(*args, **kwargs) if not hasattr(BaseFactory, "_base_factories"): BaseFactory._base_factories = [] if not hasattr(BaseFactory, "_factory_type_mapping"): BaseFactory._factory_type_mapping = {} if cls.__min_collection_length__ > cls.__max_collection_length__: msg = "Minimum collection length shouldn't be greater than maximum collection length" raise ConfigurationException( msg, ) if "__is_base_factory__" not in cls.__dict__ or not cls.__is_base_factory__: model: type[T] | None = getattr(cls, "__model__", None) or cls._infer_model_type() if not model: msg = f"required configuration attribute '__model__' is not set on {cls.__name__}" raise ConfigurationException( msg, ) cls.__model__ = model if not cls.is_supported_type(model): for factory in BaseFactory._base_factories: if factory.is_supported_type(model): msg = f"{cls.__name__} does not support {model.__name__}, but this type is supported by the {factory.__name__} base factory class. To resolve this error, subclass the factory from {factory.__name__} instead of {cls.__name__}" raise ConfigurationException( msg, ) msg = f"Model type {model.__name__} is not supported. To support it, register an appropriate base factory and subclass it for your factory." raise ConfigurationException( msg, ) if cls.__check_model__: cls._check_declared_fields_exist_in_model() else: BaseFactory._base_factories.append(cls) random_seed = getattr(cls, "__random_seed__", None) if random_seed is not None: cls.seed_random(random_seed) if cls.__set_as_default_factory_for_type__ and hasattr(cls, "__model__"): BaseFactory._factory_type_mapping[cls.__model__] = cls @classmethod def _get_build_context(cls, build_context: BuildContext | None) -> BuildContext: """Return a BuildContext instance. :returns: BuildContext """ if build_context is None: return {"seen_models": set()} return copy.deepcopy(build_context) @classmethod def _infer_model_type(cls: type[F]) -> type[T] | None: """Return model type inferred from class declaration. class Foo(ModelFactory[MyModel]): # <<< MyModel ... If more than one base class and/or generic arguments specified return None. :returns: Inferred model type or None """ factory_bases: Iterable[type[BaseFactory[T]]] = ( b for b in get_original_bases(cls) if get_origin(b) and issubclass(get_origin(b), BaseFactory) ) generic_args: Sequence[type[T]] = [ arg for factory_base in factory_bases for arg in get_args(factory_base) if not isinstance(arg, TypeVar) ] if len(generic_args) != 1: return None return generic_args[0] @classmethod def _get_sync_persistence(cls) -> SyncPersistenceProtocol[T]: """Return a SyncPersistenceHandler if defined for the factory, otherwise raises a ConfigurationException. :raises: ConfigurationException :returns: SyncPersistenceHandler """ if cls.__sync_persistence__: return cls.__sync_persistence__() if callable(cls.__sync_persistence__) else cls.__sync_persistence__ msg = "A '__sync_persistence__' handler must be defined in the factory to use this method" raise ConfigurationException( msg, ) @classmethod def _get_async_persistence(cls) -> AsyncPersistenceProtocol[T]: """Return a AsyncPersistenceHandler if defined for the factory, otherwise raises a ConfigurationException. :raises: ConfigurationException :returns: AsyncPersistenceHandler """ if cls.__async_persistence__: return cls.__async_persistence__() if callable(cls.__async_persistence__) else cls.__async_persistence__ msg = "An '__async_persistence__' handler must be defined in the factory to use this method" raise ConfigurationException( msg, ) @classmethod def _handle_factory_field( # noqa: PLR0911 cls, field_value: Any, build_context: BuildContext, field_build_parameters: Any | None = None, ) -> Any: """Handle a value defined on the factory class itself. :param field_value: A value defined as an attribute on the factory class. :param field_build_parameters: Any build parameters passed to the factory as kwarg values. :returns: An arbitrary value correlating with the given field_meta value. """ if is_safe_subclass(field_value, BaseFactory): if isinstance(field_build_parameters, Mapping): return field_value.build(_build_context=build_context, **field_build_parameters) if isinstance(field_build_parameters, Sequence): return [ field_value.build(_build_context=build_context, **parameter) for parameter in field_build_parameters ] return field_value.build(_build_context=build_context) if isinstance(field_value, Use): return field_value.to_value() if isinstance(field_value, Fixture): return field_value.to_value() if callable(field_value): return field_value() return field_value if isinstance(field_value, Hashable) else copy.deepcopy(field_value) @classmethod def _handle_factory_field_coverage( cls, field_value: Any, field_build_parameters: Any | None = None, build_context: BuildContext | None = None, ) -> Any: """Handle a value defined on the factory class itself. :param field_value: A value defined as an attribute on the factory class. :param field_build_parameters: Any build parameters passed to the factory as kwarg values. :returns: An arbitrary value correlating with the given field_meta value. """ if is_safe_subclass(field_value, BaseFactory): if isinstance(field_build_parameters, Mapping): return CoverageContainer(field_value.coverage(_build_context=build_context, **field_build_parameters)) if isinstance(field_build_parameters, Sequence): return [ CoverageContainer(field_value.coverage(_build_context=build_context, **parameter)) for parameter in field_build_parameters ] return CoverageContainer(field_value.coverage()) if isinstance(field_value, Use): return field_value.to_value() if isinstance(field_value, Fixture): return CoverageContainerCallable(field_value.to_value) return CoverageContainerCallable(field_value) if callable(field_value) else field_value @classmethod def _get_config(cls) -> dict[str, Any]: return { **{key: getattr(cls, key) for key in cls.__config_keys__}, "_extra_providers": cls.get_provider_map(), } @classmethod def _get_or_create_factory(cls, model: type) -> type[BaseFactory[Any]]: """Get a factory from registered factories or generate a factory dynamically. :param model: A model type. :returns: A Factory sub-class. """ if factory := BaseFactory._factory_type_mapping.get(model): return factory config = cls._get_config() if cls.__base_factory_overrides__: for model_ancestor in model.mro(): if factory := cls.__base_factory_overrides__.get(model_ancestor): return factory.create_factory(model, **config) for factory in reversed(BaseFactory._base_factories): if factory.is_supported_type(model): return factory.create_factory(model, **config) msg = f"unsupported model type {model.__name__}" raise ParameterException(msg) # pragma: no cover # Public Methods @classmethod def is_factory_type(cls, annotation: Any) -> bool: """Determine whether a given field is annotated with a type that is supported by a base factory. :param annotation: A type annotation. :returns: Boolean dictating whether the annotation is a factory type """ return any(factory.is_supported_type(annotation) for factory in BaseFactory._base_factories) @classmethod def is_batch_factory_type(cls, annotation: Any) -> bool: """Determine whether a given field is annotated with a sequence of supported factory types. :param annotation: A type annotation. :returns: Boolean dictating whether the annotation is a batch factory type """ origin = get_type_origin(annotation) or annotation if is_safe_subclass(origin, Sequence) and (args := unwrap_args(annotation, random=cls.__random__)): return len(args) == 1 and BaseFactory.is_factory_type(annotation=args[0]) return False @classmethod def extract_field_build_parameters(cls, field_meta: FieldMeta, build_args: dict[str, Any]) -> Any: """Extract from the build kwargs any build parameters passed for a given field meta - if it is a factory type. :param field_meta: A field meta instance. :param build_args: Any kwargs passed to the factory. :returns: Any values """ if build_arg := build_args.get(field_meta.name): annotation = unwrap_optional(field_meta.annotation) if ( BaseFactory.is_factory_type(annotation=annotation) and isinstance(build_arg, Mapping) and not BaseFactory.is_factory_type(annotation=type(build_arg)) ): return build_args.pop(field_meta.name) if ( BaseFactory.is_batch_factory_type(annotation=annotation) and isinstance(build_arg, Sequence) and not any(BaseFactory.is_factory_type(annotation=type(value)) for value in build_arg) ): return build_args.pop(field_meta.name) return None @classmethod @abstractmethod def is_supported_type(cls, value: Any) -> "TypeGuard[type[T]]": # pragma: no cover """Determine whether the given value is supported by the factory. :param value: An arbitrary value. :returns: A typeguard """ raise NotImplementedError @classmethod def seed_random(cls, seed: int) -> None: """Seed faker and random with the given integer. :param seed: An integer to set as seed. :returns: 'None' """ cls.__random__ = Random(seed) cls.__faker__.seed_instance(seed) @classmethod def is_ignored_type(cls, value: Any) -> bool: """Check whether a given value is an ignored type. :param value: An arbitrary value. :notes: - This method is meant to be overwritten by extension factories and other subclasses :returns: A boolean determining whether the value should be ignored. """ return value is None @classmethod def get_provider_map(cls) -> dict[Any, Callable[[], Any]]: """Map types to callables. :notes: - This method is distinct to allow overriding. :returns: a dictionary mapping types to callables. """ def _create_generic_fn() -> Callable: """Return a generic lambda""" return lambda *args: None return { Any: lambda: create_random_string(cls.__random__, min_length=1, max_length=10), # primitives object: object, float: cls.__faker__.pyfloat, int: cls.__faker__.pyint, bool: cls.__faker__.pybool, str: cls.__faker__.pystr, bytes: partial(create_random_bytes, cls.__random__), # built-in objects dict: cls.__faker__.pydict, tuple: cls.__faker__.pytuple, list: cls.__faker__.pylist, set: cls.__faker__.pyset, frozenset: lambda: frozenset(cls.__faker__.pylist()), deque: lambda: deque(cls.__faker__.pylist()), # standard library objects Path: lambda: Path(realpath(__file__)), Decimal: cls.__faker__.pydecimal, UUID: lambda: UUID(str(cls.__faker__.uuid4())), # datetime datetime: cls.__faker__.date_time_between, date: cls.__faker__.date_this_decade, time: cls.__faker__.time_object, timedelta: cls.__faker__.time_delta, # ip addresses IPv4Address: lambda: ip_address(cls.__faker__.ipv4()), IPv4Interface: lambda: ip_interface(cls.__faker__.ipv4()), IPv4Network: lambda: ip_network(cls.__faker__.ipv4(network=True)), IPv6Address: lambda: ip_address(cls.__faker__.ipv6()), IPv6Interface: lambda: ip_interface(cls.__faker__.ipv6()), IPv6Network: lambda: ip_network(cls.__faker__.ipv6(network=True)), # types Callable: _create_generic_fn, abc.Callable: _create_generic_fn, Counter: lambda: Counter(cls.__faker__.pystr()), **(cls._extra_providers or {}), } @classmethod def create_factory( cls: type[F], model: type[T] | None = None, bases: tuple[type[BaseFactory[Any]], ...] | None = None, **kwargs: Any, ) -> type[F]: """Generate a factory for the given type dynamically. :param model: A type to model. Defaults to current factory __model__ if any. Otherwise, raise an error :param bases: Base classes to use when generating the new class. :param kwargs: Any kwargs. :returns: A 'ModelFactory' subclass. """ if model is None: try: model = cls.__model__ except AttributeError as ex: msg = "A 'model' argument is required when creating a new factory from a base one" raise TypeError(msg) from ex return cast( "Type[F]", type( f"{model.__name__}Factory", # pyright: ignore[reportOptionalMemberAccess] (*(bases or ()), cls), {"__model__": model, **kwargs}, ), ) @classmethod def get_constrained_field_value( # noqa: C901, PLR0911 cls, annotation: Any, field_meta: FieldMeta, field_build_parameters: Any | None = None, build_context: BuildContext | None = None, ) -> Any: try: constraints = cast("Constraints", field_meta.constraints) if is_safe_subclass(annotation, float): return handle_constrained_float( random=cls.__random__, multiple_of=cast("Any", constraints.get("multiple_of")), gt=cast("Any", constraints.get("gt")), ge=cast("Any", constraints.get("ge")), lt=cast("Any", constraints.get("lt")), le=cast("Any", constraints.get("le")), ) if is_safe_subclass(annotation, int): return handle_constrained_int( random=cls.__random__, multiple_of=cast("Any", constraints.get("multiple_of")), gt=cast("Any", constraints.get("gt")), ge=cast("Any", constraints.get("ge")), lt=cast("Any", constraints.get("lt")), le=cast("Any", constraints.get("le")), ) if is_safe_subclass(annotation, Decimal): return handle_constrained_decimal( random=cls.__random__, decimal_places=cast("Any", constraints.get("decimal_places")), max_digits=cast("Any", constraints.get("max_digits")), multiple_of=cast("Any", constraints.get("multiple_of")), gt=cast("Any", constraints.get("gt")), ge=cast("Any", constraints.get("ge")), lt=cast("Any", constraints.get("lt")), le=cast("Any", constraints.get("le")), ) if url_constraints := constraints.get("url"): return handle_constrained_url(constraints=url_constraints) if is_safe_subclass(annotation, str) or is_safe_subclass(annotation, bytes): return handle_constrained_string_or_bytes( random=cls.__random__, t_type=str if is_safe_subclass(annotation, str) else bytes, lower_case=constraints.get("lower_case") or False, upper_case=constraints.get("upper_case") or False, min_length=constraints.get("min_length"), max_length=constraints.get("max_length"), pattern=constraints.get("pattern"), ) try: collection_type = get_collection_type(annotation) except ValueError: collection_type = None if collection_type is not None: if collection_type is dict: return handle_constrained_mapping( factory=cls, field_meta=field_meta, min_items=constraints.get("min_length"), max_items=constraints.get("max_length"), field_build_parameters=field_build_parameters, build_context=build_context, ) return handle_constrained_collection( collection_type=collection_type, # type: ignore[type-var] factory=cls, field_meta=field_meta.children[0] if field_meta.children else field_meta, item_type=constraints.get("item_type"), max_items=constraints.get("max_length"), min_items=constraints.get("min_length"), unique_items=constraints.get("unique_items", False), field_build_parameters=field_build_parameters, build_context=build_context, ) if is_safe_subclass(annotation, date): return handle_constrained_date( faker=cls.__faker__, ge=cast("Any", constraints.get("ge")), gt=cast("Any", constraints.get("gt")), le=cast("Any", constraints.get("le")), lt=cast("Any", constraints.get("lt")), tz=cast("Any", constraints.get("tz")), ) if is_safe_subclass(annotation, UUID) and (uuid_version := constraints.get("uuid_version")): return handle_constrained_uuid( uuid_version=uuid_version, faker=cls.__faker__, ) if is_safe_subclass(annotation, Path) and (path_constraint := constraints.get("path_type")): return handle_constrained_path(constraint=path_constraint, faker=cls.__faker__) except TypeError as e: raise ParameterException from e msg = f"received constraints for unsupported type {annotation}" raise ParameterException(msg) @classmethod def get_field_value( # noqa: C901, PLR0911, PLR0912 cls, field_meta: FieldMeta, field_build_parameters: Any | None = None, build_context: BuildContext | None = None, ) -> Any: """Return a field value on the subclass if existing, otherwise returns a mock value. :param field_meta: FieldMeta instance. :param field_build_parameters: Any build parameters passed to the factory as kwarg values. :param build_context: BuildContext data for current build. :returns: An arbitrary value. """ build_context = cls._get_build_context(build_context) if cls.is_ignored_type(field_meta.annotation): return None if field_build_parameters is None and cls.should_set_none_value(field_meta=field_meta): return None unwrapped_annotation = unwrap_annotation(field_meta.annotation, random=cls.__random__) if is_literal(annotation=unwrapped_annotation) and (literal_args := get_args(unwrapped_annotation)): return cls.__random__.choice(literal_args) if isinstance(unwrapped_annotation, EnumMeta): return cls.__random__.choice(list(unwrapped_annotation)) if field_meta.constraints: return cls.get_constrained_field_value( annotation=unwrapped_annotation, field_meta=field_meta, field_build_parameters=field_build_parameters, build_context=build_context, ) if is_union(field_meta.annotation) and field_meta.children: seen_models = build_context["seen_models"] children = [child for child in field_meta.children if child.annotation not in seen_models] # `None` is removed from the children when creating FieldMeta so when `children` # is empty, it must mean that the field meta is an optional type. if not children: return None return cls.get_field_value(cls.__random__.choice(children), field_build_parameters, build_context) if BaseFactory.is_factory_type(annotation=unwrapped_annotation): if not field_build_parameters and unwrapped_annotation in build_context["seen_models"]: return None if is_optional(field_meta.annotation) else Null return cls._get_or_create_factory(model=unwrapped_annotation).build( _build_context=build_context, **(field_build_parameters if isinstance(field_build_parameters, Mapping) else {}), ) if BaseFactory.is_batch_factory_type(annotation=unwrapped_annotation): factory = cls._get_or_create_factory(model=field_meta.type_args[0]) if isinstance(field_build_parameters, Sequence): return [ factory.build(_build_context=build_context, **field_parameters) for field_parameters in field_build_parameters ] if field_meta.type_args[0] in build_context["seen_models"]: return [] if not cls.__randomize_collection_length__: return [factory.build(_build_context=build_context)] batch_size = cls.__random__.randint(cls.__min_collection_length__, cls.__max_collection_length__) return factory.batch(size=batch_size, _build_context=build_context) if (origin := get_type_origin(unwrapped_annotation)) and is_safe_subclass(origin, Collection): collection_type = get_collection_type(unwrapped_annotation) is_fixed_length = collection_type is tuple and ( not field_meta.children or field_meta.children[-1].annotation != Ellipsis ) if cls.__randomize_collection_length__ and not is_fixed_length: if collection_type is not dict: return handle_constrained_collection( collection_type=collection_type, # type: ignore[type-var] factory=cls, item_type=Any, field_meta=field_meta.children[0] if field_meta.children else field_meta, min_items=cls.__min_collection_length__, max_items=cls.__max_collection_length__, field_build_parameters=field_build_parameters, build_context=build_context, ) return handle_constrained_mapping( factory=cls, field_meta=field_meta, min_items=cls.__min_collection_length__, max_items=cls.__max_collection_length__, field_build_parameters=field_build_parameters, build_context=build_context, ) return handle_collection_type( field_meta, origin, cls, field_build_parameters=field_build_parameters, build_context=build_context, ) if provider := cls.get_provider_map().get(unwrapped_annotation): return provider() if isinstance(unwrapped_annotation, TypeVar): return create_random_string(cls.__random__, min_length=1, max_length=10) if callable(unwrapped_annotation): # if value is a callable we can try to naively call it. # this will work for callables that do not require any parameters passed with suppress(Exception): return unwrapped_annotation() msg = f"Unsupported type: {unwrapped_annotation!r}\n\nEither extend the providers map or add a factory function for this type." raise ParameterException( msg, ) @classmethod def get_field_value_coverage( # noqa: C901,PLR0912 cls, field_meta: FieldMeta, field_build_parameters: Any | None = None, build_context: BuildContext | None = None, ) -> Iterable[Any]: """Return a field value on the subclass if existing, otherwise returns a mock value. :param field_meta: FieldMeta instance. :param field_build_parameters: Any build parameters passed to the factory as kwarg values. :param build_context: BuildContext data for current build. :returns: An iterable of values. """ if cls.is_ignored_type(field_meta.annotation): return for unwrapped_annotation in flatten_annotation(field_meta.annotation): if unwrapped_annotation in (None, NoneType): yield None elif is_literal(annotation=unwrapped_annotation) and (literal_args := get_args(unwrapped_annotation)): yield CoverageContainer(literal_args) elif isinstance(unwrapped_annotation, EnumMeta): yield CoverageContainer(list(unwrapped_annotation)) elif field_meta.constraints: yield CoverageContainerCallable( cls.get_constrained_field_value, annotation=unwrapped_annotation, field_meta=field_meta, ) elif BaseFactory.is_factory_type(annotation=unwrapped_annotation): yield CoverageContainer( cls._get_or_create_factory(model=unwrapped_annotation).coverage( _build_context=build_context, **(field_build_parameters if isinstance(field_build_parameters, Mapping) else {}), ), ) elif (origin := get_type_origin(unwrapped_annotation)) and issubclass(origin, Collection): if not field_meta.children: msg = "A subclass of Collection should always have children in it's field_meta" raise ParameterException(msg) # We actually want to use the parent in cases where the collection is the parent # such as tuple so default to the parent if this annotation is not present in the children child_meta = next( (meta for meta in field_meta.children if meta.annotation == unwrapped_annotation), field_meta, ) yield handle_collection_type_coverage(child_meta, origin, cls, build_context=build_context) elif provider := cls.get_provider_map().get(unwrapped_annotation): yield CoverageContainerCallable(provider) elif isinstance(unwrapped_annotation, TypeVar): yield create_random_string(cls.__random__, min_length=1, max_length=10) elif callable(unwrapped_annotation): # if value is a callable we can try to naively call it. # this will work for callables that do not require any parameters passed yield CoverageContainerCallable(unwrapped_annotation) else: msg = f"Unsupported type: {unwrapped_annotation!r}\n\nEither extend the providers map or add a factory function for this type." raise ParameterException( msg, ) @classmethod def should_set_none_value(cls, field_meta: FieldMeta) -> bool: """Determine whether a given model field_meta should be set to None. :param field_meta: Field metadata. :notes: - This method is distinct to allow overriding. :returns: A boolean determining whether 'None' should be set for the given field_meta. """ return ( cls.__allow_none_optionals__ and is_optional(field_meta.annotation) and create_random_boolean(random=cls.__random__) ) @classmethod def should_use_default_value(cls, field_meta: FieldMeta) -> bool: """Determine whether to use the default value for the given field. :param field_meta: FieldMeta instance. :notes: - This method is distinct to allow overriding. :returns: A boolean determining whether the default value should be used for the given field_meta. """ return cls.__use_defaults__ and field_meta.default is not Null @classmethod def should_set_field_value(cls, field_meta: FieldMeta, **kwargs: Any) -> bool: """Determine whether to set a value for a given field_name. :param field_meta: FieldMeta instance. :param kwargs: Any kwargs passed to the factory. :notes: - This method is distinct to allow overriding. :returns: A boolean determining whether a value should be set for the given field_meta. """ return not field_meta.name.startswith("_") and field_meta.name not in kwargs @classmethod @abstractmethod def get_model_fields(cls) -> list[FieldMeta]: # pragma: no cover """Retrieve a list of fields from the factory's model. :returns: A list of field MetaData instances. """ raise NotImplementedError @classmethod def get_factory_fields(cls) -> list[tuple[str, Any]]: """Retrieve a list of fields from the factory. Trying to be smart about what should be considered a field on the model, ignoring dunder methods and some parent class attributes. :returns: A list of tuples made of field name and field definition """ factory_fields = cls.__dict__.items() return [ (field_name, field_value) for field_name, field_value in factory_fields if not (field_name.startswith("__") or field_name == "_abc_impl") ] @classmethod def _check_declared_fields_exist_in_model(cls) -> None: model_fields_names = {field_meta.name for field_meta in cls.get_model_fields()} factory_fields = cls.get_factory_fields() for field_name, field_value in factory_fields: if field_name in model_fields_names: continue error_message = ( f"{field_name} is declared on the factory {cls.__name__}" f" but it is not part of the model {cls.__model__.__name__}" ) if isinstance(field_value, (Use, PostGenerated, Ignore, Require)): raise ConfigurationException(error_message) @classmethod def process_kwargs(cls, **kwargs: Any) -> dict[str, Any]: """Process the given kwargs and generate values for the factory's model. :param kwargs: Any build kwargs. :returns: A dictionary of build results. """ _build_context = cls._get_build_context(kwargs.pop("_build_context", None)) _build_context["seen_models"].add(cls.__model__) result: dict[str, Any] = {**kwargs} generate_post: dict[str, PostGenerated] = {} for field_meta in cls.get_model_fields(): field_build_parameters = cls.extract_field_build_parameters(field_meta=field_meta, build_args=kwargs) if cls.should_set_field_value(field_meta, **kwargs) and not cls.should_use_default_value(field_meta): if hasattr(cls, field_meta.name) and not hasattr(BaseFactory, field_meta.name): field_value = getattr(cls, field_meta.name) if isinstance(field_value, Ignore): continue if isinstance(field_value, Require) and field_meta.name not in kwargs: msg = f"Require kwarg {field_meta.name} is missing" raise MissingBuildKwargException(msg) if isinstance(field_value, PostGenerated): generate_post[field_meta.name] = field_value continue result[field_meta.name] = cls._handle_factory_field( field_value=field_value, field_build_parameters=field_build_parameters, build_context=_build_context, ) continue field_result = cls.get_field_value( field_meta, field_build_parameters=field_build_parameters, build_context=_build_context, ) if field_result is Null: continue result[field_meta.name] = field_result for field_name, post_generator in generate_post.items(): result[field_name] = post_generator.to_value(field_name, result) return result @classmethod def process_kwargs_coverage(cls, **kwargs: Any) -> abc.Iterable[dict[str, Any]]: """Process the given kwargs and generate values for the factory's model. :param kwargs: Any build kwargs. :param build_context: BuildContext data for current build. :returns: A dictionary of build results. """ _build_context = cls._get_build_context(kwargs.pop("_build_context", None)) _build_context["seen_models"].add(cls.__model__) result: dict[str, Any] = {**kwargs} generate_post: dict[str, PostGenerated] = {} for field_meta in cls.get_model_fields(): field_build_parameters = cls.extract_field_build_parameters(field_meta=field_meta, build_args=kwargs) if cls.should_set_field_value(field_meta, **kwargs): if hasattr(cls, field_meta.name) and not hasattr(BaseFactory, field_meta.name): field_value = getattr(cls, field_meta.name) if isinstance(field_value, Ignore): continue if isinstance(field_value, Require) and field_meta.name not in kwargs: msg = f"Require kwarg {field_meta.name} is missing" raise MissingBuildKwargException(msg) if isinstance(field_value, PostGenerated): generate_post[field_meta.name] = field_value continue result[field_meta.name] = cls._handle_factory_field_coverage( field_value=field_value, field_build_parameters=field_build_parameters, build_context=_build_context, ) continue result[field_meta.name] = CoverageContainer( cls.get_field_value_coverage( field_meta, field_build_parameters=field_build_parameters, build_context=_build_context, ), ) for resolved in resolve_kwargs_coverage(result): for field_name, post_generator in generate_post.items(): resolved[field_name] = post_generator.to_value(field_name, resolved) yield resolved @classmethod def build(cls, **kwargs: Any) -> T: """Build an instance of the factory's __model__ :param kwargs: Any kwargs. If field names are set in kwargs, their values will be used. :returns: An instance of type T. """ return cast("T", cls.__model__(**cls.process_kwargs(**kwargs))) @classmethod def batch(cls, size: int, **kwargs: Any) -> list[T]: """Build a batch of size n of the factory's Meta.model. :param size: Size of the batch. :param kwargs: Any kwargs. If field_meta names are set in kwargs, their values will be used. :returns: A list of instances of type T. """ return [cls.build(**kwargs) for _ in range(size)] @classmethod def coverage(cls, **kwargs: Any) -> abc.Iterator[T]: """Build a batch of the factory's Meta.model will full coverage of the sub-types of the model. :param kwargs: Any kwargs. If field_meta names are set in kwargs, their values will be used. :returns: A iterator of instances of type T. """ for data in cls.process_kwargs_coverage(**kwargs): instance = cls.__model__(**data) yield cast("T", instance) @classmethod def create_sync(cls, **kwargs: Any) -> T: """Build and persists synchronously a single model instance. :param kwargs: Any kwargs. If field_meta names are set in kwargs, their values will be used. :returns: An instance of type T. """ return cls._get_sync_persistence().save(data=cls.build(**kwargs)) @classmethod def create_batch_sync(cls, size: int, **kwargs: Any) -> list[T]: """Build and persists synchronously a batch of n size model instances. :param size: Size of the batch. :param kwargs: Any kwargs. If field_meta names are set in kwargs, their values will be used. :returns: A list of instances of type T. """ return cls._get_sync_persistence().save_many(data=cls.batch(size, **kwargs)) @classmethod async def create_async(cls, **kwargs: Any) -> T: """Build and persists asynchronously a single model instance. :param kwargs: Any kwargs. If field_meta names are set in kwargs, their values will be used. :returns: An instance of type T. """ return await cls._get_async_persistence().save(data=cls.build(**kwargs)) @classmethod async def create_batch_async(cls, size: int, **kwargs: Any) -> list[T]: """Build and persists asynchronously a batch of n size model instances. :param size: Size of the batch. :param kwargs: Any kwargs. If field_meta names are set in kwargs, their values will be used. :returns: A list of instances of type T. """ return await cls._get_async_persistence().save_many(data=cls.batch(size, **kwargs)) def _register_builtin_factories() -> None: """This function is used to register the base factories, if present. :returns: None """ import polyfactory.factories.dataclass_factory import polyfactory.factories.typed_dict_factory # noqa: F401 for module in [ "polyfactory.factories.pydantic_factory", "polyfactory.factories.beanie_odm_factory", "polyfactory.factories.odmantic_odm_factory", "polyfactory.factories.msgspec_factory", # `AttrsFactory` is not being registered by default since not all versions of `attrs` are supported. # Issue: https://github.com/litestar-org/polyfactory/issues/356 # "polyfactory.factories.attrs_factory", ]: try: import_module(module) except ImportError: # noqa: PERF203 continue _register_builtin_factories() �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/polyfactory/factories/beanie_odm_factory.py�������������������������������0000664�0000000�0000000�00000005753�14721310225�0026221�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from __future__ import annotations from typing import TYPE_CHECKING, Any, Generic, TypeVar from typing_extensions import get_args from polyfactory.exceptions import MissingDependencyException from polyfactory.factories.pydantic_factory import ModelFactory from polyfactory.persistence import AsyncPersistenceProtocol from polyfactory.utils.predicates import is_safe_subclass if TYPE_CHECKING: from typing_extensions import TypeGuard from polyfactory.factories.base import BuildContext from polyfactory.field_meta import FieldMeta try: from beanie import Document except ImportError as e: msg = "beanie is not installed" raise MissingDependencyException(msg) from e T = TypeVar("T", bound=Document) class BeaniePersistenceHandler(Generic[T], AsyncPersistenceProtocol[T]): """Persistence Handler using beanie logic""" async def save(self, data: T) -> T: """Persist a single instance in mongoDB.""" return await data.insert() # pyright: ignore[reportGeneralTypeIssues] async def save_many(self, data: list[T]) -> list[T]: """Persist multiple instances in mongoDB. .. note:: we cannot use the ``.insert_many`` method from Beanie here because it doesn't return the created instances """ return [await doc.insert() for doc in data] # pyright: ignore[reportGeneralTypeIssues] class BeanieDocumentFactory(Generic[T], ModelFactory[T]): """Base factory for Beanie Documents""" __async_persistence__ = BeaniePersistenceHandler __is_base_factory__ = True @classmethod def is_supported_type(cls, value: Any) -> "TypeGuard[type[T]]": """Determine whether the given value is supported by the factory. :param value: An arbitrary value. :returns: A typeguard """ return is_safe_subclass(value, Document) @classmethod def get_field_value( cls, field_meta: "FieldMeta", field_build_parameters: Any | None = None, build_context: BuildContext | None = None, ) -> Any: """Return a field value on the subclass if existing, otherwise returns a mock value. :param field_meta: FieldMeta instance. :param field_build_parameters: Any build parameters passed to the factory as kwarg values. :param build_context: BuildContext instance. :returns: An arbitrary value. """ if hasattr(field_meta.annotation, "__name__"): if "Indexed " in field_meta.annotation.__name__: base_type = field_meta.annotation.__bases__[0] field_meta.annotation = base_type if "Link" in field_meta.annotation.__name__: link_class = get_args(field_meta.annotation)[0] field_meta.annotation = link_class field_meta.annotation = link_class return super().get_field_value( field_meta=field_meta, field_build_parameters=field_build_parameters, build_context=build_context, ) ���������������������python-polyfactory-2.18.1/polyfactory/factories/dataclass_factory.py��������������������������������0000664�0000000�0000000�00000003313�14721310225�0026064�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from __future__ import annotations from dataclasses import MISSING, fields, is_dataclass from typing import Any, Generic from typing_extensions import TypeGuard, get_type_hints from polyfactory.factories.base import BaseFactory, T from polyfactory.field_meta import FieldMeta, Null class DataclassFactory(Generic[T], BaseFactory[T]): """Dataclass base factory""" __is_base_factory__ = True @classmethod def is_supported_type(cls, value: Any) -> TypeGuard[type[T]]: """Determine whether the given value is supported by the factory. :param value: An arbitrary value. :returns: A typeguard """ return bool(is_dataclass(value)) @classmethod def get_model_fields(cls) -> list["FieldMeta"]: """Retrieve a list of fields from the factory's model. :returns: A list of field MetaData instances. """ fields_meta: list["FieldMeta"] = [] model_type_hints = get_type_hints(cls.__model__, include_extras=True) for field in fields(cls.__model__): # type: ignore[arg-type] if not field.init: continue if field.default_factory and field.default_factory is not MISSING: default_value = field.default_factory() elif field.default is not MISSING: default_value = field.default else: default_value = Null fields_meta.append( FieldMeta.from_type( annotation=model_type_hints[field.name], name=field.name, default=default_value, random=cls.__random__, ), ) return fields_meta ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/polyfactory/factories/msgspec_factory.py����������������������������������0000664�0000000�0000000�00000004640�14721310225�0025572�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from __future__ import annotations from inspect import isclass from typing import TYPE_CHECKING, Any, Callable, Generic, TypeVar from typing_extensions import get_type_hints from polyfactory.exceptions import MissingDependencyException from polyfactory.factories.base import BaseFactory from polyfactory.field_meta import FieldMeta, Null from polyfactory.value_generators.constrained_numbers import handle_constrained_int from polyfactory.value_generators.primitives import create_random_bytes if TYPE_CHECKING: from typing_extensions import TypeGuard try: import msgspec from msgspec.structs import fields except ImportError as e: msg = "msgspec is not installed" raise MissingDependencyException(msg) from e T = TypeVar("T", bound=msgspec.Struct) class MsgspecFactory(Generic[T], BaseFactory[T]): """Base factory for msgspec Structs.""" __is_base_factory__ = True @classmethod def get_provider_map(cls) -> dict[Any, Callable[[], Any]]: def get_msgpack_ext() -> msgspec.msgpack.Ext: code = handle_constrained_int(cls.__random__, ge=-128, le=127) data = create_random_bytes(cls.__random__) return msgspec.msgpack.Ext(code, data) msgspec_provider_map = {msgspec.UnsetType: lambda: msgspec.UNSET, msgspec.msgpack.Ext: get_msgpack_ext} provider_map = super().get_provider_map() provider_map.update(msgspec_provider_map) return provider_map @classmethod def is_supported_type(cls, value: Any) -> TypeGuard[type[T]]: return isclass(value) and hasattr(value, "__struct_fields__") @classmethod def get_model_fields(cls) -> list[FieldMeta]: fields_meta: list[FieldMeta] = [] type_hints = get_type_hints(cls.__model__, include_extras=True) for field in fields(cls.__model__): annotation = type_hints[field.name] if field.default is not msgspec.NODEFAULT: default_value = field.default elif field.default_factory is not msgspec.NODEFAULT: default_value = field.default_factory() else: default_value = Null fields_meta.append( FieldMeta.from_type( annotation=annotation, name=field.name, default=default_value, random=cls.__random__, ), ) return fields_meta ������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/polyfactory/factories/odmantic_odm_factory.py�����������������������������0000664�0000000�0000000�00000004237�14721310225�0026570�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from __future__ import annotations import decimal from typing import TYPE_CHECKING, Any, Callable, Generic, TypeVar, Union from polyfactory.exceptions import MissingDependencyException from polyfactory.factories.pydantic_factory import ModelFactory from polyfactory.utils.predicates import is_safe_subclass from polyfactory.value_generators.primitives import create_random_bytes try: from bson.decimal128 import Decimal128, create_decimal128_context from odmantic import EmbeddedModel, Model from odmantic import bson as odbson except ImportError as e: msg = "odmantic is not installed" raise MissingDependencyException(msg) from e T = TypeVar("T", bound=Union[Model, EmbeddedModel]) if TYPE_CHECKING: from typing_extensions import TypeGuard class OdmanticModelFactory(Generic[T], ModelFactory[T]): """Base factory for odmantic models""" __is_base_factory__ = True @classmethod def is_supported_type(cls, value: Any) -> "TypeGuard[type[T]]": """Determine whether the given value is supported by the factory. :param value: An arbitrary value. :returns: A typeguard """ return is_safe_subclass(value, (Model, EmbeddedModel)) @classmethod def get_provider_map(cls) -> dict[Any, Callable[[], Any]]: provider_map = super().get_provider_map() provider_map.update( { odbson.Int64: lambda: odbson.Int64.validate(cls.__faker__.pyint()), odbson.Decimal128: lambda: _to_decimal128(cls.__faker__.pydecimal()), odbson.Binary: lambda: odbson.Binary.validate(create_random_bytes(cls.__random__)), odbson._datetime: lambda: odbson._datetime.validate(cls.__faker__.date_time_between()), # bson.Regex and bson._Pattern not supported as there is no way to generate # a random regular expression with Faker # bson.Regex: # bson._Pattern: }, ) return provider_map def _to_decimal128(value: decimal.Decimal) -> Decimal128: with decimal.localcontext(create_decimal128_context()) as ctx: return Decimal128(ctx.create_decimal(value)) �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/polyfactory/factories/pydantic_factory.py���������������������������������0000664�0000000�0000000�00000057426�14721310225�0025756�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from __future__ import annotations import copy from contextlib import suppress from datetime import timezone from functools import partial from os.path import realpath from pathlib import Path from typing import TYPE_CHECKING, Any, ClassVar, ForwardRef, Generic, Mapping, Tuple, TypeVar, cast from uuid import NAMESPACE_DNS, uuid1, uuid3, uuid5 from typing_extensions import Literal, get_args, get_origin from polyfactory.collection_extender import CollectionExtender from polyfactory.constants import DEFAULT_RANDOM from polyfactory.exceptions import MissingDependencyException from polyfactory.factories.base import BaseFactory, BuildContext from polyfactory.factories.base import BuildContext as BaseBuildContext from polyfactory.field_meta import Constraints, FieldMeta, Null from polyfactory.utils.deprecation import check_for_deprecated_parameters from polyfactory.utils.helpers import unwrap_new_type, unwrap_optional from polyfactory.utils.predicates import is_optional, is_safe_subclass, is_union from polyfactory.utils.types import NoneType from polyfactory.value_generators.primitives import create_random_bytes try: import pydantic from pydantic import VERSION, Json from pydantic.fields import FieldInfo except ImportError as e: msg = "pydantic is not installed" raise MissingDependencyException(msg) from e try: # pydantic v1 from pydantic import ( # noqa: I001 UUID1, UUID3, UUID4, UUID5, AmqpDsn, AnyHttpUrl, AnyUrl, DirectoryPath, FilePath, HttpUrl, KafkaDsn, PostgresDsn, RedisDsn, ) from pydantic import BaseModel as BaseModelV1 from pydantic.color import Color from pydantic.fields import ( # type: ignore[attr-defined] DeferredType, # pyright: ignore[attr-defined,reportAttributeAccessIssue] ModelField, # pyright: ignore[attr-defined,reportAttributeAccessIssue] Undefined, # pyright: ignore[attr-defined,reportAttributeAccessIssue] ) # Keep this import last to prevent warnings from pydantic if pydantic v2 # is installed. from pydantic import PyObject # prevent unbound variable warnings BaseModelV2 = BaseModelV1 UndefinedV2 = Undefined except ImportError: # pydantic v2 # v2 specific imports from pydantic import BaseModel as BaseModelV2 from pydantic_core import PydanticUndefined as UndefinedV2 from pydantic_core import to_json from pydantic.v1 import ( # v1 compat imports UUID1, UUID3, UUID4, UUID5, AmqpDsn, AnyHttpUrl, AnyUrl, DirectoryPath, FilePath, HttpUrl, KafkaDsn, PostgresDsn, PyObject, RedisDsn, ) from pydantic.v1 import BaseModel as BaseModelV1 # type: ignore[assignment] from pydantic.v1.color import Color # type: ignore[assignment] from pydantic.v1.fields import DeferredType, ModelField, Undefined if TYPE_CHECKING: from collections import abc from random import Random from typing import Callable, Sequence from typing_extensions import NotRequired, TypeGuard T = TypeVar("T", bound="BaseModelV1 | BaseModelV2") # pyright: ignore[reportInvalidTypeForm] _IS_PYDANTIC_V1 = VERSION.startswith("1") class PydanticBuildContext(BaseBuildContext): factory_use_construct: bool class PydanticConstraints(Constraints): """Metadata regarding a Pydantic type constraints, if any""" json: NotRequired[bool] class PydanticFieldMeta(FieldMeta): """Field meta subclass capable of handling pydantic ModelFields""" def __init__( self, *, name: str, annotation: type, random: Random | None = None, default: Any = ..., children: list[FieldMeta] | None = None, constraints: PydanticConstraints | None = None, ) -> None: super().__init__( name=name, annotation=annotation, random=random, default=default, children=children, constraints=constraints, ) @classmethod def from_field_info( cls, field_name: str, field_info: FieldInfo, use_alias: bool, random: Random | None, randomize_collection_length: bool | None = None, min_collection_length: int | None = None, max_collection_length: int | None = None, ) -> PydanticFieldMeta: """Create an instance from a pydantic field info. :param field_name: The name of the field. :param field_info: A pydantic FieldInfo instance. :param use_alias: Whether to use the field alias. :param random: A random.Random instance. :param randomize_collection_length: Whether to randomize collection length. :param min_collection_length: Minimum collection length. :param max_collection_length: Maximum collection length. :returns: A PydanticFieldMeta instance. """ check_for_deprecated_parameters( "2.11.0", parameters=( ("randomize_collection_length", randomize_collection_length), ("min_collection_length", min_collection_length), ("max_collection_length", max_collection_length), ), ) if callable(field_info.default_factory): default_value = field_info.default_factory() else: default_value = field_info.default if field_info.default is not UndefinedV2 else Null annotation = unwrap_new_type(field_info.annotation) children: list[FieldMeta,] | None = None name = field_info.alias if field_info.alias and use_alias else field_name constraints: PydanticConstraints # pydantic v2 does not always propagate metadata for Union types if is_union(annotation): constraints = {} children = [] for arg in get_args(annotation): if arg is NoneType: continue child_field_info = FieldInfo.from_annotation(arg) merged_field_info = FieldInfo.merge_field_infos(field_info, child_field_info) children.append( cls.from_field_info( field_name="", field_info=merged_field_info, use_alias=use_alias, random=random, ), ) else: metadata, is_json = [], False for m in field_info.metadata: if not is_json and isinstance(m, Json): # type: ignore[misc] is_json = True elif m is not None: metadata.append(m) constraints = cast( PydanticConstraints, cls.parse_constraints(metadata=metadata) if metadata else {}, ) if "url" in constraints: # pydantic uses a sentinel value for url constraints annotation = str if is_json: constraints["json"] = True return PydanticFieldMeta.from_type( annotation=annotation, children=children, constraints=cast("Constraints", {k: v for k, v in constraints.items() if v is not None}) or None, default=default_value, name=name, random=random or DEFAULT_RANDOM, ) @classmethod def from_model_field( # pragma: no cover cls, model_field: ModelField, # pyright: ignore[reportGeneralTypeIssues] use_alias: bool, randomize_collection_length: bool | None = None, min_collection_length: int | None = None, max_collection_length: int | None = None, random: Random = DEFAULT_RANDOM, ) -> PydanticFieldMeta: """Create an instance from a pydantic model field. :param model_field: A pydantic ModelField. :param use_alias: Whether to use the field alias. :param randomize_collection_length: A boolean flag whether to randomize collections lengths :param min_collection_length: Minimum number of elements in randomized collection :param max_collection_length: Maximum number of elements in randomized collection :param random: An instance of random.Random. :returns: A PydanticFieldMeta instance. """ check_for_deprecated_parameters( "2.11.0", parameters=( ("randomize_collection_length", randomize_collection_length), ("min_collection_length", min_collection_length), ("max_collection_length", max_collection_length), ), ) if model_field.default is not Undefined: default_value = model_field.default elif callable(model_field.default_factory): default_value = model_field.default_factory() else: default_value = model_field.default if model_field.default is not Undefined else Null name = model_field.alias if model_field.alias and use_alias else model_field.name outer_type = unwrap_new_type(model_field.outer_type_) annotation = ( model_field.outer_type_ if isinstance(model_field.annotation, (DeferredType, ForwardRef)) else unwrap_new_type(model_field.annotation) ) constraints = cast( "Constraints", { "ge": getattr(outer_type, "ge", model_field.field_info.ge), "gt": getattr(outer_type, "gt", model_field.field_info.gt), "le": getattr(outer_type, "le", model_field.field_info.le), "lt": getattr(outer_type, "lt", model_field.field_info.lt), "min_length": ( getattr(outer_type, "min_length", model_field.field_info.min_length) or getattr(outer_type, "min_items", model_field.field_info.min_items) ), "max_length": ( getattr(outer_type, "max_length", model_field.field_info.max_length) or getattr(outer_type, "max_items", model_field.field_info.max_items) ), "pattern": getattr(outer_type, "regex", model_field.field_info.regex), "unique_items": getattr(outer_type, "unique_items", model_field.field_info.unique_items), "decimal_places": getattr(outer_type, "decimal_places", None), "max_digits": getattr(outer_type, "max_digits", None), "multiple_of": getattr(outer_type, "multiple_of", None), "upper_case": getattr(outer_type, "to_upper", None), "lower_case": getattr(outer_type, "to_lower", None), "item_type": getattr(outer_type, "item_type", None), }, ) # pydantic v1 has constraints set for these values, but we generate them using faker if unwrap_optional(annotation) in ( AnyUrl, HttpUrl, KafkaDsn, PostgresDsn, RedisDsn, AmqpDsn, AnyHttpUrl, ): constraints = {} if model_field.field_info.const and ( default_value is None or isinstance(default_value, (int, bool, str, bytes)) ): annotation = Literal[default_value] # pyright: ignore # noqa: PGH003 children: list[FieldMeta] = [] # Refer #412. args = get_args(model_field.annotation) if is_optional(model_field.annotation) and len(args) == 2: # noqa: PLR2004 child_annotation = args[0] if args[0] is not NoneType else args[1] children.append(PydanticFieldMeta.from_type(child_annotation)) elif model_field.key_field or model_field.sub_fields: fields_to_iterate = ( ([model_field.key_field, *model_field.sub_fields]) if model_field.key_field is not None else model_field.sub_fields ) type_args = tuple( ( sub_field.outer_type_ if isinstance(sub_field.annotation, DeferredType) else unwrap_new_type(sub_field.annotation) ) for sub_field in fields_to_iterate ) type_arg_to_sub_field = dict(zip(type_args, fields_to_iterate)) if get_origin(outer_type) in (tuple, Tuple) and get_args(outer_type)[-1] == Ellipsis: # pydantic removes ellipses from Tuples in sub_fields type_args += (...,) extended_type_args = CollectionExtender.extend_type_args(annotation, type_args, 1) children.extend( PydanticFieldMeta.from_model_field( model_field=type_arg_to_sub_field[arg], use_alias=use_alias, random=random, ) for arg in extended_type_args ) return PydanticFieldMeta( name=name, random=random or DEFAULT_RANDOM, annotation=annotation, children=children or None, default=default_value, constraints=cast("PydanticConstraints", {k: v for k, v in constraints.items() if v is not None}) or None, ) if not _IS_PYDANTIC_V1: @classmethod def get_constraints_metadata(cls, annotation: Any) -> Sequence[Any]: metadata = [] for m in super().get_constraints_metadata(annotation): if isinstance(m, FieldInfo): metadata.extend(m.metadata) else: metadata.append(m) return metadata class ModelFactory(Generic[T], BaseFactory[T]): """Base factory for pydantic models""" __forward_ref_resolution_type_mapping__: ClassVar[Mapping[str, type]] = {} __is_base_factory__ = True def __init_subclass__(cls, *args: Any, **kwargs: Any) -> None: super().__init_subclass__(*args, **kwargs) if ( getattr(cls, "__model__", None) and _is_pydantic_v1_model(cls.__model__) and hasattr(cls.__model__, "update_forward_refs") ): with suppress(NameError): # pragma: no cover cls.__model__.update_forward_refs(**cls.__forward_ref_resolution_type_mapping__) # type: ignore[attr-defined] @classmethod def is_supported_type(cls, value: Any) -> TypeGuard[type[T]]: """Determine whether the given value is supported by the factory. :param value: An arbitrary value. :returns: A typeguard """ return _is_pydantic_v1_model(value) or _is_pydantic_v2_model(value) @classmethod def get_model_fields(cls) -> list["FieldMeta"]: """Retrieve a list of fields from the factory's model. :returns: A list of field MetaData instances. """ if "_fields_metadata" not in cls.__dict__: if _is_pydantic_v1_model(cls.__model__): cls._fields_metadata = [ PydanticFieldMeta.from_model_field( field, use_alias=not cls.__model__.__config__.allow_population_by_field_name, # type: ignore[attr-defined] random=cls.__random__, ) for field in cls.__model__.__fields__.values() ] else: cls._fields_metadata = [ PydanticFieldMeta.from_field_info( field_info=field_info, field_name=field_name, random=cls.__random__, use_alias=not cls.__model__.model_config.get( # pyright: ignore[reportGeneralTypeIssues] "populate_by_name", False, ), ) for field_name, field_info in cls.__model__.model_fields.items() # pyright: ignore[reportGeneralTypeIssues] ] return cls._fields_metadata @classmethod def get_constrained_field_value( cls, annotation: Any, field_meta: FieldMeta, field_build_parameters: Any | None = None, build_context: BuildContext | None = None, ) -> Any: constraints = cast(PydanticConstraints, field_meta.constraints) if constraints.pop("json", None): value = cls.get_field_value( field_meta, field_build_parameters=field_build_parameters, build_context=build_context ) return to_json(value) # pyright: ignore[reportPossiblyUnboundVariable] return super().get_constrained_field_value( annotation, field_meta, field_build_parameters=field_build_parameters, build_context=build_context ) @classmethod def build( cls, factory_use_construct: bool = False, **kwargs: Any, ) -> T: """Build an instance of the factory's __model__ :param factory_use_construct: A boolean that determines whether validations will be made when instantiating the model. This is supported only for pydantic models. :param kwargs: Any kwargs. If field_meta names are set in kwargs, their values will be used. :returns: An instance of type T. """ if "_build_context" not in kwargs: kwargs["_build_context"] = PydanticBuildContext( seen_models=set(), factory_use_construct=factory_use_construct ) processed_kwargs = cls.process_kwargs(**kwargs) return cls._create_model(kwargs["_build_context"], **processed_kwargs) @classmethod def _get_build_context(cls, build_context: BaseBuildContext | PydanticBuildContext | None) -> PydanticBuildContext: """Return a PydanticBuildContext instance. If build_context is None, return a new PydanticBuildContext. :returns: PydanticBuildContext """ if build_context is None: return {"seen_models": set(), "factory_use_construct": False} factory_use_construct = bool(build_context.get("factory_use_construct", False)) return { "seen_models": copy.deepcopy(build_context["seen_models"]), "factory_use_construct": factory_use_construct, } @classmethod def _create_model(cls, _build_context: PydanticBuildContext, **kwargs: Any) -> T: """Create an instance of the factory's __model__ :param _build_context: BuildContext instance. :param kwargs: Model kwargs. :returns: An instance of type T. """ if cls._get_build_context(_build_context).get("factory_use_construct"): if _is_pydantic_v1_model(cls.__model__): return cls.__model__.construct(**kwargs) # type: ignore[return-value] return cls.__model__.model_construct(**kwargs) # type: ignore[return-value] return cls.__model__(**kwargs) # type: ignore[return-value] @classmethod def coverage(cls, factory_use_construct: bool = False, **kwargs: Any) -> abc.Iterator[T]: """Build a batch of the factory's Meta.model will full coverage of the sub-types of the model. :param kwargs: Any kwargs. If field_meta names are set in kwargs, their values will be used. :returns: A iterator of instances of type T. """ if "_build_context" not in kwargs: kwargs["_build_context"] = PydanticBuildContext( seen_models=set(), factory_use_construct=factory_use_construct ) for data in cls.process_kwargs_coverage(**kwargs): yield cls._create_model(_build_context=kwargs["_build_context"], **data) @classmethod def is_custom_root_field(cls, field_meta: FieldMeta) -> bool: """Determine whether the field is a custom root field. :param field_meta: FieldMeta instance. :returns: A boolean determining whether the field is a custom root. """ return field_meta.name == "__root__" @classmethod def should_set_field_value(cls, field_meta: FieldMeta, **kwargs: Any) -> bool: """Determine whether to set a value for a given field_name. This is an override of BaseFactory.should_set_field_value. :param field_meta: FieldMeta instance. :param kwargs: Any kwargs passed to the factory. :returns: A boolean determining whether a value should be set for the given field_meta. """ return field_meta.name not in kwargs and ( not field_meta.name.startswith("_") or cls.is_custom_root_field(field_meta) ) @classmethod def get_provider_map(cls) -> dict[Any, Callable[[], Any]]: mapping: dict[Any, Callable[[], Any]] = { pydantic.ByteSize: cls.__faker__.pyint, pydantic.PositiveInt: cls.__faker__.pyint, pydantic.NegativeFloat: lambda: cls.__random__.uniform(-100, -1), pydantic.NegativeInt: lambda: cls.__faker__.pyint() * -1, pydantic.PositiveFloat: cls.__faker__.pyint, pydantic.NonPositiveFloat: lambda: cls.__random__.uniform(-100, 0), pydantic.NonNegativeInt: cls.__faker__.pyint, pydantic.StrictInt: cls.__faker__.pyint, pydantic.StrictBool: cls.__faker__.pybool, pydantic.StrictBytes: partial(create_random_bytes, cls.__random__), pydantic.StrictFloat: cls.__faker__.pyfloat, pydantic.StrictStr: cls.__faker__.pystr, pydantic.EmailStr: cls.__faker__.free_email, pydantic.NameEmail: cls.__faker__.free_email, pydantic.Json: cls.__faker__.json, pydantic.PaymentCardNumber: cls.__faker__.credit_card_number, pydantic.AnyUrl: cls.__faker__.url, pydantic.AnyHttpUrl: cls.__faker__.url, pydantic.HttpUrl: cls.__faker__.url, pydantic.SecretBytes: partial(create_random_bytes, cls.__random__), pydantic.SecretStr: cls.__faker__.pystr, pydantic.IPvAnyAddress: cls.__faker__.ipv4, pydantic.IPvAnyInterface: cls.__faker__.ipv4, pydantic.IPvAnyNetwork: lambda: cls.__faker__.ipv4(network=True), pydantic.PastDate: cls.__faker__.past_date, pydantic.FutureDate: cls.__faker__.future_date, } # v1 only values mapping.update( { PyObject: lambda: "decimal.Decimal", AmqpDsn: lambda: "amqps://example.com", KafkaDsn: lambda: "kafka://localhost:9092", PostgresDsn: lambda: "postgresql://user:secret@localhost", RedisDsn: lambda: "redis://localhost:6379/0", FilePath: lambda: Path(realpath(__file__)), DirectoryPath: lambda: Path(realpath(__file__)).parent, UUID1: uuid1, UUID3: lambda: uuid3(NAMESPACE_DNS, cls.__faker__.pystr()), UUID4: cls.__faker__.uuid4, UUID5: lambda: uuid5(NAMESPACE_DNS, cls.__faker__.pystr()), Color: cls.__faker__.hex_color, # pyright: ignore[reportGeneralTypeIssues] }, ) if not _IS_PYDANTIC_V1: mapping.update( { # pydantic v2 specific types pydantic.PastDatetime: cls.__faker__.past_datetime, pydantic.FutureDatetime: cls.__faker__.future_datetime, pydantic.AwareDatetime: partial(cls.__faker__.date_time, timezone.utc), pydantic.NaiveDatetime: cls.__faker__.date_time, }, ) mapping.update(super().get_provider_map()) return mapping def _is_pydantic_v1_model(model: Any) -> TypeGuard[BaseModelV1]: return is_safe_subclass(model, BaseModelV1) def _is_pydantic_v2_model(model: Any) -> TypeGuard[BaseModelV2]: # pyright: ignore[reportInvalidTypeForm] return not _IS_PYDANTIC_V1 and is_safe_subclass(model, BaseModelV2) ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/polyfactory/factories/sqlalchemy_factory.py�������������������������������0000664�0000000�0000000�00000022441�14721310225�0026272�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from __future__ import annotations from datetime import date, datetime from typing import TYPE_CHECKING, Any, Callable, ClassVar, Generic, List, TypeVar, Union from typing_extensions import Annotated from polyfactory.exceptions import MissingDependencyException from polyfactory.factories.base import BaseFactory from polyfactory.field_meta import Constraints, FieldMeta from polyfactory.persistence import AsyncPersistenceProtocol, SyncPersistenceProtocol from polyfactory.utils.types import Frozendict try: from sqlalchemy import ARRAY, Column, Numeric, String, inspect, types from sqlalchemy.dialects import mssql, mysql, postgresql, sqlite from sqlalchemy.exc import NoInspectionAvailable from sqlalchemy.orm import InstanceState, Mapper except ImportError as e: msg = "sqlalchemy is not installed" raise MissingDependencyException(msg) from e if TYPE_CHECKING: from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.orm import Session from sqlalchemy.sql.type_api import TypeEngine from typing_extensions import TypeGuard T = TypeVar("T") class SQLASyncPersistence(SyncPersistenceProtocol[T]): def __init__(self, session: Session) -> None: """Sync persistence handler for SQLAFactory.""" self.session = session def save(self, data: T) -> T: self.session.add(data) self.session.commit() return data def save_many(self, data: list[T]) -> list[T]: self.session.add_all(data) self.session.commit() return data class SQLAASyncPersistence(AsyncPersistenceProtocol[T]): def __init__(self, session: AsyncSession) -> None: """Async persistence handler for SQLAFactory.""" self.session = session async def save(self, data: T) -> T: self.session.add(data) await self.session.commit() await self.session.refresh(data) return data async def save_many(self, data: list[T]) -> list[T]: self.session.add_all(data) await self.session.commit() for batch_item in data: await self.session.refresh(batch_item) return data class SQLAlchemyFactory(Generic[T], BaseFactory[T]): """Base factory for SQLAlchemy models.""" __is_base_factory__ = True __set_primary_key__: ClassVar[bool] = True """Configuration to consider primary key columns as a field or not.""" __set_foreign_keys__: ClassVar[bool] = True """Configuration to consider columns with foreign keys as a field or not.""" __set_relationships__: ClassVar[bool] = False """Configuration to consider relationships property as a model field or not.""" __session__: ClassVar[Session | Callable[[], Session] | None] = None __async_session__: ClassVar[AsyncSession | Callable[[], AsyncSession] | None] = None __config_keys__ = ( *BaseFactory.__config_keys__, "__set_primary_key__", "__set_foreign_keys__", "__set_relationships__", ) @classmethod def get_sqlalchemy_types(cls) -> dict[Any, Callable[[], Any]]: """Get mapping of types where column type should be used directly. For sqlalchemy dialect `JSON` type, accepted only basic types in pydict in case sqlalchemy process `JSON` raise serialize error. """ return { types.TupleType: cls.__faker__.pytuple, mssql.JSON: lambda: cls.__faker__.pydict(value_types=(str, int, bool, float)), mysql.YEAR: lambda: cls.__random__.randint(1901, 2155), mysql.JSON: lambda: cls.__faker__.pydict(value_types=(str, int, bool, float)), postgresql.CIDR: lambda: cls.__faker__.ipv4(network=True), postgresql.DATERANGE: lambda: (cls.__faker__.past_date(), date.today()), # noqa: DTZ011 postgresql.INET: lambda: cls.__faker__.ipv4(network=False), postgresql.INT4RANGE: lambda: tuple(sorted([cls.__faker__.pyint(), cls.__faker__.pyint()])), postgresql.INT8RANGE: lambda: tuple(sorted([cls.__faker__.pyint(), cls.__faker__.pyint()])), postgresql.MACADDR: lambda: cls.__faker__.hexify(text="^^:^^:^^:^^:^^:^^", upper=True), postgresql.NUMRANGE: lambda: tuple(sorted([cls.__faker__.pyint(), cls.__faker__.pyint()])), postgresql.TSRANGE: lambda: (cls.__faker__.past_datetime(), datetime.now()), # noqa: DTZ005 postgresql.TSTZRANGE: lambda: (cls.__faker__.past_datetime(), datetime.now()), # noqa: DTZ005 postgresql.HSTORE: lambda: cls.__faker__.pydict(value_types=(str, int, bool, float)), postgresql.JSON: lambda: cls.__faker__.pydict(value_types=(str, int, bool, float)), postgresql.JSONB: lambda: cls.__faker__.pydict(value_types=(str, int, bool, float)), sqlite.JSON: lambda: cls.__faker__.pydict(value_types=(str, int, bool, float)), types.JSON: lambda: cls.__faker__.pydict(value_types=(str, int, bool, float)), } @classmethod def get_sqlalchemy_constraints(cls) -> dict[type[TypeEngine], dict[str, str]]: """Get mapping of SQLA type engine to attribute to constraints key.""" return { String: { "length": "max_length", }, Numeric: { "precision": "max_digits", "scale": "decimal_places", }, } @classmethod def get_provider_map(cls) -> dict[Any, Callable[[], Any]]: providers_map = super().get_provider_map() providers_map.update(cls.get_sqlalchemy_types()) return providers_map @classmethod def is_supported_type(cls, value: Any) -> TypeGuard[type[T]]: try: inspected = inspect(value) except NoInspectionAvailable: return False return isinstance(inspected, (Mapper, InstanceState)) @classmethod def should_column_be_set(cls, column: Any) -> bool: if not isinstance(column, Column): return False if not cls.__set_primary_key__ and column.primary_key: return False return bool(cls.__set_foreign_keys__ or not column.foreign_keys) @classmethod def _get_type_from_type_engine(cls, type_engine: TypeEngine) -> type: if type(type_engine) in cls.get_sqlalchemy_types(): return type(type_engine) annotation: type try: annotation = type_engine.python_type except NotImplementedError: annotation = type_engine.impl.python_type # type: ignore[attr-defined] constraints: Constraints = {} for type_, constraint_fields in cls.get_sqlalchemy_constraints().items(): if not isinstance(type_engine, type_): continue for sqlalchemy_field, constraint_field in constraint_fields.items(): if (value := getattr(type_engine, sqlalchemy_field, None)) is not None: constraints[constraint_field] = value # type: ignore[literal-required] if constraints: annotation = Annotated[annotation, Frozendict(constraints)] # type: ignore[assignment] return annotation @classmethod def get_type_from_column(cls, column: Column) -> type: annotation: type if isinstance(column.type, (ARRAY, postgresql.ARRAY)): item_type = cls._get_type_from_type_engine(column.type.item_type) annotation = List[item_type] # type: ignore[valid-type] else: annotation = cls._get_type_from_type_engine(column.type) if column.nullable: annotation = Union[annotation, None] # type: ignore[assignment] return annotation @classmethod def get_model_fields(cls) -> list[FieldMeta]: fields_meta: list[FieldMeta] = [] table: Mapper = inspect(cls.__model__) # type: ignore[assignment] fields_meta.extend( FieldMeta.from_type( annotation=cls.get_type_from_column(column), name=name, random=cls.__random__, ) for name, column in table.columns.items() if cls.should_column_be_set(column) ) if cls.__set_relationships__: for name, relationship in table.relationships.items(): class_ = relationship.entity.class_ annotation = class_ if not relationship.uselist else List[class_] # type: ignore[valid-type] fields_meta.append( FieldMeta.from_type( name=name, annotation=annotation, random=cls.__random__, ), ) return fields_meta @classmethod def _get_sync_persistence(cls) -> SyncPersistenceProtocol[T]: if cls.__session__ is not None: return ( SQLASyncPersistence(cls.__session__()) if callable(cls.__session__) else SQLASyncPersistence(cls.__session__) ) return super()._get_sync_persistence() @classmethod def _get_async_persistence(cls) -> AsyncPersistenceProtocol[T]: if cls.__async_session__ is not None: return ( SQLAASyncPersistence(cls.__async_session__()) if callable(cls.__async_session__) else SQLAASyncPersistence(cls.__async_session__) ) return super()._get_async_persistence() �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/polyfactory/factories/typed_dict_factory.py�������������������������������0000664�0000000�0000000�00000003444�14721310225�0026262�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from __future__ import annotations from typing import Any, Generic, TypeVar, get_args from typing_extensions import ( # type: ignore[attr-defined] NotRequired, Required, TypeGuard, _TypedDictMeta, # pyright: ignore[reportAttributeAccessIssue] get_origin, get_type_hints, is_typeddict, ) from polyfactory.constants import DEFAULT_RANDOM from polyfactory.factories.base import BaseFactory from polyfactory.field_meta import FieldMeta, Null TypedDictT = TypeVar("TypedDictT", bound=_TypedDictMeta) class TypedDictFactory(Generic[TypedDictT], BaseFactory[TypedDictT]): """TypedDict base factory""" __is_base_factory__ = True @classmethod def is_supported_type(cls, value: Any) -> TypeGuard[type[TypedDictT]]: """Determine whether the given value is supported by the factory. :param value: An arbitrary value. :returns: A typeguard """ return is_typeddict(value) @classmethod def get_model_fields(cls) -> list["FieldMeta"]: """Retrieve a list of fields from the factory's model. :returns: A list of field MetaData instances. """ model_type_hints = get_type_hints(cls.__model__, include_extras=True) field_metas: list[FieldMeta] = [] for field_name, annotation in model_type_hints.items(): origin = get_origin(annotation) if origin in (Required, NotRequired): annotation = get_args(annotation)[0] # noqa: PLW2901 field_metas.append( FieldMeta.from_type( annotation=annotation, random=DEFAULT_RANDOM, name=field_name, default=getattr(cls.__model__, field_name, Null), ), ) return field_metas ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/polyfactory/field_meta.py�������������������������������������������������0000664�0000000�0000000�00000021364�14721310225�0022516�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from __future__ import annotations from dataclasses import asdict, is_dataclass from typing import TYPE_CHECKING, Any, Literal, Mapping, Pattern, TypedDict, cast from typing_extensions import get_args, get_origin from polyfactory.constants import DEFAULT_RANDOM, TYPE_MAPPING from polyfactory.utils.deprecation import check_for_deprecated_parameters from polyfactory.utils.helpers import get_annotation_metadata, unwrap_annotated, unwrap_new_type from polyfactory.utils.predicates import is_annotated from polyfactory.utils.types import NoneType if TYPE_CHECKING: import datetime from decimal import Decimal from random import Random from typing import Sequence from typing_extensions import NotRequired, Self class Null: """Sentinel class for empty values""" class UrlConstraints(TypedDict): max_length: NotRequired[int] allowed_schemes: NotRequired[list[str]] host_required: NotRequired[bool] default_host: NotRequired[str] default_port: NotRequired[int] default_path: NotRequired[str] class Constraints(TypedDict): """Metadata regarding a type constraints, if any""" allow_inf_nan: NotRequired[bool] decimal_places: NotRequired[int] ge: NotRequired[int | float | Decimal] gt: NotRequired[int | float | Decimal] item_type: NotRequired[Any] le: NotRequired[int | float | Decimal] lower_case: NotRequired[bool] lt: NotRequired[int | float | Decimal] max_digits: NotRequired[int] max_length: NotRequired[int] min_length: NotRequired[int] multiple_of: NotRequired[int | float | Decimal] path_type: NotRequired[Literal["file", "dir", "new"]] pattern: NotRequired[str | Pattern] tz: NotRequired[datetime.tzinfo] unique_items: NotRequired[bool] upper_case: NotRequired[bool] url: NotRequired[UrlConstraints] uuid_version: NotRequired[Literal[1, 3, 4, 5]] class FieldMeta: """Factory field metadata container. This class is used to store the data about a field of a factory's model.""" __slots__ = ("name", "annotation", "random", "children", "default", "constraints") annotation: Any random: Random children: list[FieldMeta] | None default: Any name: str constraints: Constraints | None def __init__( self, *, name: str, annotation: type, random: Random | None = None, default: Any = Null, children: list[FieldMeta] | None = None, constraints: Constraints | None = None, ) -> None: """Create a factory field metadata instance.""" self.annotation = annotation self.random = random or DEFAULT_RANDOM self.children = children self.default = default self.name = name self.constraints = constraints @property def type_args(self) -> tuple[Any, ...]: """Return the normalized type args of the annotation, if any. :returns: a tuple of types. """ return tuple(TYPE_MAPPING.get(arg, arg) for arg in get_args(self.annotation)) @classmethod def from_type( cls, annotation: Any, random: Random = DEFAULT_RANDOM, name: str = "", default: Any = Null, constraints: Constraints | None = None, randomize_collection_length: bool | None = None, min_collection_length: int | None = None, max_collection_length: int | None = None, children: list[FieldMeta] | None = None, ) -> Self: """Builder method to create a FieldMeta from a type annotation. :param annotation: A type annotation. :param random: An instance of random.Random. :param name: Field name :param default: Default value, if any. :param constraints: A dictionary of constraints, if any. :param randomize_collection_length: A boolean flag whether to randomize collections lengths :param min_collection_length: Minimum number of elements in randomized collection :param max_collection_length: Maximum number of elements in randomized collection :returns: A field meta instance. """ check_for_deprecated_parameters( "2.11.0", parameters=( ("randomize_collection_length", randomize_collection_length), ("min_collection_length", min_collection_length), ("max_collection_length", max_collection_length), ), ) annotated = is_annotated(annotation) if not constraints and annotated: metadata = cls.get_constraints_metadata(annotation) constraints = cls.parse_constraints(metadata) if annotated: annotation = get_args(annotation)[0] elif (origin := get_origin(annotation)) and origin in TYPE_MAPPING: # pragma: no cover container = TYPE_MAPPING[origin] annotation = container[get_args(annotation)] # type: ignore[index] field = cls( annotation=annotation, random=random, name=name, default=default, children=children, constraints=constraints, ) if field.type_args and not field.children: field.children = [ cls.from_type( annotation=unwrap_new_type(arg), random=random, ) for arg in field.type_args if arg is not NoneType ] return field @classmethod def parse_constraints(cls, metadata: Sequence[Any]) -> "Constraints": constraints = {} for value in metadata: if is_annotated(value): _, inner_metadata = unwrap_annotated(value, random=DEFAULT_RANDOM) constraints.update(cast("dict[str, Any]", cls.parse_constraints(metadata=inner_metadata))) elif func := getattr(value, "func", None): if func is str.islower: constraints["lower_case"] = True elif func is str.isupper: constraints["upper_case"] = True elif func is str.isascii: constraints["pattern"] = "[[:ascii:]]" elif func is str.isdigit: constraints["pattern"] = "[[:digit:]]" elif is_dataclass(value) and (value_dict := asdict(value)) and ("allowed_schemes" in value_dict): # type: ignore[call-overload] constraints["url"] = {k: v for k, v in value_dict.items() if v is not None} # This is to support `Constraints`, but we can't do a isinstance with `Constraints` since isinstance # checks with `TypedDict` is not supported. elif isinstance(value, Mapping): constraints.update(value) else: constraints.update( { k: v for k, v in { "allow_inf_nan": getattr(value, "allow_inf_nan", None), "decimal_places": getattr(value, "decimal_places", None), "ge": getattr(value, "ge", None), "gt": getattr(value, "gt", None), "item_type": getattr(value, "item_type", None), "le": getattr(value, "le", None), "lower_case": getattr(value, "to_lower", None), "lt": getattr(value, "lt", None), "max_digits": getattr(value, "max_digits", None), "max_length": getattr(value, "max_length", getattr(value, "max_length", None)), "min_length": getattr(value, "min_length", getattr(value, "min_items", None)), "multiple_of": getattr(value, "multiple_of", None), "path_type": getattr(value, "path_type", None), "pattern": getattr(value, "regex", getattr(value, "pattern", None)), "tz": getattr(value, "tz", None), "unique_items": getattr(value, "unique_items", None), "upper_case": getattr(value, "to_upper", None), "uuid_version": getattr(value, "uuid_version", None), }.items() if v is not None }, ) return cast("Constraints", constraints) @classmethod def get_constraints_metadata(cls, annotation: Any) -> Sequence[Any]: """Get the metadatas of the constraints from the given annotation. :param annotation: A type annotation. :param random: An instance of random.Random. :returns: A list of the metadata in the annotation. """ return get_annotation_metadata(annotation) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/polyfactory/fields.py�����������������������������������������������������0000664�0000000�0000000�00000006423�14721310225�0021672�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from __future__ import annotations from typing import Any, Callable, Generic, TypedDict, TypeVar, cast from typing_extensions import ParamSpec from polyfactory.exceptions import ParameterException T = TypeVar("T") P = ParamSpec("P") class WrappedCallable(TypedDict): """A ref storing a callable. This class is a utility meant to prevent binding of methods.""" value: Callable class Require: """A factory field that marks an attribute as a required build-time kwarg.""" class Ignore: """A factory field that marks an attribute as ignored.""" class Use(Generic[P, T]): """Factory field used to wrap a callable. The callable will be invoked whenever building the given factory attribute. """ __slots__ = ("fn", "kwargs", "args") def __init__(self, fn: Callable[P, T], *args: P.args, **kwargs: P.kwargs) -> None: """Wrap a callable. :param fn: A callable to wrap. :param args: Any args to pass to the callable. :param kwargs: Any kwargs to pass to the callable. """ self.fn: WrappedCallable = {"value": fn} self.kwargs = kwargs self.args = args def to_value(self) -> T: """Invoke the callable. :returns: The output of the callable. """ return cast("T", self.fn["value"](*self.args, **self.kwargs)) class PostGenerated: """Factory field that allows generating values after other fields are generated by the factory.""" __slots__ = ("fn", "kwargs", "args") def __init__(self, fn: Callable, *args: Any, **kwargs: Any) -> None: """Designate field as post-generated. :param fn: A callable. :param args: Args for the callable. :param kwargs: Kwargs for the callable. """ self.fn: WrappedCallable = {"value": fn} self.kwargs = kwargs self.args = args def to_value(self, name: str, values: dict[str, Any]) -> Any: """Invoke the post-generation callback passing to it the build results. :param name: Field name. :param values: Generated values. :returns: An arbitrary value. """ return self.fn["value"](name, values, *self.args, **self.kwargs) class Fixture: """Factory field to create a pytest fixture from a factory.""" __slots__ = ("ref", "size", "kwargs") def __init__(self, fixture: Callable, size: int | None = None, **kwargs: Any) -> None: """Create a fixture from a factory. :param fixture: A factory that was registered as a fixture. :param size: Optional batch size. :param kwargs: Any build kwargs. """ self.ref: WrappedCallable = {"value": fixture} self.size = size self.kwargs = kwargs def to_value(self) -> Any: """Call the factory's build or batch method. :raises: ParameterException :returns: The build result. """ from polyfactory.pytest_plugin import FactoryFixture if factory := FactoryFixture.factory_class_map.get(self.ref["value"]): if self.size is not None: return factory.batch(self.size, **self.kwargs) return factory.build(**self.kwargs) msg = "fixture has not been registered using the register_factory decorator" raise ParameterException(msg) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/polyfactory/persistence.py������������������������������������������������0000664�0000000�0000000�00000002250�14721310225�0022742�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from __future__ import annotations from typing import Protocol, TypeVar, runtime_checkable T = TypeVar("T") @runtime_checkable class SyncPersistenceProtocol(Protocol[T]): """Protocol for sync persistence""" def save(self, data: T) -> T: """Persist a single instance synchronously. :param data: A single instance to persist. :returns: The persisted result. """ ... def save_many(self, data: list[T]) -> list[T]: """Persist multiple instances synchronously. :param data: A list of instances to persist. :returns: The persisted result """ ... @runtime_checkable class AsyncPersistenceProtocol(Protocol[T]): """Protocol for async persistence""" async def save(self, data: T) -> T: """Persist a single instance asynchronously. :param data: A single instance to persist. :returns: The persisted result. """ ... async def save_many(self, data: list[T]) -> list[T]: """Persist multiple instances asynchronously. :param data: A list of instances to persist. :returns: The persisted result """ ... ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/polyfactory/py.typed������������������������������������������������������0000664�0000000�0000000�00000000000�14721310225�0021532�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/polyfactory/pytest_plugin.py����������������������������������������������0000664�0000000�0000000�00000006541�14721310225�0023333�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from __future__ import annotations import re from typing import ( Any, Callable, ClassVar, Literal, Type, TypeVar, Union, cast, overload, ) from pytest import Config, fixture # noqa: PT013 from polyfactory.exceptions import ParameterException from polyfactory.factories.base import BaseFactory from polyfactory.utils.predicates import is_safe_subclass Scope = Union[ Literal["session", "package", "module", "class", "function"], Callable[[str, Config], Literal["session", "package", "module", "class", "function"]], ] T = TypeVar("T", bound=BaseFactory[Any]) split_pattern_1 = re.compile(r"([A-Z]+)([A-Z][a-z])") split_pattern_2 = re.compile(r"([a-z\d])([A-Z])") def _get_fixture_name(name: str) -> str: """From inflection.underscore. :param name: str: A name. :returns: Normalized fixture name. """ name = re.sub(split_pattern_1, r"\1_\2", name) name = re.sub(split_pattern_2, r"\1_\2", name) name = name.replace("-", "_") return name.lower() class FactoryFixture: """Decorator that creates a pytest fixture from a factory""" __slots__ = ("scope", "autouse", "name") factory_class_map: ClassVar[dict[Callable, type[BaseFactory[Any]]]] = {} def __init__( self, scope: Scope = "function", autouse: bool = False, name: str | None = None, ) -> None: """Create a factory fixture decorator :param scope: Fixture scope :param autouse: Autouse the fixture :param name: Fixture name """ self.scope = scope self.autouse = autouse self.name = name def __call__(self, factory: type[T]) -> Callable[[], type[T]]: if not is_safe_subclass(factory, BaseFactory): msg = f"{factory.__name__} is not a BaseFactory subclass." raise ParameterException(msg) fixture_name = self.name or _get_fixture_name(factory.__name__) fixture_register = fixture( scope=self.scope, # pyright: ignore[reportArgumentType] name=fixture_name, autouse=self.autouse, ) def _factory_fixture() -> type[T]: """The wrapped factory""" return cast(Type[T], factory) _factory_fixture.__doc__ = factory.__doc__ marker = fixture_register(_factory_fixture) self.factory_class_map[marker] = factory return marker @overload def register_fixture( factory: None = None, *, scope: Scope = "function", autouse: bool = False, name: str | None = None, ) -> FactoryFixture: ... @overload def register_fixture( factory: type[T], *, scope: Scope = "function", autouse: bool = False, name: str | None = None, ) -> Callable[[], type[T]]: ... def register_fixture( factory: type[T] | None = None, *, scope: Scope = "function", autouse: bool = False, name: str | None = None, ) -> FactoryFixture | Callable[[], type[T]]: """A decorator that allows registering model factories as fixtures. :param factory: An optional factory class to decorate. :param scope: Pytest scope. :param autouse: Auto use fixture. :param name: Fixture name. :returns: A fixture factory instance. """ factory_fixture = FactoryFixture(scope=scope, autouse=autouse, name=name) return factory_fixture(factory) if factory else factory_fixture ���������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/polyfactory/utils/��������������������������������������������������������0000775�0000000�0000000�00000000000�14721310225�0021205�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/polyfactory/utils/__init__.py���������������������������������������������0000664�0000000�0000000�00000000000�14721310225�0023304�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/polyfactory/utils/deprecation.py������������������������������������������0000664�0000000�0000000�00000011575�14721310225�0024065�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from __future__ import annotations import inspect from functools import wraps from typing import Any, Callable, Literal, TypeVar from warnings import warn from typing_extensions import ParamSpec __all__ = ("deprecated", "warn_deprecation", "check_for_deprecated_parameters") T = TypeVar("T") P = ParamSpec("P") DeprecatedKind = Literal["function", "method", "classmethod", "attribute", "property", "class", "parameter", "import"] def warn_deprecation( version: str, deprecated_name: str, kind: DeprecatedKind, *, removal_in: str | None = None, alternative: str | None = None, info: str | None = None, pending: bool = False, ) -> None: """Warn about a call to a (soon to be) deprecated function. Args: version: Polyfactory version where the deprecation will occur. deprecated_name: Name of the deprecated function. removal_in: Polyfactory version where the deprecated function will be removed. alternative: Name of a function that should be used instead. info: Additional information. pending: Use ``PendingDeprecationWarning`` instead of ``DeprecationWarning``. kind: Type of the deprecated thing. """ parts = [] if kind == "import": access_type = "Import of" elif kind in {"function", "method"}: access_type = "Call to" else: access_type = "Use of" if pending: parts.append(f"{access_type} {kind} awaiting deprecation {deprecated_name!r}") else: parts.append(f"{access_type} deprecated {kind} {deprecated_name!r}") parts.extend( ( f"Deprecated in polyfactory {version}", f"This {kind} will be removed in {removal_in or 'the next major version'}", ) ) if alternative: parts.append(f"Use {alternative!r} instead") if info: parts.append(info) text = ". ".join(parts) warning_class = PendingDeprecationWarning if pending else DeprecationWarning warn(text, warning_class, stacklevel=2) def deprecated( version: str, *, removal_in: str | None = None, alternative: str | None = None, info: str | None = None, pending: bool = False, kind: Literal["function", "method", "classmethod", "property"] | None = None, ) -> Callable[[Callable[P, T]], Callable[P, T]]: """Create a decorator wrapping a function, method or property with a warning call about a (pending) deprecation. Args: version: Polyfactory version where the deprecation will occur. removal_in: Polyfactory version where the deprecated function will be removed. alternative: Name of a function that should be used instead. info: Additional information. pending: Use ``PendingDeprecationWarning`` instead of ``DeprecationWarning``. kind: Type of the deprecated callable. If ``None``, will use ``inspect`` to figure out if it's a function or method. Returns: A decorator wrapping the function call with a warning """ def decorator(func: Callable[P, T]) -> Callable[P, T]: @wraps(func) def wrapped(*args: P.args, **kwargs: P.kwargs) -> T: warn_deprecation( version=version, deprecated_name=func.__name__, info=info, alternative=alternative, pending=pending, removal_in=removal_in, kind=kind or ("method" if inspect.ismethod(func) else "function"), ) return func(*args, **kwargs) return wrapped return decorator def check_for_deprecated_parameters( version: str, *, parameters: tuple[tuple[str, Any], ...], default_value: Any = None, removal_in: str | None = None, alternative: str | None = None, info: str | None = None, pending: bool = False, ) -> None: """Warn about a call to a (soon to be) deprecated argument to a function. Args: version: Polyfactory version where the deprecation will occur. parameters: Parameters to trigger warning if used. default_value: Default value for parameter to detect if supplied or not. removal_in: Polyfactory version where the deprecated function will be removed. alternative: Name of a function that should be used instead. info: Additional information. pending: Use ``PendingDeprecationWarning`` instead of ``DeprecationWarning``. kind: Type of the deprecated callable. If ``None``, will use ``inspect`` to figure out if it's a function or method. """ for parameter_name, value in parameters: if value == default_value: continue warn_deprecation( version=version, deprecated_name=parameter_name, info=info, alternative=alternative, pending=pending, removal_in=removal_in, kind="parameter", ) �����������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/polyfactory/utils/helpers.py����������������������������������������������0000664�0000000�0000000�00000013400�14721310225�0023217�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from __future__ import annotations import sys from collections import deque from typing import TYPE_CHECKING, Any, Mapping, Sequence from typing_extensions import TypeAliasType, get_args, get_origin from polyfactory.constants import TYPE_MAPPING from polyfactory.utils.predicates import is_annotated, is_new_type, is_optional, is_safe_subclass, is_union from polyfactory.utils.types import NoneType if TYPE_CHECKING: from random import Random def unwrap_new_type(annotation: Any) -> Any: """Return base type if given annotation is a type derived with NewType, otherwise annotation. :param annotation: A type annotation, possibly one created using 'types.NewType' :returns: The unwrapped annotation. """ while is_new_type(annotation): annotation = annotation.__supertype__ return annotation def unwrap_union(annotation: Any, random: Random) -> Any: """Unwraps union types - recursively. :param annotation: A type annotation, possibly a type union. :param random: An instance of random.Random. :returns: A type annotation """ while is_union(annotation): args = list(get_args(annotation)) annotation = random.choice(args) return annotation def unwrap_optional(annotation: Any) -> Any: """Unwraps optional union types - recursively. :param annotation: A type annotation, possibly an optional union. :returns: A type annotation """ while is_optional(annotation): annotation = next(arg for arg in get_args(annotation) if arg not in (NoneType, None)) return annotation def unwrap_annotation(annotation: Any, random: Random) -> Any: """Unwraps an annotation. :param annotation: A type annotation. :param random: An instance of random.Random. :returns: The unwrapped annotation. """ while ( is_optional(annotation) or is_union(annotation) or is_new_type(annotation) or is_annotated(annotation) or isinstance(annotation, TypeAliasType) ): if is_new_type(annotation): annotation = unwrap_new_type(annotation) elif is_optional(annotation): annotation = unwrap_optional(annotation) elif is_annotated(annotation): annotation = unwrap_annotated(annotation, random=random)[0] elif isinstance(annotation, TypeAliasType): annotation = annotation.__value__ else: annotation = unwrap_union(annotation, random=random) return annotation def flatten_annotation(annotation: Any) -> list[Any]: """Flattens an annotation. :param annotation: A type annotation. :returns: The flattened annotations. """ flat = [] if is_new_type(annotation): flat.extend(flatten_annotation(unwrap_new_type(annotation))) elif is_optional(annotation): for a in get_args(annotation): flat.extend(flatten_annotation(a)) elif is_annotated(annotation): flat.extend(flatten_annotation(get_args(annotation)[0])) elif is_union(annotation): for a in get_args(annotation): flat.extend(flatten_annotation(a)) else: flat.append(annotation) return flat def unwrap_args(annotation: Any, random: Random) -> tuple[Any, ...]: """Unwrap the annotation and return any type args. :param annotation: A type annotation :param random: An instance of random.Random. :returns: A tuple of type args. """ return get_args(unwrap_annotation(annotation=annotation, random=random)) def unwrap_annotated(annotation: Any, random: Random) -> tuple[Any, list[Any]]: """Unwrap an annotated type and return a tuple of type args and optional metadata. :param annotation: An annotated type annotation :param random: An instance of random.Random. :returns: A tuple of type args. """ args = [arg for arg in get_args(annotation) if arg is not None] return unwrap_annotation(args[0], random=random), args[1:] def normalize_annotation(annotation: Any, random: Random) -> Any: """Normalize an annotation. :param annotation: A type annotation. :returns: A normalized type annotation. """ if is_new_type(annotation): annotation = unwrap_new_type(annotation) if is_annotated(annotation): annotation = unwrap_annotated(annotation, random=random)[0] # we have to maintain compatibility with the older non-subscriptable typings. if sys.version_info <= (3, 9): # pragma: no cover return annotation origin = get_origin(annotation) or annotation if origin in TYPE_MAPPING: origin = TYPE_MAPPING[origin] if args := get_args(annotation): args = tuple(normalize_annotation(arg, random=random) for arg in args) return origin[args] if origin is not type else annotation return origin def get_annotation_metadata(annotation: Any) -> Sequence[Any]: """Get the metadata in the annotation. :param annotation: A type annotation. :returns: The metadata. """ return get_args(annotation)[1:] def get_collection_type(annotation: Any) -> type[list | tuple | set | frozenset | dict | deque]: # noqa: PLR0911 """Get the collection type from the annotation. :param annotation: A type annotation. :returns: The collection type. """ if is_safe_subclass(annotation, list): return list if is_safe_subclass(annotation, Mapping): return dict if is_safe_subclass(annotation, tuple): return tuple if is_safe_subclass(annotation, set): return set if is_safe_subclass(annotation, frozenset): return frozenset if is_safe_subclass(annotation, deque): return deque if is_safe_subclass(annotation, Sequence): return list msg = f"Unknown collection type - {annotation}" raise ValueError(msg) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/polyfactory/utils/model_coverage.py���������������������������������������0000664�0000000�0000000�00000011463�14721310225�0024537�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from __future__ import annotations from abc import ABC, abstractmethod from collections.abc import Callable, Iterable, Iterator, Mapping, MutableSequence from typing import AbstractSet, Any, Generic, Set, TypeVar, cast from typing_extensions import ParamSpec from polyfactory.exceptions import ParameterException class CoverageContainerBase(ABC): """Base class for coverage container implementations. A coverage container is a wrapper providing values for a particular field. Coverage containers return field values and track a "done" state to indicate that all coverage examples have been generated. """ @abstractmethod def next_value(self) -> Any: """Provide the next value""" ... @abstractmethod def is_done(self) -> bool: """Indicate if this container has provided every coverage example it has""" ... T = TypeVar("T") class CoverageContainer(CoverageContainerBase, Generic[T]): """A coverage container that wraps a collection of values. When calling ``next_value()`` a greater number of times than the length of the given collection will cause duplicate examples to be returned (wraps around). If there are any coverage containers within the given collection, the values from those containers are essentially merged into the parent container. """ def __init__(self, instances: Iterable[T]) -> None: self._pos = 0 self._instances = list(instances) if not self._instances: msg = "CoverageContainer must have at least one instance" raise ValueError(msg) def next_value(self) -> T: value = self._instances[self._pos % len(self._instances)] if isinstance(value, CoverageContainerBase): result = value.next_value() if value.is_done(): # Only move onto the next instance if the sub-container is done self._pos += 1 return cast(T, result) self._pos += 1 return value def is_done(self) -> bool: return self._pos >= len(self._instances) def __repr__(self) -> str: return f"CoverageContainer(instances={self._instances}, is_done={self.is_done()})" P = ParamSpec("P") class CoverageContainerCallable(CoverageContainerBase, Generic[T]): """A coverage container that wraps a callable. When calling ``next_value()`` the wrapped callable is called to provide a value. """ def __init__(self, func: Callable[P, T], *args: P.args, **kwargs: P.kwargs) -> None: self._func = func self._args = args self._kwargs = kwargs def next_value(self) -> T: try: return self._func(*self._args, **self._kwargs) except Exception as e: msg = f"Unsupported type: {self._func!r}\n\nEither extend the providers map or add a factory function for this type." raise ParameterException(msg) from e def is_done(self) -> bool: return True def _resolve_next(unresolved: Any) -> tuple[Any, bool]: # noqa: C901 if isinstance(unresolved, CoverageContainerBase): result, done = _resolve_next(unresolved.next_value()) return result, unresolved.is_done() and done if isinstance(unresolved, Mapping): result = {} done_status = True for key, value in unresolved.items(): val_resolved, val_done = _resolve_next(value) key_resolved, key_done = _resolve_next(key) result[key_resolved] = val_resolved done_status = done_status and val_done and key_done return result, done_status if isinstance(unresolved, (tuple, MutableSequence)): result = [] done_status = True for value in unresolved: resolved, done = _resolve_next(value) result.append(resolved) done_status = done_status and done if isinstance(unresolved, tuple): result = tuple(result) return result, done_status if isinstance(unresolved, Set): result = type(unresolved)() done_status = True for value in unresolved: resolved, done = _resolve_next(value) result.add(resolved) done_status = done_status and done return result, done_status if issubclass(type(unresolved), AbstractSet): result = type(unresolved)() done_status = True resolved_values = [] for value in unresolved: resolved, done = _resolve_next(value) resolved_values.append(resolved) done_status = done_status and done return result.union(resolved_values), done_status return unresolved, True def resolve_kwargs_coverage(kwargs: dict[str, Any]) -> Iterator[dict[str, Any]]: done = False while not done: resolved, done = _resolve_next(kwargs) yield resolved �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/polyfactory/utils/predicates.py�������������������������������������������0000664�0000000�0000000�00000007577�14721310225�0023722�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from __future__ import annotations from inspect import isclass from typing import Any, Literal, NewType, Optional, TypeVar, get_args from typing_extensions import ( Annotated, NotRequired, ParamSpec, Required, TypeGuard, _AnnotatedAlias, get_origin, ) from polyfactory.constants import TYPE_MAPPING from polyfactory.utils.types import UNION_TYPES, NoneType P = ParamSpec("P") T = TypeVar("T") def is_safe_subclass(annotation: Any, class_or_tuple: type[T] | tuple[type[T], ...]) -> "TypeGuard[type[T]]": """Determine whether a given annotation is a subclass of a give type :param annotation: A type annotation. :param class_or_tuple: A potential super class or classes. :returns: A typeguard """ origin = get_type_origin(annotation) if not origin and not isclass(annotation): return False try: return issubclass(origin or annotation, class_or_tuple) except TypeError: # pragma: no cover return False def is_any(annotation: Any) -> "TypeGuard[Any]": """Determine whether a given annotation is 'typing.Any'. :param annotation: A type annotation. :returns: A typeguard. """ return ( annotation is Any or getattr(annotation, "_name", "") == "typing.Any" or (get_origin(annotation) in UNION_TYPES and Any in get_args(annotation)) ) def is_dict_key_or_value_type(annotation: Any) -> "TypeGuard[Any]": """Determine whether a given annotation is a valid dict key or value type: ``typing.KT`` or ``typing.VT``. :returns: A typeguard. """ return str(annotation) in {"~KT", "~VT"} def is_union(annotation: Any) -> "TypeGuard[Any]": """Determine whether a given annotation is 'typing.Union'. :param annotation: A type annotation. :returns: A typeguard. """ return get_type_origin(annotation) in UNION_TYPES def is_optional(annotation: Any) -> "TypeGuard[Any | None]": """Determine whether a given annotation is 'typing.Optional'. :param annotation: A type annotation. :returns: A typeguard. """ origin = get_type_origin(annotation) return origin is Optional or (get_origin(annotation) in UNION_TYPES and NoneType in get_args(annotation)) def is_literal(annotation: Any) -> bool: """Determine whether a given annotation is 'typing.Literal'. :param annotation: A type annotation. :returns: A boolean. """ return ( get_type_origin(annotation) is Literal or repr(annotation).startswith("typing.Literal") or repr(annotation).startswith("typing_extensions.Literal") ) def is_new_type(annotation: Any) -> "TypeGuard[type[NewType]]": """Determine whether a given annotation is 'typing.NewType'. :param annotation: A type annotation. :returns: A typeguard. """ return hasattr(annotation, "__supertype__") def is_annotated(annotation: Any) -> bool: """Determine whether a given annotation is 'typing.Annotated'. :param annotation: A type annotation. :returns: A boolean. """ return get_origin(annotation) is Annotated or ( isinstance(annotation, _AnnotatedAlias) and getattr(annotation, "__args__", None) is not None ) def is_any_annotated(annotation: Any) -> bool: """Determine whether any of the types in the given annotation is `typing.Annotated`. :param annotation: A type annotation. :returns: A boolean """ return any(is_annotated(arg) or hasattr(arg, "__args__") and is_any_annotated(arg) for arg in get_args(annotation)) def get_type_origin(annotation: Any) -> Any: """Get the type origin of an annotation - safely. :param annotation: A type annotation. :returns: A type annotation. """ origin = get_origin(annotation) if origin in (Annotated, Required, NotRequired): origin = get_args(annotation)[0] return mapped_type if (mapped_type := TYPE_MAPPING.get(origin)) else origin ���������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/polyfactory/utils/types.py������������������������������������������������0000664�0000000�0000000�00000001531�14721310225�0022723�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from typing import TYPE_CHECKING, Any, NoReturn, Union try: from types import NoneType, UnionType UNION_TYPES = {UnionType, Union} except ImportError: UNION_TYPES = {Union} NoneType = type(None) # type: ignore[misc] class Frozendict(dict): def _immutable_error(self, *_: Any, **__: Any) -> NoReturn: msg = f"Unable to mutate {type(self).__name__}" raise TypeError(msg) # Override all mutation methods to prevent changes if not TYPE_CHECKING: __setitem__ = _immutable_error __delitem__ = _immutable_error clear = _immutable_error pop = _immutable_error popitem = _immutable_error update = _immutable_error def __hash__(self) -> int: # type: ignore[override] return hash(tuple(self.items())) __all__ = ("NoneType", "UNION_TYPES", "Frozendict") �����������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/polyfactory/value_generators/���������������������������������������������0000775�0000000�0000000�00000000000�14721310225�0023412�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/polyfactory/value_generators/__init__.py����������������������������������0000664�0000000�0000000�00000000000�14721310225�0025511�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/polyfactory/value_generators/complex_types.py�����������������������������0000664�0000000�0000000�00000013644�14721310225�0026667�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from __future__ import annotations from typing import TYPE_CHECKING, AbstractSet, Any, Iterable, MutableMapping, MutableSequence, Set, Tuple, cast from typing_extensions import is_typeddict from polyfactory.constants import INSTANTIABLE_TYPE_MAPPING, PY_38 from polyfactory.field_meta import FieldMeta from polyfactory.utils.model_coverage import CoverageContainer if TYPE_CHECKING: from polyfactory.factories.base import BaseFactory, BuildContext def handle_collection_type( field_meta: FieldMeta, container_type: type, factory: type[BaseFactory[Any]], field_build_parameters: Any | None = None, build_context: BuildContext | None = None, ) -> Any: """Handle generation of container types recursively. :param container_type: A type that can accept type arguments. :param factory: A factory. :param field_meta: A field meta instance. :param field_build_parameters: Any build parameters passed to the factory as kwarg values. :param build_context: BuildContext data for current build. :returns: A built result. """ if PY_38 and container_type in INSTANTIABLE_TYPE_MAPPING: container_type = INSTANTIABLE_TYPE_MAPPING[container_type] # type: ignore[assignment] container = container_type() if field_meta.children is None or any( child_meta.annotation in factory._get_build_context(build_context)["seen_models"] for child_meta in field_meta.children ): return container if issubclass(container_type, MutableMapping) or is_typeddict(container_type): for key_field_meta, value_field_meta in cast( Iterable[Tuple[FieldMeta, FieldMeta]], zip(field_meta.children[::2], field_meta.children[1::2]), ): key = factory.get_field_value( key_field_meta, field_build_parameters=field_build_parameters, build_context=build_context ) value = factory.get_field_value( value_field_meta, field_build_parameters=field_build_parameters, build_context=build_context ) container[key] = value return container if issubclass(container_type, MutableSequence): container.extend( [ factory.get_field_value( subfield_meta, field_build_parameters=field_build_parameters, build_context=build_context ) for subfield_meta in field_meta.children ] ) return container if issubclass(container_type, Set): for subfield_meta in field_meta.children: container.add( factory.get_field_value( subfield_meta, field_build_parameters=field_build_parameters, build_context=build_context ) ) return container if issubclass(container_type, AbstractSet): return container.union( handle_collection_type( field_meta, set, factory, field_build_parameters=field_build_parameters, build_context=build_context ) ) if issubclass(container_type, tuple): return container_type( factory.get_field_value(child, field_build_parameters=field_build_parameters, build_context=build_context) for child in field_meta.children if child.annotation != Ellipsis ) msg = f"Unsupported container type: {container_type}" raise NotImplementedError(msg) def handle_collection_type_coverage( # noqa: C901, PLR0911 field_meta: FieldMeta, container_type: type, factory: type[BaseFactory[Any]], build_context: BuildContext | None = None, ) -> Any: """Handle coverage generation of container types recursively. :param container_type: A type that can accept type arguments. :param factory: A factory. :param field_meta: A field meta instance. :returns: An unresolved built result. """ container = container_type() if not field_meta.children: return container if issubclass(container_type, MutableMapping) or is_typeddict(container_type): for key_field_meta, value_field_meta in cast( Iterable[Tuple[FieldMeta, FieldMeta]], zip(field_meta.children[::2], field_meta.children[1::2]), ): key = CoverageContainer(factory.get_field_value_coverage(key_field_meta, build_context=build_context)) value = CoverageContainer(factory.get_field_value_coverage(value_field_meta, build_context=build_context)) container[key] = value return container if issubclass(container_type, MutableSequence): container_instance = container_type() for subfield_meta in field_meta.children: container_instance.extend(factory.get_field_value_coverage(subfield_meta, build_context=build_context)) return container_instance if issubclass(container_type, Set): set_instance = container_type() for subfield_meta in field_meta.children: set_instance = set_instance.union( factory.get_field_value_coverage(subfield_meta, build_context=build_context) ) return set_instance if issubclass(container_type, AbstractSet): return container.union(handle_collection_type_coverage(field_meta, set, factory, build_context=build_context)) if issubclass(container_type, tuple): if field_meta.children[-1].annotation == Ellipsis: return ( CoverageContainer( factory.get_field_value_coverage( field_meta.children[0], build_context=build_context, ) ), ) return container_type( CoverageContainer(factory.get_field_value_coverage(subfield_meta, build_context=build_context)) for subfield_meta in field_meta.children ) msg = f"Unsupported container type: {container_type}" raise NotImplementedError(msg) ��������������������������������������������������������������������������������������������python-polyfactory-2.18.1/polyfactory/value_generators/constrained_collections.py�������������������0000664�0000000�0000000�00000011723�14721310225�0030677�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from __future__ import annotations from enum import EnumMeta from typing import TYPE_CHECKING, Any, Callable, Literal, Mapping, TypeVar from polyfactory.exceptions import ParameterException if TYPE_CHECKING: from polyfactory.factories.base import BaseFactory, BuildContext from polyfactory.field_meta import FieldMeta T = TypeVar("T", list, set, frozenset) def handle_constrained_collection( # noqa: C901 collection_type: Callable[..., T], factory: type[BaseFactory[Any]], field_meta: FieldMeta, item_type: Any, max_items: int | None = None, min_items: int | None = None, unique_items: bool = False, field_build_parameters: Any | None = None, build_context: BuildContext | None = None, ) -> T: """Generate a constrained list or set. :param collection_type: A type that can accept type arguments. :param factory: A factory. :param field_meta: A field meta instance. :param item_type: Type of the collection items. :param max_items: Maximal number of items. :param min_items: Minimal number of items. :param unique_items: Whether the items should be unique. :param field_build_parameters: Any build parameters passed to the factory as kwarg values. :param build_context: BuildContext data for current build. :returns: A collection value. """ build_context = factory._get_build_context(build_context) if field_meta.annotation in build_context["seen_models"]: return collection_type() min_items = abs(min_items if min_items is not None else (max_items or 0)) max_items = abs(max_items if max_items is not None else min_items + 1) if max_items < min_items: msg = "max_items must be larger or equal to min_items" raise ParameterException(msg) if collection_type in (frozenset, set) or unique_items: max_field_values = max_items if hasattr(field_meta.annotation, "__origin__") and field_meta.annotation.__origin__ is Literal: if field_meta.children is not None: max_field_values = len(field_meta.children) elif isinstance(field_meta.annotation, EnumMeta): max_field_values = len(field_meta.annotation) min_items = min(min_items, max_field_values) max_items = min(max_items, max_field_values) collection: set[T] | list[T] = set() if (collection_type in (frozenset, set) or unique_items) else [] try: length = factory.__random__.randint(min_items, max_items) while (i := len(collection)) < length: if field_build_parameters and len(field_build_parameters) > i: build_params = field_build_parameters[i] else: build_params = None value = factory.get_field_value( field_meta, field_build_parameters=build_params, build_context=build_context, ) if isinstance(collection, set): collection.add(value) else: collection.append(value) return collection_type(collection) except TypeError as e: msg = f"cannot generate a constrained collection of type: {item_type}" raise ParameterException(msg) from e def handle_constrained_mapping( factory: type[BaseFactory[Any]], field_meta: FieldMeta, max_items: int | None = None, min_items: int | None = None, field_build_parameters: Any | None = None, build_context: BuildContext | None = None, ) -> Mapping[Any, Any]: """Generate a constrained mapping. :param factory: A factory. :param field_meta: A field meta instance. :param max_items: Maximal number of items. :param min_items: Minimal number of items. :param field_build_parameters: Any build parameters passed to the factory as kwarg values. :param build_context: BuildContext data for current build. :returns: A mapping instance. """ build_context = factory._get_build_context(build_context) if field_meta.children is None or any( child_meta.annotation in build_context["seen_models"] for child_meta in field_meta.children ): return {} min_items = abs(min_items if min_items is not None else (max_items or 0)) max_items = abs(max_items if max_items is not None else min_items + 1) if max_items < min_items: msg = "max_items must be larger or equal to min_items" raise ParameterException(msg) length = factory.__random__.randint(min_items, max_items) or 1 collection: dict[Any, Any] = {} children = field_meta.children key_field_meta = children[0] value_field_meta = children[1] while len(collection) < length: key = factory.get_field_value( key_field_meta, field_build_parameters=field_build_parameters, build_context=build_context ) value = factory.get_field_value( value_field_meta, field_build_parameters=field_build_parameters, build_context=build_context ) collection[key] = value return collection ���������������������������������������������python-polyfactory-2.18.1/polyfactory/value_generators/constrained_dates.py�������������������������0000664�0000000�0000000�00000002121�14721310225�0027451�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from __future__ import annotations from datetime import date, datetime, timedelta, timezone, tzinfo from typing import TYPE_CHECKING if TYPE_CHECKING: from faker import Faker def handle_constrained_date( faker: Faker, ge: date | None = None, gt: date | None = None, le: date | None = None, lt: date | None = None, tz: tzinfo = timezone.utc, ) -> date: """Generates a date value fulfilling the expected constraints. :param faker: An instance of faker. :param lt: Less than value. :param le: Less than or equal value. :param gt: Greater than value. :param ge: Greater than or equal value. :param tz: A timezone. :returns: A date instance. """ start_date = datetime.now(tz=tz).date() - timedelta(days=100) if ge: start_date = ge elif gt: start_date = gt + timedelta(days=1) end_date = datetime.now(tz=timezone.utc).date() + timedelta(days=100) if le: end_date = le elif lt: end_date = lt - timedelta(days=1) return faker.date_between(start_date=start_date, end_date=end_date) �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/polyfactory/value_generators/constrained_numbers.py�����������������������0000664�0000000�0000000�00000032652�14721310225�0030040�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from __future__ import annotations from decimal import Decimal from sys import float_info from typing import TYPE_CHECKING, Any, Protocol, TypeVar, cast from polyfactory.exceptions import ParameterException from polyfactory.value_generators.primitives import create_random_decimal, create_random_float, create_random_integer if TYPE_CHECKING: from random import Random T = TypeVar("T", Decimal, int, float) class NumberGeneratorProtocol(Protocol[T]): """Protocol for custom callables used to generate numerical values""" def __call__(self, random: "Random", minimum: T | None = None, maximum: T | None = None) -> T: """Signature of the callable. :param random: An instance of random. :param minimum: A minimum value. :param maximum: A maximum value. :return: The generated numeric value. """ ... def almost_equal_floats(value_1: float, value_2: float, *, delta: float = 1e-8) -> bool: """Return True if two floats are almost equal :param value_1: A float value. :param value_2: A float value. :param delta: A minimal delta. :returns: Boolean dictating whether the floats can be considered equal - given python's problematic comparison of floats. """ return abs(value_1 - value_2) <= delta def is_multiply_of_multiple_of_in_range( minimum: T, maximum: T, multiple_of: T, ) -> bool: """Determine if at least one multiply of `multiple_of` lies in the given range. :param minimum: T: A minimum value. :param maximum: T: A maximum value. :param multiple_of: T: A value to use as a base for multiplication. :returns: Boolean dictating whether at least one multiply of `multiple_of` lies in the given range between minimum and maximum. """ # if the range has infinity on one of its ends then infinite number of multipliers # can be found within the range # if we were given floats and multiple_of is really close to zero then it doesn't make sense # to continue trying to check the range if ( isinstance(minimum, float) and isinstance(multiple_of, float) and minimum / multiple_of in [float("+inf"), float("-inf")] ): return False multiplier = round(minimum / multiple_of) step = 1 if multiple_of > 0 else -1 # since rounding can go either up or down we may end up in a situation when # minimum is less or equal to `multiplier * multiple_of` # or when it is greater than `multiplier * multiple_of` # (in this case minimum is less than `(multiplier + 1)* multiple_of`). So we need to check # that any of two values is inside the given range. ASCII graphic below explain this # # minimum # -----------------+-------+-----------------------------------+---------------------------- # # # minimum # -------------------------+--------+--------------------------+---------------------------- # # since `multiple_of` can be a negative number adding +1 to `multiplier` drives `(multiplier + 1) * multiple_of`` # away from `minimum` to the -infinity. It looks like this: # minimum # -----------------------+--------------------------------+------------------------+-------- # # so for negative `multiple_of` we want to subtract 1 from multiplier for multiply in [multiplier * multiple_of, (multiplier + step) * multiple_of]: multiply_float = float(multiply) if ( almost_equal_floats(multiply_float, float(minimum)) or almost_equal_floats(multiply_float, float(maximum)) or minimum < multiply < maximum ): return True return False def passes_pydantic_multiple_validator(value: T, multiple_of: T) -> bool: """Determine whether a given value passes the pydantic multiple_of validation. :param value: A numeric value. :param multiple_of: Another numeric value. :returns: Boolean dictating whether value is a multiple of value. """ if multiple_of == 0: return True mod = float(value) / float(multiple_of) % 1 return almost_equal_floats(mod, 0.0) or almost_equal_floats(mod, 1.0) def get_increment(t_type: type[T]) -> T: """Get a small increment base to add to constrained values, i.e. lt/gt entries. :param t_type: A value of type T. :returns: An increment T. """ values: dict[Any, Any] = { int: 1, float: float_info.epsilon, Decimal: Decimal("0.001"), } return cast("T", values[t_type]) def get_value_or_none( t_type: type[T], lt: T | None = None, le: T | None = None, gt: T | None = None, ge: T | None = None, ) -> tuple[T | None, T | None]: """Return an optional value. :param equal_value: An GE/LE value. :param constrained: An GT/LT value. :param increment: increment :returns: Optional T. """ if ge is not None: minimum_value = ge elif gt is not None: minimum_value = gt + get_increment(t_type) else: minimum_value = None if le is not None: maximum_value = le elif lt is not None: maximum_value = lt - get_increment(t_type) else: maximum_value = None return minimum_value, maximum_value def get_constrained_number_range( t_type: type[T], random: Random, lt: T | None = None, le: T | None = None, gt: T | None = None, ge: T | None = None, multiple_of: T | None = None, ) -> tuple[T | None, T | None]: """Return the minimum and maximum values given a field_meta's constraints. :param t_type: A primitive constructor - int, float or Decimal. :param random: An instance of Random. :param lt: Less than value. :param le: Less than or equal value. :param gt: Greater than value. :param ge: Greater than or equal value. :param multiple_of: Multiple of value. :returns: a tuple of optional minimum and maximum values. """ seed = t_type(random.random() * 10) minimum, maximum = get_value_or_none(lt=lt, le=le, gt=gt, ge=ge, t_type=t_type) if minimum is not None and maximum is not None and maximum < minimum: msg = "maximum value must be greater than minimum value" raise ParameterException(msg) if multiple_of is None: if minimum is not None and maximum is None: return (minimum, seed) if minimum == 0 else (minimum, minimum + seed) # pyright: ignore[reportGeneralTypeIssues] if maximum is not None and minimum is None: return maximum - seed, maximum else: if multiple_of == 0.0: # TODO: investigate @guacs # noqa: FIX002 msg = "multiple_of can not be zero" raise ParameterException(msg) if ( minimum is not None and maximum is not None and not is_multiply_of_multiple_of_in_range(minimum=minimum, maximum=maximum, multiple_of=multiple_of) ): msg = "given range should include at least one multiply of multiple_of" raise ParameterException(msg) return minimum, maximum def generate_constrained_number( random: Random, minimum: T | None, maximum: T | None, multiple_of: T | None, method: "NumberGeneratorProtocol[T]", ) -> T: """Generate a constrained number, output depends on the passed in callbacks. :param random: An instance of random. :param minimum: A minimum value. :param maximum: A maximum value. :param multiple_of: A multiple of value. :param method: A function that generates numbers of type T. :returns: A value of type T. """ if minimum is None or maximum is None: return multiple_of if multiple_of is not None else method(random=random) if multiple_of is None: return method(random=random, minimum=minimum, maximum=maximum) if multiple_of >= minimum: return multiple_of result = minimum while not passes_pydantic_multiple_validator(result, multiple_of): result = round(method(random=random, minimum=minimum, maximum=maximum) / multiple_of) * multiple_of return result def handle_constrained_int( random: Random, multiple_of: int | None = None, gt: int | None = None, ge: int | None = None, lt: int | None = None, le: int | None = None, ) -> int: """Handle constrained integers. :param random: An instance of Random. :param lt: Less than value. :param le: Less than or equal value. :param gt: Greater than value. :param ge: Greater than or equal value. :param multiple_of: Multiple of value. :returns: An integer. """ minimum, maximum = get_constrained_number_range( gt=gt, ge=ge, lt=lt, le=le, t_type=int, multiple_of=multiple_of, random=random, ) return generate_constrained_number( random=random, minimum=minimum, maximum=maximum, multiple_of=multiple_of, method=create_random_integer, ) def handle_constrained_float( random: Random, multiple_of: float | None = None, gt: float | None = None, ge: float | None = None, lt: float | None = None, le: float | None = None, ) -> float: """Handle constrained floats. :param random: An instance of Random. :param lt: Less than value. :param le: Less than or equal value. :param gt: Greater than value. :param ge: Greater than or equal value. :param multiple_of: Multiple of value. :returns: A float. """ minimum, maximum = get_constrained_number_range( gt=gt, ge=ge, lt=lt, le=le, t_type=float, multiple_of=multiple_of, random=random, ) return generate_constrained_number( random=random, minimum=minimum, maximum=maximum, multiple_of=multiple_of, method=create_random_float, ) def validate_max_digits( max_digits: int, minimum: Decimal | None, decimal_places: int | None, ) -> None: """Validate that max digits is greater than minimum and decimal places. :param max_digits: The maximal number of digits for the decimal. :param minimum: Minimal value. :param decimal_places: Number of decimal places :returns: 'None' """ if max_digits <= 0: msg = "max_digits must be greater than 0" raise ParameterException(msg) if minimum is not None: min_str = str(minimum).split(".")[1] if "." in str(minimum) else str(minimum) if max_digits <= len(min_str): msg = "minimum is greater than max_digits" raise ParameterException(msg) if decimal_places is not None and max_digits <= decimal_places: msg = "max_digits must be greater than decimal places" raise ParameterException(msg) def handle_decimal_length( generated_decimal: Decimal, decimal_places: int | None, max_digits: int | None, ) -> Decimal: """Handle the length of the decimal. :param generated_decimal: A decimal value. :param decimal_places: Number of decimal places. :param max_digits: Maximal number of digits. """ string_number = str(generated_decimal) sign = "-" if "-" in string_number else "+" string_number = string_number.replace("-", "") whole_numbers, decimals = string_number.split(".") if ( max_digits is not None and decimal_places is not None and len(whole_numbers) + decimal_places > max_digits or (max_digits is None or decimal_places is None) and max_digits is not None ): max_decimals = max_digits - len(whole_numbers) elif max_digits is not None: max_decimals = decimal_places # type: ignore[assignment] else: max_decimals = cast("int", decimal_places) if max_decimals < 0: # pyright: ignore[reportOptionalOperand] return Decimal(sign + whole_numbers[:max_decimals]) decimals = decimals[:max_decimals] return Decimal(sign + whole_numbers + "." + decimals[:decimal_places]) def handle_constrained_decimal( random: Random, multiple_of: Decimal | None = None, decimal_places: int | None = None, max_digits: int | None = None, gt: Decimal | None = None, ge: Decimal | None = None, lt: Decimal | None = None, le: Decimal | None = None, ) -> Decimal: """Handle a constrained decimal. :param random: An instance of Random. :param multiple_of: Multiple of value. :param decimal_places: Number of decimal places. :param max_digits: Maximal number of digits. :param lt: Less than value. :param le: Less than or equal value. :param gt: Greater than value. :param ge: Greater than or equal value. :returns: A decimal. """ minimum, maximum = get_constrained_number_range( gt=gt, ge=ge, lt=lt, le=le, multiple_of=multiple_of, t_type=Decimal, random=random, ) if max_digits is not None: validate_max_digits(max_digits=max_digits, minimum=minimum, decimal_places=decimal_places) generated_decimal = generate_constrained_number( random=random, minimum=minimum, maximum=maximum, multiple_of=multiple_of, method=create_random_decimal, ) if max_digits is not None or decimal_places is not None: return handle_decimal_length( generated_decimal=generated_decimal, max_digits=max_digits, decimal_places=decimal_places, ) return generated_decimal ��������������������������������������������������������������������������������������python-polyfactory-2.18.1/polyfactory/value_generators/constrained_path.py��������������������������0000664�0000000�0000000�00000000661�14721310225�0027314�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from os.path import realpath from pathlib import Path from typing import Literal, cast from faker import Faker def handle_constrained_path(constraint: Literal["file", "dir", "new"], faker: Faker) -> Path: if constraint == "new": return cast("Path", faker.file_path(depth=1, category=None, extension=None)) if constraint == "file": return Path(realpath(__file__)) return Path(realpath(__file__)).parent �������������������������������������������������������������������������������python-polyfactory-2.18.1/polyfactory/value_generators/constrained_strings.py�����������������������0000664�0000000�0000000�00000007474�14721310225�0030062�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from __future__ import annotations from typing import TYPE_CHECKING, Callable, Pattern, TypeVar, Union, cast from polyfactory.exceptions import ParameterException from polyfactory.value_generators.primitives import create_random_bytes, create_random_string from polyfactory.value_generators.regex import RegexFactory T = TypeVar("T", bound=Union[bytes, str]) if TYPE_CHECKING: from random import Random def _validate_length( min_length: int | None = None, max_length: int | None = None, ) -> None: """Validate the length parameters make sense. :param min_length: Minimum length. :param max_length: Maximum length. :raises: ParameterException. :returns: None. """ if min_length is not None and min_length < 0: msg = "min_length must be greater or equal to 0" raise ParameterException(msg) if max_length is not None and max_length < 0: msg = "max_length must be greater or equal to 0" raise ParameterException(msg) if max_length is not None and min_length is not None and max_length < min_length: msg = "max_length must be greater than min_length" raise ParameterException(msg) def _generate_pattern( random: Random, pattern: str | Pattern, lower_case: bool = False, upper_case: bool = False, min_length: int | None = None, max_length: int | None = None, ) -> str: """Generate a regex. :param random: An instance of random. :param pattern: A regex or string pattern. :param lower_case: Whether to lowercase the result. :param upper_case: Whether to uppercase the result. :param min_length: A minimum length. :param max_length: A maximum length. :returns: A string matching the given pattern. """ regex_factory = RegexFactory(random=random) result = regex_factory(pattern) if min_length: while len(result) < min_length: result += regex_factory(pattern) if max_length is not None and len(result) > max_length: result = result[:max_length] if lower_case: result = result.lower() if upper_case: result = result.upper() return result def handle_constrained_string_or_bytes( random: Random, t_type: Callable[[], T], lower_case: bool = False, upper_case: bool = False, min_length: int | None = None, max_length: int | None = None, pattern: str | Pattern | None = None, ) -> T: """Handle constrained string or bytes, for example - pydantic `constr` or `conbytes`. :param random: An instance of random. :param t_type: A type (str or bytes) :param lower_case: Whether to lowercase the result. :param upper_case: Whether to uppercase the result. :param min_length: A minimum length. :param max_length: A maximum length. :param pattern: A regex or string pattern. :returns: A value of type T. """ _validate_length(min_length=min_length, max_length=max_length) if max_length == 0: return t_type() if pattern: return cast( "T", _generate_pattern( random=random, pattern=pattern, lower_case=lower_case, upper_case=upper_case, min_length=min_length, max_length=max_length, ), ) if t_type is str: return cast( "T", create_random_string( min_length=min_length, max_length=max_length, lower_case=lower_case, upper_case=upper_case, random=random, ), ) return cast( "T", create_random_bytes( min_length=min_length, max_length=max_length, lower_case=lower_case, upper_case=upper_case, random=random, ), ) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/polyfactory/value_generators/constrained_url.py���������������������������0000664�0000000�0000000�00000000670�14721310225�0027162�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from polyfactory.field_meta import UrlConstraints def handle_constrained_url(constraints: UrlConstraints) -> str: schema = (constraints.get("allowed_schemes") or ["http", "https"])[0] default_host = constraints.get("default_host") or "localhost" default_port = constraints.get("default_port") or 80 default_path = constraints.get("default_path") or "" return f"{schema}://{default_host}:{default_port}{default_path}" ������������������������������������������������������������������������python-polyfactory-2.18.1/polyfactory/value_generators/constrained_uuid.py��������������������������0000664�0000000�0000000�00000001602�14721310225�0027322�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from typing import Literal, cast from uuid import NAMESPACE_DNS, UUID, uuid1, uuid3, uuid5 from faker import Faker UUID_VERSION_1 = 1 UUID_VERSION_3 = 3 UUID_VERSION_4 = 4 UUID_VERSION_5 = 5 def handle_constrained_uuid(uuid_version: Literal[1, 3, 4, 5], faker: Faker) -> UUID: """Generate a UUID based on the version specified. Args: uuid_version: The version of the UUID to generate. faker: The Faker instance to use. Returns: The generated UUID. """ if uuid_version == UUID_VERSION_1: return uuid1() if uuid_version == UUID_VERSION_3: return uuid3(NAMESPACE_DNS, faker.pystr()) if uuid_version == UUID_VERSION_4: return cast("UUID", faker.uuid4()) if uuid_version == UUID_VERSION_5: return uuid5(NAMESPACE_DNS, faker.pystr()) msg = f"Unknown UUID version: {uuid_version}" raise ValueError(msg) ������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/polyfactory/value_generators/primitives.py��������������������������������0000664�0000000�0000000�00000007122�14721310225�0026161�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from __future__ import annotations from binascii import hexlify from decimal import Decimal from typing import TYPE_CHECKING if TYPE_CHECKING: from random import Random def create_random_float( random: Random, minimum: Decimal | float | None = None, maximum: Decimal | float | None = None, ) -> float: """Generate a random float given the constraints. :param random: An instance of random. :param minimum: A minimum value :param maximum: A maximum value. :returns: A random float. """ if minimum is None: minimum = float(random.randint(0, 100)) if maximum is None else float(maximum) - 100.0 if maximum is None: maximum = float(minimum) + 1.0 * 2.0 if minimum >= 0 else float(minimum) + 1.0 / 2.0 return random.uniform(float(minimum), float(maximum)) def create_random_integer(random: Random, minimum: int | None = None, maximum: int | None = None) -> int: """Generate a random int given the constraints. :param random: An instance of random. :param minimum: A minimum value :param maximum: A maximum value. :returns: A random integer. """ return round(create_random_float(random=random, minimum=minimum, maximum=maximum)) def create_random_decimal( random: Random, minimum: Decimal | None = None, maximum: Decimal | None = None, ) -> Decimal: """Generate a random Decimal given the constraints. :param random: An instance of random. :param minimum: A minimum value :param maximum: A maximum value. :returns: A random decimal. """ return Decimal(str(create_random_float(random=random, minimum=minimum, maximum=maximum))) def create_random_bytes( random: Random, min_length: int | None = None, max_length: int | None = None, lower_case: bool = False, upper_case: bool = False, ) -> bytes: """Generate a random bytes given the constraints. :param random: An instance of random. :param min_length: A minimum length. :param max_length: A maximum length. :param lower_case: Whether to lowercase the result. :param upper_case: Whether to uppercase the result. :returns: A random byte-string. """ if min_length is None: min_length = 0 if max_length is None: max_length = min_length + 1 * 2 length = random.randint(min_length, max_length) result = b"" if length == 0 else hexlify(random.getrandbits(length * 8).to_bytes(length, "little")) if lower_case: result = result.lower() elif upper_case: result = result.upper() if max_length and len(result) > max_length: end = random.randint(min_length or 0, max_length) return result[:end] return result def create_random_string( random: Random, min_length: int | None = None, max_length: int | None = None, lower_case: bool = False, upper_case: bool = False, ) -> str: """Generate a random string given the constraints. :param random: An instance of random. :param min_length: A minimum length. :param max_length: A maximum length. :param lower_case: Whether to lowercase the result. :param upper_case: Whether to uppercase the result. :returns: A random string. """ return create_random_bytes( random=random, min_length=min_length, max_length=max_length, lower_case=lower_case, upper_case=upper_case, ).decode("utf-8") def create_random_boolean(random: Random) -> bool: """Generate a random boolean value. :param random: An instance of random. :returns: A random boolean. """ return bool(random.getrandbits(1)) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/polyfactory/value_generators/regex.py�������������������������������������0000664�0000000�0000000�00000014154�14721310225�0025103�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������"""The code in this files is adapted from https://github.com/crdoconnor/xeger/blob/master/xeger/xeger.py.Which in turn adapted it from https://bitbucket.org/leapfrogdevelopment/rstr/. Copyright (C) 2015, Colm O'Connor All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the Leapfrog Direct Response, LLC, including its subsidiaries and affiliates nor the names of its contributors, may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL LEAPFROG DIRECT RESPONSE, LLC, INCLUDING ITS SUBSIDIARIES AND AFFILIATES, BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """ from __future__ import annotations from itertools import chain from string import ascii_letters, ascii_lowercase, ascii_uppercase, digits, printable, punctuation, whitespace from typing import TYPE_CHECKING, Any, Pattern try: # >=3.11 from re._parser import SubPattern, parse except ImportError: # < 3.11 from sre_parse import ( SubPattern, # pylint: disable=deprecated-module parse, ) if TYPE_CHECKING: from random import Random _alphabets = { "printable": printable, "letters": ascii_letters, "uppercase": ascii_uppercase, "lowercase": ascii_lowercase, "digits": digits, "punctuation": punctuation, "nondigits": ascii_letters + punctuation, "nonletters": digits + punctuation, "whitespace": whitespace, "nonwhitespace": printable.strip(), "normal": ascii_letters + digits + " ", "word": ascii_letters + digits + "_", "nonword": "".join(set(printable).difference(ascii_letters + digits + "_")), "postalsafe": ascii_letters + digits + " .-#/", "urlsafe": ascii_letters + digits + "-._~", "domainsafe": ascii_letters + digits + "-", } _categories = { "category_digit": _alphabets["digits"], "category_not_digit": _alphabets["nondigits"], "category_space": _alphabets["whitespace"], "category_not_space": _alphabets["nonwhitespace"], "category_word": _alphabets["word"], "category_not_word": _alphabets["nonword"], } class RegexFactory: """Factory for regexes.""" def __init__(self, random: Random, limit: int = 10) -> None: """Create a RegexFactory""" self._limit = limit self._cache: dict[str, Any] = {} self._random = random self._cases = { "literal": chr, "not_literal": lambda x: self._random.choice(printable.replace(chr(x), "")), "at": lambda x: "", "in": self._handle_in, "any": lambda x: self._random.choice(printable.replace("\n", "")), "range": lambda x: [chr(i) for i in range(x[0], x[1] + 1)], "category": lambda x: _categories[str(x).lower()], "branch": lambda x: "".join(self._handle_state(i) for i in self._random.choice(x[1])), "subpattern": self._handle_group, "assert": lambda x: "".join(self._handle_state(i) for i in x[1]), "assert_not": lambda x: "", "groupref": lambda x: self._cache[x], "min_repeat": lambda x: self._handle_repeat(*x), "max_repeat": lambda x: self._handle_repeat(*x), "negate": lambda x: [False], } def __call__(self, string_or_regex: str | Pattern) -> str: """Generate a string matching a regex. :param string_or_regex: A string or pattern. :return: The generated string. """ pattern = string_or_regex.pattern if isinstance(string_or_regex, Pattern) else string_or_regex parsed = parse(pattern) result = self._build_string(parsed) # pyright: ignore[reportArgumentType] self._cache.clear() return result def _build_string(self, parsed: SubPattern) -> str: return "".join([self._handle_state(state) for state in parsed]) # pyright:ignore[reportArgumentType,reportCallIssue] def _handle_state(self, state: tuple[SubPattern, tuple[Any, ...]]) -> Any: opcode, value = state return self._cases[str(opcode).lower()](value) # type: ignore[no-untyped-call] def _handle_group(self, value: tuple[Any, ...]) -> str: result = "".join(self._handle_state(i) for i in value[3]) if value[0]: self._cache[value[0]] = result return result def _handle_in(self, value: tuple[Any, ...]) -> Any: candidates = list(chain(*(self._handle_state(i) for i in value))) if candidates and candidates[0] is False: candidates = list(set(printable).difference(candidates[1:])) return self._random.choice(candidates) return self._random.choice(candidates) def _handle_repeat(self, start_range: int, end_range: Any, value: SubPattern) -> str: end_range = min(end_range, self._limit) result = [ "".join(self._handle_state(v) for v in value) # pyright: ignore[reportCallIssue,reportArgumentType] for _ in range(self._random.randint(start_range, max(start_range, end_range))) ] return "".join(result) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/pyproject.toml������������������������������������������������������������0000664�0000000�0000000�00000031462�14721310225�0020414�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������[project] authors = [ {name = "Na'aman Hirschfeld", email = "nhirschfeld@gmail.com"}, ] maintainers = [ {name = "Visakh Unnikrishnan", email = "guacs@litestar.dev"}, {name = "Cody Fincher", email = "cody@litestar.dev"}, {name = "Janek Nouvertné", email = "janek@litestar.dev"}, {name = "Jacob Coffee", email = "jacob@litestar.dev"}, {name = "Peter Schutt", email = "peter@litestar.dev"}, {name = "Alc", email = "alc@litestar.dev"}, ] keywords = ["dataclasses", "msgspec", "pydantic", "attrs", "sqlalchemy",] classifiers = [ "Development Status :: 5 - Production/Stable", "Environment :: Web Environment", "Framework :: Pytest", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Natural Language :: English", "Operating System :: OS Independent", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python", "Topic :: Software Development :: Libraries", "Topic :: Software Development :: Testing :: Unit", "Topic :: Software Development :: Testing", "Topic :: Software Development", "Topic :: Utilities", "Typing :: Typed", ] name = "polyfactory" version = "2.18.1" description = "Mock data generation factories" readme = "docs/PYPI_README.md" license = {text = "MIT"} requires-python = ">=3.8,<4.0" dependencies = [ "faker", "typing-extensions>=4.6.0", ] [project.optional-dependencies] sqlalchemy = ["sqlalchemy>=1.4.29",] pydantic = ["pydantic[email]",] msgspec = ["msgspec",] odmantic = ["odmantic<1.0.0", "pydantic[email]",] beanie = ["beanie", "pydantic[email]",] attrs = ["attrs>=22.2.0",] full = ["pydantic", "odmantic", "msgspec", "beanie", "attrs", "sqlalchemy"] [project.urls] "Issue Tracker" = "https://github.com/litestar-org/polyfactory/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc" Changelog = "https://github.com/litestar-org/polyfactory/releases/" Twitter = "https://twitter.com/LitestarAPI" Reddit = "https://www.reddit.com/r/LitestarAPI" Discord = "https://discord.gg/MmcwxztmQb" Blog = "https://blog.litestar.dev" homepage = "https://github.com/litestar-org/polyfactory" repository = "https://github.com/litestar-org/polyfactory" documentation = "https://github.com/litestar-org/polyfactory" [build-system] build-backend = "hatchling.build" requires = ["hatchling"] [tool.pdm.scripts] lint = "pre-commit run --all-files" test = "pytest tests docs/examples" docs-serve = "sphinx-autobuild docs docs/_build/ -j auto --watch polyfactory --watch docs --watch tests --port 8002" ci = {composite = ["lint", "test"]} [tool.pdm.dev-dependencies] docs = [ "sphinx>=7.1.2", "sphinx-autobuild>=2021.3.14", "auto-pytabs>=0.4.0", "sphinx-copybutton>=0.5.2", "sphinx-toolbox>=3.5.0", "sphinx-design>=0.5.0", "sphinxcontrib-mermaid>=0.9.2", "sphinx-paramlinks>=0.6.0", "sphinx-togglebutton>=0.3.2", # "litestar-sphinx-theme @ {root:uri}/../litestar-sphinx-theme", # only needed when working on the theme "litestar-sphinx-theme @ git+https://github.com/litestar-org/litestar-sphinx-theme.git@v3", "git-cliff>=2.2.1", ] lint = [ "ruff>=0.0.290", "codespell>=2.2.5", "mypy>=1.5.1", "pre-commit>=3.4.0", "shellcheck-py>=0.9.0.5", "pyright>=1.1.327", "sourcery>=1.9.0", ] test = [ "pytest>=7.4.2", "pytest-asyncio>=0.21.1", "pytest-cov>=4.1.0", "hypothesis>=6.86.2", "annotated-types>=0.5.0", ] dev = [ "mongomock-motor>=0.0.21", "aiosqlite>=0.19.0", "sqlalchemy[asyncio]>=1.4.29", ] [tool.mypy] exclude = "^tools/.*" plugins = ["pydantic.mypy"] warn_unused_ignores = true warn_redundant_casts = true warn_unused_configs = true warn_unreachable = true warn_return_any = true strict = true disallow_untyped_decorators = true disallow_any_generics = false implicit_reexport = false show_error_codes = true [tool.pydantic-mypy] init_forbid_extra = true init_typed = true warn_required_dynamic_aliases = true warn_untyped_fields = true [tool.mypy-tests.typing_test_strict] disallow_any_generics = true [tool.pyright] include = ["polyfactory", "tests", "examples"] exclude = ["tools/**/*.*"] [tool.coverage.run] omit = ["*/tests/*"] [tool.pytest.ini_options] addopts = "--strict-config --strict-markers" asyncio_mode = "auto" filterwarnings = [ "ignore:.*pkg_resources.declare_namespace\\('sphinxcontrib'\\).*:DeprecationWarning", "ignore:pkg_resources is deprecated as an API:DeprecationWarning", # Get rid those above once sphinxcontrib-mermaid doesn't use pkg_resources anymore # https://github.com/mgaitan/sphinxcontrib-mermaid/issues/119 ] markers = [ # Marks tests that use `attrs` library "attrs", ] [tool.coverage.report] exclude_lines = [ 'pragma: no cover', 'if TYPE_CHECKING:', 'except ImportError:', 'except ImportError as e:', '\.\.\.', ] [tool.ruff] line-length = 120 src = ["polyfactory", "tests", "docs/examples"] target-version = "py38" [tool.ruff.format] docstring-code-format = true docstring-code-line-length = 88 [tool.ruff.lint] select = ["ALL"] ignore = [ "A003", # flake8-builtins - class attribute {name} is shadowing a python builtin "B010", # flake8-bugbear - do not call setattr with a constant attribute value "D100", # pydocstyle - missing docstring in public module "D101", # pydocstyle - missing docstring in public class "D102", # pydocstyle - missing docstring in public method "D103", # pydocstyle - missing docstring in public function "D104", # pydocstyle - missing docstring in public package "D105", # pydocstyle - missing docstring in magic method "D106", # pydocstyle - missing docstring in public nested class "D107", # pydocstyle - missing docstring in __init__ "D202", # pydocstyle - no blank lines allowed after function docstring "D205", # pydocstyle - 1 blank line required between summary line and description "D415", # pydocstyle - first line should end with a period, question mark, or exclamation point "E501", # pycodestyle line too long, handled by black "N818", # pep8-naming - exception name should be named with an Error suffix "S311", # flake8-bandit - Standard pseudo-random generators are not suitable for security/cryptographic purposes "UP037", # pyupgrade - removes quotes from type annotation "COM812", # conflict with formatter "ISC001", # conflict with formatter ] [tool.ruff.lint.pydocstyle] convention = "google" [tool.ruff.lint.pep8-naming] classmethod-decorators = [ "classmethod", "pydantic.validator", "pydantic.root_validator", "sqlalchemy.ext.declarative.declared_attr", ] [tool.ruff.lint.isort] known-first-party = ["polyfactory", "tests"] section-order = ["future", "standard-library", "third-party", "pydantic", "pydantic_v1", "first-party", "local-folder"] [tool.ruff.lint.isort.sections] pydantic = ["pydantic", "pydantic_core"] pydantic_v1 = ["pydantic.v1"] [tool.ruff.lint.per-file-ignores] "**/*.*" = ["ANN101", "ANN401", "ANN102", "TD",] "polyfactory/**/*.*" = ["PLR0913", "ARG005", # Investigate @guacs "FBT001", # Investigate @guacs "FBT002", # Investigate @guacs "SLF001", # Ignore use of private member access ] "polyfactory/field_meta.py" = ["N806"] "tests/**/*.*" = [ "S101", "D", "ARG", "PGH", "B", "FBT", "PTH", "A", "TCH", "DTZ", "TRY", "EM", "S", "N", "SIM", "PLR", "BLE", "RSE", "C901", "PLW", "G", "PIE", "RUF012", "FA", "ANN", "SLF", "PT", "INP", "TD", "FIX", "FBT", "PLR0913", # too many arguments "PT", "ARG002", # Investigate @guacs "PERF203", # Investigate @guacs ] "docs/examples/**/*.*" = [ "PLR2004", # Investigate @guacs "INP001", # Add __init__.py ] "docs/examples/tests/**/*.*" = [ "S101", "D", "ARG", "PGH", "B", "FBT", "PTH", "A", "TCH", "DTZ", "TRY", "EM", "S", "N", "SIM", "PLR", "BLE", "RSE", "C901", "PLW", "G", "PIE", ] "docs/**/*.*" = [ "S", "B", "DTZ", "A", "TCH", "ERA", "D", "RET", "E731", "RUF012", "FA100", "ARG001", ] "docs/conf.py" = ["FIX002", "ARG001",] "tools/**/*.*" = ["D", "ARG", "EM", "TRY", "G", "FBT", "INP"] [tool.git-cliff.changelog] trim = true header = """ ========= Changelog =========\n All commits to this project will be documented in this file.\n """ # TODO: Fix footers for co-authors body = """ {% if version %}\ `Release [v{{ version | trim_start_matches(pat="v") }}] - {{ timestamp | date(format="%Y-%m-%d") }} <https://github.com/litestar-org/polyfactory/releases/tag/v{{ version | trim_start_matches(pat="v") }}>`_ ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * `See All commits in v{{ version | trim_start_matches(pat="v") }} <https://github.com/litestar-org/polyfactory/commits/v{{ version | trim_start_matches(pat="v") }}>`_ {% else %}\ [unreleased] ------------ {% if previous %}\ {% if previous.commit_id %} `{{ previous.commit_id | default(value='') | truncate(length=7, end='') }} <https://github.com/litestar-org/polyfactory/commit/{{ previous.commit_id }}>`_ is the last commit in the changelog before unreleased changes. {% endif %}\ {% else %} `Initial commit` {% endif %} {% endif %}\ {% if previous %}\ {% if previous.commit_id and version %} `{{ previous.commit_id | default(value='') | truncate(length=7, end='') }} <https://github.com/litestar-org/polyfactory/commit/{{ previous.commit_id }}>`_ ... \ `{{ commit_id | default(value='') | truncate(length=7, end='') }} <https://github.com/litestar-org/polyfactory/commit/{{ commit_id }}>`_ \ | `See diff for {{ version | trim_start_matches(pat="v") }} <https://github.com/litestar-org/polyfactory/compare/{{ previous.commit_id }}...{{ commit_id }}>`_ {% endif %}\ {% endif %}\ {% for group, commits in commits | group_by(attribute="group") %} {{ group | upper_first }} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ {% for commit in commits %} * (`{{ commit.id | default(value='') | truncate(length=7, end='') }} <https://github.com/litestar-org/polyfactory/commit/{{ commit.id }}>`_) {% if commit.breaking %}[**breaking**] {% endif %} - {{ commit.message | upper_first }} {% if commit.github.username %} by `@{{ commit.github.username }} <https://github.com/{{ commit.github.username }}>`_ {%- endif %}\ {% if commit.github.pr_number %} in `#{{ commit.github.pr_number }} <https://github.com/litestar-org/polyfactory/pull/{{ commit.github.pr_number }}>`_ {%- endif %}\ {% endfor %} {% endfor %}\n """ footer = """ Polyfactory Changelog """ [tool.git-cliff.git] commit_parsers = [ { message = "^feat", group = "Features" }, { message = "^fix", group = "Bug Fixes" }, { message = "^doc", group = "Documentation" }, { message = "^perf", group = "Performance" }, { message = "^refactor", group = "Refactor" }, { message = "^style", group = "Styling" }, { message = "^test", group = "Testing" }, { message = "^chore\\(release\\): prepare for", skip = true }, { message = "^chore", group = "Miscellaneous Tasks" }, { body = ".*security", group = "Security" }, ] conventional_commits = true filter_commits = false filter_unconventional = true ignore_tags = "" protect_breaking_commits = false skip_tags = "v0.1.0-beta.1" sort_commits = "oldest" split_commits = false tag_pattern = "v[0-9]*" topo_order = false commit_preprocessors = [ # Matches a single backtick that is not preceded by another backtick (negative lookbehind) # and not followed by another backtick (negative lookahead).. but these aren't supported # in git cliff regexes. So we have to do it in 3 steps: # Step 1: Replace pairs of backticks with a placeholder (e.g., "DOUBLEBACKTICK") { pattern = "``", replace = "DOUBLEBACKTICK" }, # Step 2: Replace single backticks with double backticks { pattern = "`", replace = "``" }, # Step 3: Replace the placeholder back to double backticks { pattern = "DOUBLEBACKTICK", replace = "``" }, # TODO: Fix Co-authored commits ] link_parsers = [ # TODO: Supposedly matches on #1234 but doesn't work? { pattern = "\\(#(\\d+)\\)", href = "https://github.com/litestar-org/polyfactory/issues/$1" }, ] [tool.git-cliff.remote.github] owner = "litestar-org" repo = "polyfactory" ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/sonar-project.properties��������������������������������������������������0000664�0000000�0000000�00000000421�14721310225�0022373�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������sonar.projectKey=starlite-api_polyfactory sonar.organization=litestar-api sonar.python.coverage.reportPaths=coverage.xml sonar.tests=tests sonar.exclusions=docs/**/*, tests/**/* sonar.sources=polyfactory sonar.sourceEncoding=UTF-8 sonar.python.version=3.8, 3.9, 3.10, 3.11 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/tests/��������������������������������������������������������������������0000775�0000000�0000000�00000000000�14721310225�0016634�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/tests/__init__.py���������������������������������������������������������0000664�0000000�0000000�00000000000�14721310225�0020733�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/tests/conftest.py���������������������������������������������������������0000664�0000000�0000000�00000002650�14721310225�0021036�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from __future__ import annotations import importlib.util import random import string import sys from typing import TYPE_CHECKING, TypeVar import pytest if TYPE_CHECKING: from pathlib import Path from types import ModuleType from typing import Callable from pytest import MonkeyPatch T = TypeVar("T") @pytest.fixture() def create_module(tmp_path: Path, monkeypatch: MonkeyPatch) -> Callable[[str], ModuleType]: """Utility fixture for dynamic module creation.""" def wrapped(source: str) -> ModuleType: """ Args: source: Source code as a string. Returns: An imported module. """ def not_none(val: T | None) -> T: assert val is not None return val def module_name_generator() -> str: letters = string.ascii_lowercase return "".join(random.choice(letters) for _ in range(10)) module_name = module_name_generator() path = tmp_path / f"{module_name}.py" path.write_text(source) # https://docs.python.org/3/library/importlib.html#importing-a-source-file-directly spec = not_none(importlib.util.spec_from_file_location(module_name, path)) module = not_none(importlib.util.module_from_spec(spec)) monkeypatch.setitem(sys.modules, module_name, module) not_none(spec.loader).exec_module(module) return module return wrapped ����������������������������������������������������������������������������������������python-polyfactory-2.18.1/tests/constraints/��������������������������������������������������������0000775�0000000�0000000�00000000000�14721310225�0021203�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/tests/constraints/test_byte_constraints.py��������������������������������0000664�0000000�0000000�00000005060�14721310225�0026207�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from random import Random import pytest from hypothesis import given from hypothesis.strategies import booleans, integers from polyfactory.exceptions import ParameterException from polyfactory.value_generators.constrained_strings import handle_constrained_string_or_bytes @given(booleans(), integers(max_value=10000), integers(max_value=10000)) def test_handle_constrained_bytes_with_min_length_and_max_length( to_lower: bool, min_length: int, max_length: int, ) -> None: if min_length < 0 or max_length < 0 or min_length > max_length: with pytest.raises(ParameterException): handle_constrained_string_or_bytes( random=Random(), t_type=bytes, min_length=min_length, max_length=max_length, pattern=None, ) else: result = handle_constrained_string_or_bytes( random=Random(), t_type=bytes, min_length=min_length, max_length=max_length, pattern=None, ) if to_lower: assert result == result.lower() assert len(result) >= min_length assert len(result) <= max_length @given(booleans(), integers(max_value=10000)) def test_handle_constrained_bytes_with_min_length(to_lower: bool, min_length: int) -> None: if min_length < 0: with pytest.raises(ParameterException): handle_constrained_string_or_bytes( random=Random(), t_type=bytes, min_length=min_length, pattern=None, ) else: result = handle_constrained_string_or_bytes( random=Random(), t_type=bytes, min_length=min_length, pattern=None, ) if to_lower: assert result == result.lower() assert len(result) >= min_length @given(booleans(), integers(max_value=10000)) def test_handle_constrained_bytes_with_max_length(to_lower: bool, max_length: int) -> None: if max_length < 0: with pytest.raises(ParameterException): handle_constrained_string_or_bytes( random=Random(), t_type=bytes, max_length=max_length, pattern=None, ) else: result = handle_constrained_string_or_bytes( random=Random(), t_type=bytes, max_length=max_length, pattern=None, ) if to_lower: assert result == result.lower() assert len(result) <= max_length ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/tests/constraints/test_date_constraints.py��������������������������������0000664�0000000�0000000�00000001752�14721310225�0026165�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from datetime import date, timedelta from typing import Dict, Optional import pytest from hypothesis import given from hypothesis.strategies import dates from pydantic import BaseModel, condate from polyfactory.factories.pydantic_factory import ModelFactory @given( dates(max_value=date.today() - timedelta(days=3)), dates(min_value=date.today()), ) @pytest.mark.parametrize(("start", "end"), (("ge", "le"), ("gt", "lt"), ("ge", "lt"), ("gt", "le"))) def test_handle_constrained_date( start: Optional[str], end: Optional[str], start_date: date, end_date: date, ) -> None: if start_date != end_date: kwargs: Dict[str, date] = {} if start: kwargs[start] = start_date if end: kwargs[end] = end_date class MyModel(BaseModel): value: condate(**kwargs) # type: ignore class MyFactory(ModelFactory): __model__ = MyModel result = MyFactory.build() assert result.value ����������������������python-polyfactory-2.18.1/tests/constraints/test_decimal_constraints.py�����������������������������0000664�0000000�0000000�00000030024�14721310225�0026640�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from decimal import Decimal from random import Random from typing import Optional, cast import pytest from hypothesis import given from hypothesis.strategies import decimals, integers from pydantic import BaseModel, condecimal from polyfactory.exceptions import ParameterException from polyfactory.factories.pydantic_factory import ModelFactory from polyfactory.value_generators.constrained_numbers import ( handle_constrained_decimal, handle_decimal_length, is_multiply_of_multiple_of_in_range, passes_pydantic_multiple_validator, ) def test_handle_constrained_decimal_without_constraints() -> None: result = handle_constrained_decimal( random=Random(), multiple_of=None, decimal_places=None, max_digits=None, gt=None, ge=None, lt=None, le=None, ) assert isinstance(result, Decimal) def test_handle_constrained_decimal_length_validation() -> None: with pytest.raises(ParameterException): handle_constrained_decimal( random=Random(), max_digits=2, ge=Decimal("100.000"), ) @given(integers(min_value=0, max_value=100)) def test_handle_constrained_decimal_handles_max_digits(max_digits: int) -> None: if max_digits > 0: result = handle_constrained_decimal( random=Random(), max_digits=max_digits, ) assert len(result.as_tuple().digits) - abs(cast("int", result.as_tuple().exponent)) <= max_digits else: with pytest.raises(ParameterException): handle_constrained_decimal( random=Random(), max_digits=max_digits, ) @given(integers(min_value=0, max_value=100)) def test_handle_constrained_decimal_handles_decimal_places(decimal_places: int) -> None: result = handle_constrained_decimal( random=Random(), decimal_places=decimal_places, ) assert abs(cast("int", result.as_tuple().exponent)) <= decimal_places @given(integers(min_value=0, max_value=100), integers(min_value=1, max_value=100)) def test_handle_constrained_decimal_handles_max_digits_and_decimal_places(max_digits: int, decimal_places: int) -> None: if max_digits > 0 and max_digits > decimal_places: result = handle_constrained_decimal( random=Random(), decimal_places=decimal_places, max_digits=max_digits, ) assert len(result.as_tuple().digits) - abs(cast("int", result.as_tuple().exponent)) <= max_digits else: with pytest.raises(ParameterException): handle_constrained_decimal( random=Random(), decimal_places=decimal_places, max_digits=max_digits, ) @given( decimals( allow_nan=False, allow_infinity=False, min_value=-1000000000, max_value=1000000000, ), ) def test_handle_constrained_decimal_handles_ge(minimum: Decimal) -> None: result = handle_constrained_decimal( random=Random(), ge=minimum, ) assert result >= minimum @given( decimals( allow_nan=False, allow_infinity=False, min_value=-1000000000, max_value=1000000000, ), ) def test_handle_constrained_decimal_handles_gt(minimum: Decimal) -> None: result = handle_constrained_decimal( random=Random(), gt=minimum, ) assert result > minimum @given( decimals( allow_nan=False, allow_infinity=False, min_value=-1000000000, max_value=1000000000, ), ) def test_handle_constrained_decimal_handles_le(maximum: Decimal) -> None: result = handle_constrained_decimal( random=Random(), le=maximum, ) assert result <= maximum @given( decimals( allow_nan=False, allow_infinity=False, min_value=-1000000000, max_value=1000000000, ), ) def test_handle_constrained_decimal_handles_lt(maximum: Decimal) -> None: result = handle_constrained_decimal( random=Random(), lt=maximum, ) assert result < maximum @given( decimals( allow_nan=False, allow_infinity=False, min_value=-1000000000, max_value=1000000000, ), ) def test_handle_constrained_decimal_handles_multiple_of(multiple_of: Decimal) -> None: if multiple_of != Decimal("0"): result = handle_constrained_decimal( random=Random(), multiple_of=multiple_of, ) assert passes_pydantic_multiple_validator(result, multiple_of) else: with pytest.raises(ParameterException): handle_constrained_decimal( random=Random(), multiple_of=multiple_of, ) @given( decimals( allow_nan=False, allow_infinity=False, min_value=-1000000000, max_value=1000000000, ), decimals( allow_nan=False, allow_infinity=False, min_value=-1000000000, max_value=1000000000, ), ) def test_handle_constrained_decimal_handles_multiple_of_with_lt(val1: Decimal, val2: Decimal) -> None: multiple_of, max_value = sorted([val1, val2]) if multiple_of != Decimal("0"): result = handle_constrained_decimal( random=Random(), multiple_of=multiple_of, lt=max_value, ) assert passes_pydantic_multiple_validator(result, multiple_of) else: with pytest.raises(ParameterException): handle_constrained_decimal( random=Random(), multiple_of=multiple_of, lt=max_value, ) @given( decimals( allow_nan=False, allow_infinity=False, min_value=-1000000000, max_value=1000000000, ), decimals( allow_nan=False, allow_infinity=False, min_value=-1000000000, max_value=1000000000, ), ) def test_handle_constrained_decimal_handles_multiple_of_with_le(val1: Decimal, val2: Decimal) -> None: multiple_of, max_value = sorted([val1, val2]) if multiple_of != Decimal("0"): result = handle_constrained_decimal( random=Random(), multiple_of=multiple_of, le=max_value, ) assert passes_pydantic_multiple_validator(result, multiple_of) else: with pytest.raises(ParameterException): handle_constrained_decimal( random=Random(), multiple_of=multiple_of, le=max_value, ) @given( decimals( allow_nan=False, allow_infinity=False, min_value=-1000000000, max_value=1000000000, ), decimals( allow_nan=False, allow_infinity=False, min_value=-1000000000, max_value=1000000000, ), ) def test_handle_constrained_decimal_handles_multiple_of_with_ge(val1: Decimal, val2: Decimal) -> None: min_value, multiple_of = sorted([val1, val2]) if multiple_of != Decimal("0"): result = handle_constrained_decimal( random=Random(), multiple_of=multiple_of, ge=min_value, ) assert passes_pydantic_multiple_validator(result, multiple_of) else: with pytest.raises(ParameterException): handle_constrained_decimal( random=Random(), multiple_of=multiple_of, ge=min_value, ) @given( decimals( allow_nan=False, allow_infinity=False, min_value=-1000000000, max_value=1000000000, ), decimals( allow_nan=False, allow_infinity=False, min_value=-1000000000, max_value=1000000000, ), ) def test_handle_constrained_decimal_handles_multiple_of_with_gt(val1: Decimal, val2: Decimal) -> None: min_value, multiple_of = sorted([val1, val2]) if multiple_of != Decimal("0"): result = handle_constrained_decimal( random=Random(), multiple_of=multiple_of, gt=min_value, ) assert passes_pydantic_multiple_validator(result, multiple_of) else: with pytest.raises(ParameterException): handle_constrained_decimal( random=Random(), multiple_of=multiple_of, gt=min_value, ) @given( decimals( allow_nan=False, allow_infinity=False, min_value=-1000000000, max_value=1000000000, ), decimals( allow_nan=False, allow_infinity=False, min_value=-1000000000, max_value=1000000000, ), decimals( allow_nan=False, allow_infinity=False, min_value=-1000000000, max_value=1000000000, ), ) def test_handle_constrained_decimal_handles_multiple_of_with_ge_and_le( val1: Decimal, val2: Decimal, val3: Decimal, ) -> None: min_value, multiple_of, max_value = sorted([val1, val2, val3]) if multiple_of != Decimal("0") and is_multiply_of_multiple_of_in_range( minimum=min_value, maximum=max_value, multiple_of=multiple_of, ): result = handle_constrained_decimal( random=Random(), multiple_of=multiple_of, ge=min_value, le=max_value, ) assert passes_pydantic_multiple_validator(result, multiple_of) else: with pytest.raises(ParameterException): handle_constrained_decimal( random=Random(), multiple_of=multiple_of, ge=min_value, le=max_value, ) def test_max_digits_and_decimal_places() -> None: class Person(BaseModel): social_score: condecimal( decimal_places=4, max_digits=5, gt=Decimal("0.0"), le=Decimal("9.9999"), ) # type: ignore class PersonFactory(ModelFactory): __model__ = Person result = PersonFactory.build() assert isinstance(result.social_score, Decimal) assert len(str(result.social_score).split(".")[1]) == 4 assert result.social_score > 0 def test_handle_decimal_length() -> None: decimal = Decimal("999.9999999") # here digits should determine decimal length max_digits = 5 decimal_places: Optional[int] = 5 result = handle_decimal_length(decimal, decimal_places, max_digits) assert isinstance(result, Decimal) assert len(result.as_tuple().digits) == 5 assert abs(cast("int", result.as_tuple().exponent)) == 2 # here decimal places should determine max length max_digits = 10 decimal_places = 5 result = handle_decimal_length(decimal, decimal_places, max_digits) assert isinstance(result, Decimal) assert len(result.as_tuple().digits) == 8 assert abs(cast("int", result.as_tuple().exponent)) == 5 # here digits determine decimal length max_digits = 10 decimal_places = None result = handle_decimal_length(decimal, decimal_places, max_digits) assert isinstance(result, Decimal) assert len(result.as_tuple().digits) == 10 assert abs(cast("int", result.as_tuple().exponent)) == 7 # here decimal places determine decimal length max_digits = None # type: ignore decimal_places = 5 result = handle_decimal_length(decimal, decimal_places, max_digits) assert isinstance(result, Decimal) assert len(result.as_tuple().digits) == 8 assert abs(cast("int", result.as_tuple().exponent)) == 5 # here max_decimals is below 0 decimal = Decimal("99.99") max_digits = 1 result = handle_decimal_length(decimal, decimal_places, max_digits) assert isinstance(result, Decimal) assert len(result.as_tuple().digits) == 1 assert cast("int", result.as_tuple().exponent) == 0 def test_zero_to_one_range() -> None: class FractionExample(BaseModel): fraction: condecimal(ge=Decimal("0.0"), le=Decimal("1.0"), decimal_places=2, max_digits=3) # type: ignore class FractionExampleFactory(ModelFactory): __model__ = FractionExample result = FractionExampleFactory.build() assert result.fraction >= Decimal("0") assert result.fraction <= Decimal("1") ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/tests/constraints/test_float_constraints.py�������������������������������0000664�0000000�0000000�00000016241�14721310225�0026354�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from random import Random import pytest from hypothesis import given from hypothesis.strategies import floats from polyfactory.exceptions import ParameterException from polyfactory.value_generators.constrained_numbers import ( handle_constrained_float, is_multiply_of_multiple_of_in_range, passes_pydantic_multiple_validator, ) def test_handle_constrained_float_without_constraints() -> None: result = handle_constrained_float( random=Random(), ) assert isinstance(result, float) @given( floats( allow_nan=False, allow_infinity=False, min_value=-1000000000, max_value=1000000000, ), ) def test_handle_constrained_float_handles_ge(minimum: float) -> None: result = handle_constrained_float( random=Random(), ge=minimum, ) assert result >= minimum @given( floats( allow_nan=False, allow_infinity=False, min_value=-1000000000, max_value=1000000000, ), ) def test_handle_constrained_float_handles_gt(minimum: float) -> None: result = handle_constrained_float( random=Random(), gt=minimum, ) assert result > minimum @given( floats( allow_nan=False, allow_infinity=False, min_value=-1000000000, max_value=1000000000, ), ) def test_handle_constrained_float_handles_le(maximum: float) -> None: result = handle_constrained_float( random=Random(), le=maximum, ) assert result <= maximum @given( floats( allow_nan=False, allow_infinity=False, min_value=-1000000000, max_value=1000000000, ), ) def test_handle_constrained_float_handles_lt(maximum: float) -> None: result = handle_constrained_float( random=Random(), lt=maximum, ) assert result < maximum @given( floats( allow_nan=False, allow_infinity=False, min_value=-1000000000, max_value=1000000000, ), ) def test_handle_constrained_float_handles_multiple_of(multiple_of: float) -> None: if multiple_of != 0.0: result = handle_constrained_float( random=Random(), multiple_of=multiple_of, ) assert passes_pydantic_multiple_validator(result, multiple_of) else: with pytest.raises(ParameterException): handle_constrained_float( random=Random(), multiple_of=multiple_of, ) @given( floats( allow_nan=False, allow_infinity=False, min_value=-1000000000, max_value=1000000000, ), floats( allow_nan=False, allow_infinity=False, min_value=-1000000000, max_value=1000000000, ), ) def test_handle_constrained_float_handles_multiple_of_with_lt(val1: float, val2: float) -> None: multiple_of, max_value = sorted([val1, val2]) if multiple_of != 0.0: result = handle_constrained_float( random=Random(), multiple_of=multiple_of, lt=max_value, ) assert passes_pydantic_multiple_validator(result, multiple_of) else: with pytest.raises(ParameterException): handle_constrained_float( random=Random(), multiple_of=multiple_of, lt=max_value, ) @given( floats( allow_nan=False, allow_infinity=False, min_value=-1000000000, max_value=1000000000, ), floats( allow_nan=False, allow_infinity=False, min_value=-1000000000, max_value=1000000000, ), ) def test_handle_constrained_float_handles_multiple_of_with_le(val1: float, val2: float) -> None: multiple_of, max_value = sorted([val1, val2]) if multiple_of != 0.0: result = handle_constrained_float( random=Random(), multiple_of=multiple_of, le=max_value, ) assert passes_pydantic_multiple_validator(result, multiple_of) else: with pytest.raises(ParameterException): handle_constrained_float( random=Random(), multiple_of=multiple_of, le=max_value, ) @given( floats( allow_nan=False, allow_infinity=False, min_value=-1000000000, max_value=1000000000, ), floats( allow_nan=False, allow_infinity=False, min_value=-1000000000, max_value=1000000000, ), ) def test_handle_constrained_float_handles_multiple_of_with_ge(val1: float, val2: float) -> None: min_value, multiple_of = sorted([val1, val2]) if multiple_of != 0.0: result = handle_constrained_float( random=Random(), multiple_of=multiple_of, ge=min_value, ) assert passes_pydantic_multiple_validator(result, multiple_of) else: with pytest.raises(ParameterException): handle_constrained_float( random=Random(), multiple_of=multiple_of, ge=min_value, ) @given( floats( allow_nan=False, allow_infinity=False, min_value=-1000000000, max_value=1000000000, ), floats( allow_nan=False, allow_infinity=False, min_value=-1000000000, max_value=1000000000, ), ) def test_handle_constrained_float_handles_multiple_of_with_gt(val1: float, val2: float) -> None: min_value, multiple_of = sorted([val1, val2]) if multiple_of != 0.0: result = handle_constrained_float( random=Random(), multiple_of=multiple_of, gt=min_value, ) assert passes_pydantic_multiple_validator(result, multiple_of) else: with pytest.raises(ParameterException): handle_constrained_float( random=Random(), multiple_of=multiple_of, gt=min_value, ) @pytest.mark.skip(reason="fails on edge cases") @given( floats( allow_nan=False, allow_infinity=False, min_value=-1000000000, max_value=1000000000, ), floats( allow_nan=False, allow_infinity=False, min_value=-1000000000, max_value=1000000000, ), floats( allow_nan=False, allow_infinity=False, min_value=-1000000000, max_value=1000000000, ), ) def test_handle_constrained_float_handles_multiple_of_with_ge_and_le(val1: float, val2: float, val3: float) -> None: min_value, multiple_of, max_value = sorted([val1, val2, val3]) if multiple_of != 0.0 and is_multiply_of_multiple_of_in_range( minimum=min_value, maximum=max_value, multiple_of=multiple_of, ): result = handle_constrained_float( random=Random(), multiple_of=multiple_of, ge=min_value, lt=max_value, ) assert passes_pydantic_multiple_validator(result, multiple_of) else: with pytest.raises(ParameterException): handle_constrained_float( random=Random(), multiple_of=multiple_of, ge=min_value, lt=max_value, ) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/tests/constraints/test_frozen_set_constraints.py��������������������������0000664�0000000�0000000�00000005306�14721310225�0027425�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from contextlib import suppress from random import Random from typing import Any import pytest from hypothesis import given from hypothesis.strategies import integers from polyfactory.exceptions import ParameterException from polyfactory.factories.pydantic_factory import ModelFactory from polyfactory.field_meta import FieldMeta from polyfactory.value_generators.constrained_collections import ( handle_constrained_collection, ) @given( integers(min_value=0, max_value=10), integers(min_value=0, max_value=10), ) def test_handle_constrained_set_with_min_items_and_max_items(min_items: int, max_items: int) -> None: if max_items >= min_items: result = handle_constrained_collection( collection_type=frozenset, factory=ModelFactory, field_meta=FieldMeta(name="test", annotation=frozenset, random=Random()), item_type=str, max_items=max_items, min_items=min_items, ) assert len(result) >= min_items assert len(result) <= max_items or 1 else: with pytest.raises(ParameterException): handle_constrained_collection( collection_type=frozenset, factory=ModelFactory, field_meta=FieldMeta(name="test", annotation=frozenset, random=Random()), item_type=str, max_items=max_items, min_items=min_items, ) @given( integers(min_value=0, max_value=10), ) def test_handle_constrained_set_with_max_items( max_items: int, ) -> None: result = handle_constrained_collection( collection_type=frozenset, factory=ModelFactory, field_meta=FieldMeta(name="test", annotation=frozenset, random=Random()), item_type=str, max_items=max_items, ) assert len(result) <= max_items or 1 @given( integers(min_value=0, max_value=10), ) def test_handle_constrained_set_with_min_items( min_items: int, ) -> None: result = handle_constrained_collection( collection_type=frozenset, factory=ModelFactory, field_meta=FieldMeta(name="test", annotation=frozenset, random=Random()), item_type=str, min_items=min_items, ) assert len(result) >= min_items @pytest.mark.parametrize("t_type", tuple(ModelFactory.get_provider_map())) def test_handle_constrained_set_with_different_types(t_type: Any) -> None: with suppress(ParameterException): result = handle_constrained_collection( collection_type=frozenset, factory=ModelFactory, field_meta=FieldMeta(name="test", annotation=frozenset, random=Random()), item_type=t_type, ) assert len(result) >= 0 ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/tests/constraints/test_get_field_value_constraints.py���������������������0000664�0000000�0000000�00000004443�14721310225�0030366�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from datetime import date, datetime, timedelta from decimal import Decimal from random import Random from typing import FrozenSet, List, Set, Tuple, Type, Union, cast import pytest from typing_extensions import Annotated from polyfactory.factories.base import BaseFactory from polyfactory.field_meta import Constraints, FieldMeta @pytest.mark.parametrize("t", (int, float, Decimal)) def test_numbers(t: Type[Union[int, float, Decimal]]) -> None: constraints: Constraints = {"ge": 1, "le": 20} field_meta = FieldMeta.from_type(annotation=t, name="foo", constraints=constraints, random=Random()) value = BaseFactory.get_field_value(field_meta) assert value >= constraints["ge"] assert value <= constraints["le"] @pytest.mark.parametrize("t", (str, bytes)) def test_str_and_bytes(t: Type[Union[str, bytes]]) -> None: constraints: Constraints = {"min_length": 20, "max_length": 45} field_meta = FieldMeta.from_type(annotation=t, name="foo", constraints=constraints, random=Random()) value = BaseFactory.get_field_value(field_meta) assert len(value) >= constraints["min_length"] assert len(value) <= constraints["max_length"] @pytest.mark.parametrize("t", (List[int], Set[int], Tuple[int], FrozenSet[int])) def test_collections(t: Type[Union[Tuple, List, Set, FrozenSet]]) -> None: constraints: Constraints = { "min_length": 2, "max_length": 10, } field_meta = FieldMeta.from_type(annotation=t, name="foo", constraints=constraints, random=Random()) value = BaseFactory.get_field_value(field_meta) assert len(value) >= constraints["min_length"] assert len(value) <= constraints["max_length"] def test_date() -> None: ge_date = datetime.now().date() le_date = ge_date + timedelta(days=10) constraints = {"ge": ge_date, "le": le_date} field_meta = FieldMeta.from_type( annotation=date, name="foo", constraints=cast(Constraints, constraints), random=Random(), ) value = BaseFactory.get_field_value(field_meta) assert value >= ge_date assert value <= le_date def test_constraints_parsing() -> None: constraints = Constraints(min_length=10) annotation = Annotated[str, constraints] field_meta = FieldMeta.from_type(annotation) assert field_meta.constraints == constraints �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/tests/constraints/test_int_constraints.py���������������������������������0000664�0000000�0000000�00000015117�14721310225�0026042�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from random import Random import pytest from hypothesis import HealthCheck, given, settings from hypothesis.strategies import integers from polyfactory.exceptions import ParameterException from polyfactory.value_generators.constrained_numbers import ( handle_constrained_int, is_multiply_of_multiple_of_in_range, passes_pydantic_multiple_validator, ) def test_handle_constrained_int_without_constraints() -> None: result = handle_constrained_int( random=Random(), ) assert isinstance(result, int) @given(integers(min_value=-1000000000, max_value=1000000000)) def test_handle_constrained_int_handles_ge(minimum: int) -> None: result = handle_constrained_int( random=Random(), ge=minimum, ) assert result >= minimum @given(integers(min_value=-1000000000, max_value=1000000000)) def test_handle_constrained_int_handles_gt(minimum: int) -> None: result = handle_constrained_int( random=Random(), gt=minimum, ) assert result > minimum @given(integers(min_value=-1000000000, max_value=1000000000)) def test_handle_constrained_int_handles_le(maximum: int) -> None: result = handle_constrained_int( random=Random(), le=maximum, ) assert result <= maximum @given(integers(min_value=-1000000000, max_value=1000000000)) def test_handle_constrained_int_handles_lt(maximum: int) -> None: result = handle_constrained_int( random=Random(), lt=maximum, ) assert result < maximum @settings(suppress_health_check=(HealthCheck.filter_too_much,)) @given( integers(min_value=1, max_value=10), integers(min_value=1, max_value=10), ) def test_handle_constrained_int_handles_ge_with_le(val1: int, val2: int) -> None: min_value, max_value = sorted([val1, val2]) result = handle_constrained_int( random=Random(), ge=min_value, le=max_value, ) assert min_value <= result <= max_value @given(integers(min_value=-1000000000, max_value=1000000000)) def test_handle_constrained_int_handles_multiple_of(multiple_of: int) -> None: if multiple_of != 0: result = handle_constrained_int( random=Random(), multiple_of=multiple_of, ) assert passes_pydantic_multiple_validator(result, multiple_of) else: with pytest.raises(ParameterException): handle_constrained_int( random=Random(), multiple_of=multiple_of, ) @given( integers(min_value=-1000000000, max_value=1000000000), integers(min_value=-1000000000, max_value=1000000000), ) def test_handle_constrained_int_handles_multiple_of_with_lt(val1: int, val2: int) -> None: multiple_of, max_value = sorted([val1, val2]) if multiple_of != 0: result = handle_constrained_int( random=Random(), multiple_of=multiple_of, lt=max_value, ) assert passes_pydantic_multiple_validator(result, multiple_of) else: with pytest.raises(ParameterException): handle_constrained_int( random=Random(), multiple_of=multiple_of, lt=max_value, ) @given( integers(min_value=-1000000000, max_value=1000000000), integers(min_value=-1000000000, max_value=1000000000), ) def test_handle_constrained_int_handles_multiple_of_with_le(val1: int, val2: int) -> None: multiple_of, max_value = sorted([val1, val2]) if multiple_of != 0: result = handle_constrained_int( random=Random(), multiple_of=multiple_of, le=max_value, ) assert passes_pydantic_multiple_validator(result, multiple_of) else: with pytest.raises(ParameterException): handle_constrained_int( random=Random(), multiple_of=multiple_of, le=max_value, ) @given( integers(min_value=-1000000000, max_value=1000000000), integers(min_value=-1000000000, max_value=1000000000), ) def test_handle_constrained_int_handles_multiple_of_with_ge(val1: int, val2: int) -> None: min_value, multiple_of = sorted([val1, val2]) if multiple_of != 0: result = handle_constrained_int( random=Random(), multiple_of=multiple_of, ge=min_value, ) assert passes_pydantic_multiple_validator(result, multiple_of) else: with pytest.raises(ParameterException): handle_constrained_int( random=Random(), multiple_of=multiple_of, ge=min_value, ) @given( integers(min_value=-1000000000, max_value=1000000000), integers(min_value=-1000000000, max_value=1000000000), ) def test_handle_constrained_int_handles_multiple_of_with_gt(val1: int, val2: int) -> None: min_value, multiple_of = sorted([val1, val2]) if multiple_of != 0: result = handle_constrained_int( random=Random(), multiple_of=multiple_of, gt=min_value, ) assert passes_pydantic_multiple_validator(result, multiple_of) else: with pytest.raises(ParameterException): handle_constrained_int( random=Random(), multiple_of=multiple_of, gt=min_value, ) @given( integers(min_value=-1000000000, max_value=1000000000), integers(min_value=-1000000000, max_value=1000000000), integers(min_value=-1000000000, max_value=1000000000), ) def test_handle_constrained_int_handles_multiple_of_with_ge_and_le(val1: int, val2: int, val3: int) -> None: min_value, multiple_of, max_value = sorted([val1, val2, val3]) if multiple_of != 0 and is_multiply_of_multiple_of_in_range( minimum=min_value, maximum=max_value, multiple_of=multiple_of, ): result = handle_constrained_int( random=Random(), multiple_of=multiple_of, ge=min_value, le=max_value, ) assert passes_pydantic_multiple_validator(result, multiple_of) else: with pytest.raises(ParameterException): handle_constrained_int( random=Random(), multiple_of=multiple_of, ge=min_value, le=max_value, ) def test_constraint_randomness() -> None: random = Random(10) result = handle_constrained_int( random=random, ) assert result == 55 result = handle_constrained_int( random=random, ) assert result == 61 result = handle_constrained_int( random=random, ) assert result == 85 �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/tests/constraints/test_list_constraints.py��������������������������������0000664�0000000�0000000�00000006430�14721310225�0026221�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������import sys from random import Random from typing import Any, List import pytest from hypothesis import given from hypothesis.strategies import integers from pydantic import VERSION from polyfactory.exceptions import ParameterException from polyfactory.factories.pydantic_factory import ModelFactory from polyfactory.field_meta import FieldMeta from polyfactory.value_generators.constrained_collections import ( handle_constrained_collection, ) @given( integers(min_value=0, max_value=10), integers(min_value=0, max_value=10), ) def test_handle_constrained_list_with_min_items_and_max_items(min_items: int, max_items: int) -> None: if max_items >= min_items: result = handle_constrained_collection( collection_type=list, factory=ModelFactory, field_meta=FieldMeta(name="test", annotation=list, random=Random()), item_type=str, max_items=max_items, min_items=min_items, ) assert len(result) >= min_items assert len(result) <= max_items or 1 else: with pytest.raises(ParameterException): handle_constrained_collection( collection_type=list, factory=ModelFactory, field_meta=FieldMeta(name="test", annotation=list, random=Random()), item_type=str, max_items=max_items, min_items=min_items, ) @given( integers(min_value=0, max_value=10), ) def test_handle_constrained_list_with_max_items( max_items: int, ) -> None: result = handle_constrained_collection( collection_type=list, factory=ModelFactory, field_meta=FieldMeta(name="test", annotation=list, random=Random()), item_type=str, max_items=max_items, ) assert len(result) <= max_items or 1 @given( integers(min_value=0, max_value=10), ) def test_handle_constrained_list_with_min_items( min_items: int, ) -> None: result = handle_constrained_collection( collection_type=list, factory=ModelFactory, field_meta=FieldMeta.from_type(List[str], name="test", random=Random()), item_type=str, min_items=min_items, ) assert len(result) >= min_items @pytest.mark.skipif( sys.version_info < (3, 9) and VERSION.startswith("2"), reason="fails on python 3.8 with pydantic v2", ) @pytest.mark.parametrize("t_type", tuple(ModelFactory.get_provider_map())) def test_handle_constrained_list_with_different_types(t_type: Any) -> None: field_meta = FieldMeta.from_type(List[t_type], name="test", random=Random()) result = handle_constrained_collection( collection_type=list, factory=ModelFactory, field_meta=field_meta.children[0], # type: ignore[index] item_type=t_type, ) assert len(result) >= 0 def test_handle_unique_items() -> None: field_meta = FieldMeta.from_type(List[str], name="test", random=Random(), constraints={"unique_items": True}) result = handle_constrained_collection( collection_type=list, factory=ModelFactory, field_meta=field_meta.children[0], # type: ignore[index] item_type=str, unique_items=True, min_items=2, max_items=2, ) assert len(result) == 2 assert len(set(result)) == 2 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/tests/constraints/test_mapping_constraints.py�����������������������������0000664�0000000�0000000�00000004664�14721310225�0026710�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from random import Random import pytest from hypothesis import given from hypothesis.strategies import integers from polyfactory.exceptions import ParameterException from polyfactory.factories.pydantic_factory import ModelFactory from polyfactory.field_meta import FieldMeta from polyfactory.value_generators.constrained_collections import ( handle_constrained_mapping, ) @given( integers(min_value=0, max_value=10), integers(min_value=0, max_value=10), ) def test_handle_constrained_mapping_with_min_items_and_max_items(min_items: int, max_items: int) -> None: random = Random() key_field = FieldMeta(name="key", annotation=str, random=random) value_field = FieldMeta(name="value", annotation=int, random=random) field_meta = FieldMeta(name="test", annotation=dict, children=[key_field, value_field], random=random) if max_items >= min_items: result = handle_constrained_mapping( factory=ModelFactory, field_meta=field_meta, max_items=max_items, min_items=min_items, ) assert len(result) >= min_items assert len(result) <= max_items or 1 for key, value in result.items(): assert isinstance(key, str) assert isinstance(value, int) else: with pytest.raises(ParameterException): handle_constrained_mapping( factory=ModelFactory, field_meta=field_meta, max_items=max_items, min_items=min_items, ) def test_handle_constrained_mapping_with_constrained_key_and_value() -> None: random = Random() key_min_length = 5 value_gt = 100 min_length = 5 max_length = 10 key_field = FieldMeta(name="key", annotation=str, random=random, constraints={"min_length": key_min_length}) value_field = FieldMeta(name="value", annotation=int, random=random, constraints={"gt": value_gt}) field_meta = FieldMeta(name="test", annotation=dict, children=[key_field, value_field], random=random) result = handle_constrained_mapping( factory=ModelFactory, field_meta=field_meta, min_items=min_length, max_items=max_length, ) assert len(result) >= min_length assert len(result) <= max_length for key, value in result.items(): assert isinstance(key, str) assert isinstance(value, int) assert len(key) >= key_min_length assert value >= value_gt ����������������������������������������������������������������������������python-polyfactory-2.18.1/tests/constraints/test_set_constraints.py���������������������������������0000664�0000000�0000000�00000005217�14721310225�0026043�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from contextlib import suppress from random import Random from typing import Any import pytest from hypothesis import given from hypothesis.strategies import integers from polyfactory.exceptions import ParameterException from polyfactory.factories.pydantic_factory import ModelFactory from polyfactory.field_meta import FieldMeta from polyfactory.value_generators.constrained_collections import ( handle_constrained_collection, ) @given( integers(min_value=0, max_value=10), integers(min_value=0, max_value=10), ) def test_handle_constrained_set_with_min_items_and_max_items(min_items: int, max_items: int) -> None: if max_items >= min_items: result = handle_constrained_collection( collection_type=list, factory=ModelFactory, field_meta=FieldMeta(name="test", annotation=set, random=Random()), item_type=str, max_items=max_items, min_items=min_items, ) assert len(result) >= min_items assert len(result) <= max_items or 1 else: with pytest.raises(ParameterException): handle_constrained_collection( collection_type=list, factory=ModelFactory, field_meta=FieldMeta(name="test", annotation=set, random=Random()), item_type=str, max_items=max_items, min_items=min_items, ) @given( integers(min_value=0, max_value=10), ) def test_handle_constrained_set_with_max_items( max_items: int, ) -> None: result = handle_constrained_collection( collection_type=list, factory=ModelFactory, field_meta=FieldMeta(name="test", annotation=set, random=Random()), item_type=str, max_items=max_items, ) assert len(result) <= max_items or 1 @given( integers(min_value=0, max_value=10), ) def test_handle_constrained_set_with_min_items( min_items: int, ) -> None: result = handle_constrained_collection( collection_type=list, factory=ModelFactory, field_meta=FieldMeta(name="test", annotation=set, random=Random()), item_type=str, min_items=min_items, ) assert len(result) >= min_items @pytest.mark.parametrize("t_type", tuple(ModelFactory.get_provider_map())) def test_handle_constrained_set_with_different_types(t_type: Any) -> None: with suppress(ParameterException): result = handle_constrained_collection( collection_type=list, factory=ModelFactory, field_meta=FieldMeta(name="test", annotation=set, random=Random()), item_type=t_type, ) assert len(result) >= 0 ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/tests/constraints/test_string_constraints.py������������������������������0000664�0000000�0000000�00000012103�14721310225�0026546�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������import re from random import Random import pytest from hypothesis import given, settings from hypothesis.strategies import booleans, integers from polyfactory.exceptions import ParameterException from polyfactory.value_generators.constrained_strings import handle_constrained_string_or_bytes REGEXES = [ r"(a|b|c)xz", r"a|b", r"[0-9]{2,4}", r"a{2,3}", r"ma?n", r"ma+n", r"ma*n", r"a$", r"\Athe", r"\bfoo", r"foo\b", r"\Bfoo", r"foo\B", ] @settings(deadline=600) @given( booleans(), integers(min_value=5, max_value=100), integers(min_value=5, max_value=100), ) def test_handle_constrained_string_with_min_length_and_max_length_and_regex( to_lower: bool, min_length: int, max_length: int, ) -> None: if min_length < 0 or max_length < 0 or min_length > max_length: with pytest.raises(ParameterException): handle_constrained_string_or_bytes( random=Random(), t_type=str, lower_case=to_lower, upper_case=to_lower, min_length=min_length, max_length=max_length, pattern=None, ) else: for regex in REGEXES: result = handle_constrained_string_or_bytes( random=Random(), t_type=str, lower_case=to_lower, upper_case=to_lower, min_length=min_length, max_length=max_length, pattern=None, ) if to_lower: assert result == result.lower() if match := re.search(regex, result): assert match[0] assert len(result) >= min_length assert len(result) <= max_length @given(booleans(), integers(max_value=10000), integers(max_value=10000)) def test_handle_constrained_string_with_min_length_and_max_length( to_lower: bool, min_length: int, max_length: int, ) -> None: if min_length < 0 or max_length < 0 or min_length > max_length: with pytest.raises(ParameterException): handle_constrained_string_or_bytes( random=Random(), t_type=str, lower_case=to_lower, upper_case=to_lower, min_length=min_length, max_length=max_length, pattern=None, ) else: result = handle_constrained_string_or_bytes( random=Random(), t_type=str, lower_case=to_lower, upper_case=to_lower, min_length=min_length, max_length=max_length, pattern=None, ) if to_lower: assert result == result.lower() assert len(result) >= min_length assert len(result) <= max_length @given(booleans(), integers(max_value=10000)) def test_handle_constrained_string_with_min_length(to_lower: bool, min_length: int) -> None: if min_length < 0: with pytest.raises(ParameterException): handle_constrained_string_or_bytes( random=Random(), t_type=str, lower_case=to_lower, upper_case=to_lower, min_length=min_length, pattern=None, ) else: result = handle_constrained_string_or_bytes( random=Random(), t_type=str, lower_case=to_lower, upper_case=to_lower, min_length=min_length, pattern=None, ) if to_lower: assert result == result.lower() assert len(result) >= min_length @given(booleans(), integers(max_value=10000)) def test_handle_constrained_string_with_max_length(to_lower: bool, max_length: int) -> None: if max_length < 0: with pytest.raises(ParameterException): handle_constrained_string_or_bytes( random=Random(), t_type=str, lower_case=to_lower, upper_case=to_lower, max_length=max_length, pattern=None, ) else: result = handle_constrained_string_or_bytes( random=Random(), t_type=str, lower_case=to_lower, upper_case=to_lower, max_length=max_length, pattern=None, ) if to_lower: assert result == result.lower() assert len(result) <= max_length def test_pattern() -> None: result = handle_constrained_string_or_bytes( random=Random(), t_type=str, lower_case=False, upper_case=True, min_length=6, max_length=10, pattern="abc", ) assert len(result) >= 6 assert len(result) <= 10 assert result.isupper() result = handle_constrained_string_or_bytes( random=Random(), t_type=str, lower_case=True, upper_case=False, min_length=6, max_length=10, pattern="abc", ) assert len(result) >= 6 assert len(result) <= 10 assert not result.isupper() �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/tests/models.py�����������������������������������������������������������0000664�0000000�0000000�00000001532�14721310225�0020472�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from datetime import date, datetime from typing import List, Optional, Union from uuid import uuid4 from pydantic import UUID4, BaseModel from polyfactory.factories.pydantic_factory import ModelFactory class Pet(BaseModel): name: str species: str color: str sound: str age: float class Person(BaseModel): id: UUID4 name: str hobbies: Optional[List[str]] nicks: List[str] age: Union[float, int] pets: List[Pet] birthday: Union[datetime, date] class PersonFactoryWithoutDefaults(ModelFactory): __model__ = Person class PersonFactoryWithDefaults(PersonFactoryWithoutDefaults): id = uuid4() name = "moishe" hobbies = ["fishing"] nicks: List[str] = [] age = 33 pets: List[Pet] = [] birthday = datetime(2021 - 33, 1, 1) class PetFactory(ModelFactory): __model__ = Pet ����������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/tests/sqlalchemy_factory/�������������������������������������������������0000775�0000000�0000000�00000000000�14721310225�0022525�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/tests/sqlalchemy_factory/test_sqlalchemy_factory_common.py����������������0000664�0000000�0000000�00000033142�14721310225�0031402�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from dataclasses import dataclass from datetime import datetime from decimal import Decimal from enum import Enum from typing import Any, Callable, Type from uuid import UUID import pytest from sqlalchemy import ( Boolean, Column, DateTime, ForeignKey, Integer, Numeric, String, create_engine, func, inspect, orm, text, types, ) from sqlalchemy.engine import Engine from sqlalchemy.ext.asyncio import AsyncEngine, AsyncSession, create_async_engine from sqlalchemy.ext.hybrid import hybrid_property from sqlalchemy.orm import Session from sqlalchemy.orm.decl_api import DeclarativeMeta, registry from polyfactory.exceptions import ConfigurationException from polyfactory.factories.base import BaseFactory from polyfactory.factories.sqlalchemy_factory import SQLAlchemyFactory from polyfactory.fields import Ignore @pytest.fixture() def engine() -> Engine: return create_engine("sqlite:///:memory:") @pytest.fixture() def async_engine() -> AsyncEngine: return create_async_engine("sqlite+aiosqlite:///:memory:") async def create_tables(engine: AsyncEngine, base: Type) -> None: async with engine.connect() as connection: await connection.run_sync(base.metadata.create_all) _registry = registry() class Base(metaclass=DeclarativeMeta): __abstract__ = True __allow_unmapped__ = True registry = _registry metadata = _registry.metadata class Author(Base): __tablename__ = "authors" id: Any = Column(Integer(), primary_key=True) books: Any = orm.relationship( "Book", collection_class=list, uselist=True, back_populates="author", ) class Book(Base): __tablename__ = "books" id: Any = Column(Integer(), primary_key=True) author_id: Any = Column( Integer(), ForeignKey(Author.id), nullable=False, ) author: Any = orm.relationship( Author, uselist=False, back_populates="books", ) @dataclass class NonSQLAchemyClass: id: int @pytest.mark.parametrize( "invalid_model", ( Base, NonSQLAchemyClass, ), ) def test_invalid_model(invalid_model: type) -> None: with pytest.raises(ConfigurationException): SQLAlchemyFactory.create_factory(invalid_model) def test_python_type_handling() -> None: _registry = registry() class Base(metaclass=DeclarativeMeta): __abstract__ = True registry = _registry metadata = _registry.metadata class Animal(str, Enum): DOG = "Dog" CAT = "Cat" class Model(Base): __tablename__ = "model" id: Any = Column(Integer(), primary_key=True) str_type: Any = Column(String(), nullable=False) enum_type: Any = Column(types.Enum(Animal), nullable=False) str_array_type: Any = Column( types.ARRAY(types.String), nullable=False, ) class ModelFactory(SQLAlchemyFactory[Model]): __model__ = Model instance = ModelFactory.build() assert isinstance(instance.id, int) assert isinstance(instance.str_type, str) assert isinstance(instance.enum_type, Animal) assert isinstance(instance.str_array_type, list) assert isinstance(instance.str_array_type[0], str) def test_properties() -> None: _registry = registry() class Base(metaclass=DeclarativeMeta): __abstract__ = True registry = _registry metadata = _registry.metadata class Model(Base): __tablename__ = "model" id: Any = Column(Integer(), primary_key=True) age: Any = Column(Integer(), nullable=False) double_age = orm.column_property(age * 2) @hybrid_property def triple_age(self) -> int: return self.age * 3 # type: ignore[no-any-return] class ModelFactory(SQLAlchemyFactory[Model]): ... instance = ModelFactory.build() assert isinstance(instance, Model) # Expect empty as requires session to be set assert instance.double_age is None assert instance.age * 3 == instance.triple_age @pytest.mark.parametrize( "type_", tuple(SQLAlchemyFactory.get_sqlalchemy_types().keys()), ) def test_sqlalchemy_type_handlers(type_: types.TypeEngine) -> None: _registry = registry() class Base(metaclass=DeclarativeMeta): __abstract__ = True registry = _registry metadata = _registry.metadata class Model(Base): __tablename__ = "model_with_overriden_type" id: Any = Column(Integer(), primary_key=True) overridden: Any = Column(type_, nullable=False) class ModelFactory(SQLAlchemyFactory[Model]): __model__ = Model instance = ModelFactory.build() assert instance.overridden is not None def test_optional_field() -> None: class Model(Base): __tablename__ = "model_with_optional_field" id: Any = Column(Integer(), primary_key=True) optional_field: Any = Column(String(), nullable=True) class ModelFactory(SQLAlchemyFactory[Model]): __model__ = Model __random_seed__ = 0 result = ModelFactory.build() assert result.optional_field is None @pytest.mark.parametrize("set_primary_key", (True, False)) def test_set_primary_key(set_primary_key: bool) -> None: class AuthorFactory(SQLAlchemyFactory[Author]): __model__ = Author __set_primary_key__ = set_primary_key result = AuthorFactory.build() assert bool(result.id) is set_primary_key @pytest.mark.parametrize("set_foreign_keys", (True, False)) def test_set_foreign_keys(set_foreign_keys: bool) -> None: class BookFactory(SQLAlchemyFactory[Book]): __model__ = Book __set_foreign_keys__ = set_foreign_keys result = BookFactory.build() assert bool(result.author_id) is set_foreign_keys def test_relationship_resolution() -> None: class BookFactory(SQLAlchemyFactory[Book]): __model__ = Book __set_relationships__ = True result = BookFactory.build() assert isinstance(result.author, Author) def test_relationship_list_resolution() -> None: class AuthorFactory(SQLAlchemyFactory[Author]): __model__ = Author __set_relationships__ = True result = AuthorFactory.build() assert isinstance(result.books, list) assert isinstance(result.books[0], Book) def test_sqla_factory_create(engine: Engine) -> None: Base.metadata.create_all(engine) class OverridenSQLAlchemyFactory(SQLAlchemyFactory): __is_base_factory__ = True __session__ = Session(engine) __set_relationships__ = True author: Author = OverridenSQLAlchemyFactory.create_factory(Author).create_sync() assert isinstance(author.books[0], Book) assert author.books[0].author is author book = OverridenSQLAlchemyFactory.create_factory(Book).create_sync() assert book.author is not None assert book.author.books == [book] BaseFactory._base_factories.remove(OverridenSQLAlchemyFactory) async def test_invalid_peristence_config_raises() -> None: class AuthorFactory(SQLAlchemyFactory[Author]): __model__ = Author with pytest.raises( ConfigurationException, match="A '__sync_persistence__' handler must be defined in the factory to use this method", ): AuthorFactory.create_sync() with pytest.raises( ConfigurationException, match="An '__async_persistence__' handler must be defined in the factory to use this method", ): await AuthorFactory.create_async() @pytest.mark.parametrize( "session_config", ( lambda session: session, lambda session: (lambda: session), ), ) def test_sync_persistence(engine: Engine, session_config: Callable[[Session], Any]) -> None: Base.metadata.create_all(bind=engine) with Session(bind=engine) as session: class AuthorFactory(SQLAlchemyFactory[Author]): __session__ = session_config(session) __model__ = Author author = AuthorFactory.create_sync() assert author.id is not None assert inspect(author).persistent # type: ignore[union-attr] batch_result = AuthorFactory.create_batch_sync(size=2) assert len(batch_result) == 2 for batch_item in batch_result: assert inspect(batch_item).persistent # type: ignore[union-attr] @pytest.mark.parametrize( "session_config", ( lambda session: session, lambda session: (lambda: session), ), ) async def test_async_persistence( async_engine: AsyncEngine, session_config: Callable[[AsyncSession], Any], ) -> None: _registry = registry() class Base(metaclass=DeclarativeMeta): __abstract__ = True registry = _registry metadata = _registry.metadata class AsyncModel(Base): __tablename__ = "table" id: Any = Column(Integer(), primary_key=True) await create_tables(async_engine, Base) async with AsyncSession(async_engine) as session: class Factory(SQLAlchemyFactory[AsyncModel]): __async_session__ = session_config(session) __model__ = AsyncModel result = await Factory.create_async() assert inspect(result).persistent # type: ignore[union-attr] batch_result = await Factory.create_batch_async(size=2) assert len(batch_result) == 2 for batch_item in batch_result: assert inspect(batch_item).persistent # type: ignore[union-attr] @pytest.mark.parametrize( "session_config", ( lambda session: session, lambda session: (lambda: session), ), ) async def test_async_server_default_refresh( async_engine: AsyncEngine, session_config: Callable[[AsyncSession], Any], ) -> None: _registry = registry() class Base(metaclass=DeclarativeMeta): __abstract__ = True registry = _registry metadata = _registry.metadata class AsyncRefreshModel(Base): __tablename__ = "server_default_test" id: Any = Column(Integer(), primary_key=True) test_datetime: Any = Column(DateTime(timezone=True), server_default=func.now(), nullable=False) test_str: Any = Column(String, nullable=False, server_default=text("test_str")) test_int: Any = Column(Integer, nullable=False, server_default=text("123")) test_bool: Any = Column(Boolean, nullable=False, server_default=text("False")) await create_tables(async_engine, Base) async with AsyncSession(async_engine) as session: class Factory(SQLAlchemyFactory[AsyncRefreshModel]): __async_session__ = session_config(session) __model__ = AsyncRefreshModel test_datetime = Ignore() test_str = Ignore() test_int = Ignore() test_bool = Ignore() result = await Factory.create_async() assert inspect(result).persistent # type: ignore[union-attr] assert result.test_datetime is not None assert isinstance(result.test_datetime, datetime) assert result.test_str == "test_str" assert result.test_int == 123 assert result.test_bool is False def test_alias() -> None: class ModelWithAlias(Base): __tablename__ = "table" id: Any = Column(Integer(), primary_key=True) name: Any = Column("alias", String(), nullable=False) class ModelFactory(SQLAlchemyFactory[ModelWithAlias]): __model__ = ModelWithAlias result = ModelFactory.build() assert isinstance(result.name, str) @pytest.mark.parametrize("python_type_", (UUID, None)) def test_sqlalchemy_custom_type_from_type_decorator(python_type_: type) -> None: class CustomType(types.TypeDecorator): impl = types.CHAR(32) cache_ok = True if python_type_ is not None: @property def python_type(self) -> type: return python_type_ class Base(metaclass=DeclarativeMeta): __abstract__ = True __allow_unmapped__ = True registry = _registry metadata = _registry.metadata class Model(Base): __tablename__ = f"model_with_custom_types_{python_type_}" id: Any = Column(Integer(), primary_key=True) custom_type: Any = Column(type_=CustomType(), nullable=False) class ModelFactory(SQLAlchemyFactory[Model]): __model__ = Model instance = ModelFactory.build() expected_type = python_type_ if python_type_ is not None else CustomType.impl.python_type assert isinstance(instance.custom_type, expected_type) def test_constrained_types() -> None: _registry = registry() class Base(metaclass=DeclarativeMeta): __abstract__ = True __allow_unmapped__ = True registry = _registry metadata = _registry.metadata class Model(Base): __tablename__ = "constrained_model" id: Any = Column(Integer(), primary_key=True) constrained_string: Any = Column(String(length=1), nullable=False) constrained_nullable_string: Any = Column(String(length=1), nullable=True) constrainted_number: Any = Column( Numeric(precision=2, scale=1), nullable=False, ) constrainted_nullable_number: Any = Column( Numeric(precision=2, scale=1), nullable=True, ) class ModelFactory(SQLAlchemyFactory[Model]): __model__ = Model instance = ModelFactory.build() assert len(instance.constrained_string) <= 1 assert instance.constrained_nullable_string is None or len(instance.constrained_nullable_string) <= 1 constrained_number: Decimal = instance.constrainted_number assert isinstance(constrained_number, Decimal) assert abs(len(constrained_number.as_tuple().digits) - abs(int(constrained_number.as_tuple().exponent))) <= 2 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/tests/sqlalchemy_factory/test_sqlalchemy_factory_v2.py��������������������0000664�0000000�0000000�00000014561�14721310225�0030445�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from enum import Enum from ipaddress import ip_network from typing import Any, Dict, List from uuid import UUID import pytest from sqlalchemy import ForeignKey, Text, __version__, orm, types from sqlalchemy.dialects.mssql import JSON as MSSQL_JSON from sqlalchemy.dialects.mysql import JSON as MYSQL_JSON from sqlalchemy.dialects.postgresql import ARRAY, CIDR, HSTORE, INET, JSON, JSONB from sqlalchemy.dialects.sqlite import JSON as SQLITE_JSON from sqlalchemy.ext.mutable import MutableDict, MutableList from polyfactory.factories.sqlalchemy_factory import SQLAlchemyFactory if __version__.startswith("1"): pytest.importorskip("SQLAlchemy", "2") class Base(orm.DeclarativeBase): ... class Author(Base): __tablename__ = "authors" id: orm.Mapped[int] = orm.mapped_column(primary_key=True) books: orm.Mapped[List["Book"]] = orm.relationship( "Book", uselist=True, back_populates="author", ) class Book(Base): __tablename__ = "books" id: orm.Mapped[int] = orm.mapped_column(primary_key=True) author_id: orm.Mapped[int] = orm.mapped_column(ForeignKey(Author.id)) author: orm.Mapped[Author] = orm.relationship( Author, uselist=False, back_populates="books", ) def test_python_type_handling_v2() -> None: class Base(orm.DeclarativeBase): ... class Animal(str, Enum): DOG = "Dog" CAT = "Cat" class Model(Base): __tablename__ = "model" id: orm.Mapped[int] = orm.mapped_column(primary_key=True) str_type: orm.Mapped[str] enum_type: orm.Mapped[Animal] str_array_type: orm.Mapped[List[str]] = orm.mapped_column( type_=types.ARRAY(types.String), ) class ModelFactory(SQLAlchemyFactory[Model]): __model__ = Model instance = ModelFactory.build() assert isinstance(instance.id, int) assert isinstance(instance.str_type, str) assert isinstance(instance.enum_type, Animal) assert isinstance(instance.str_array_type, list) assert isinstance(instance.str_array_type[0], str) def test_sqla_dialect_types() -> None: class Base(orm.DeclarativeBase): ... class SqlaModel(Base): __tablename__ = "sql_models" id: orm.Mapped[int] = orm.mapped_column(primary_key=True) uuid_type: orm.Mapped[UUID] = orm.mapped_column(type_=types.UUID) nested_array_inet: orm.Mapped[List[str]] = orm.mapped_column(type_=ARRAY(INET, dimensions=1)) nested_array_cidr: orm.Mapped[List[str]] = orm.mapped_column(type_=ARRAY(CIDR, dimensions=1)) hstore_type: orm.Mapped[Dict] = orm.mapped_column(type_=HSTORE) mut_nested_arry_inet: orm.Mapped[List[str]] = orm.mapped_column( type_=MutableList.as_mutable(ARRAY(INET, dimensions=1)) ) pg_json_type: orm.Mapped[Dict] = orm.mapped_column(type_=JSON) pg_jsonb_type: orm.Mapped[Dict] = orm.mapped_column(type_=JSONB) common_json_type: orm.Mapped[Dict] = orm.mapped_column(type_=types.JSON) mysql_json: orm.Mapped[Dict] = orm.mapped_column(type_=MYSQL_JSON) sqlite_json: orm.Mapped[Dict] = orm.mapped_column(type_=SQLITE_JSON) mssql_json: orm.Mapped[Dict] = orm.mapped_column(type_=MSSQL_JSON) multible_pg_json_type: orm.Mapped[Dict] = orm.mapped_column( type_=MutableDict.as_mutable(JSON(astext_type=Text())) # type: ignore[no-untyped-call] ) multible_pg_jsonb_type: orm.Mapped[Dict] = orm.mapped_column( type_=MutableDict.as_mutable(JSONB(astext_type=Text())) # type: ignore[no-untyped-call] ) multible_common_json_type: orm.Mapped[Dict] = orm.mapped_column(type_=MutableDict.as_mutable(types.JSON())) multible_mysql_json: orm.Mapped[Dict] = orm.mapped_column(type_=MutableDict.as_mutable(MYSQL_JSON())) multible_sqlite_json: orm.Mapped[Dict] = orm.mapped_column(type_=MutableDict.as_mutable(SQLITE_JSON())) multible_mssql_json: orm.Mapped[Dict] = orm.mapped_column(type_=MutableDict.as_mutable(MSSQL_JSON())) class ModelFactory(SQLAlchemyFactory[SqlaModel]): __model__ = SqlaModel instance = ModelFactory.build() assert isinstance(instance.nested_array_inet[0], str) assert ip_network(instance.nested_array_inet[0]) assert isinstance(instance.nested_array_cidr[0], str) assert ip_network(instance.nested_array_cidr[0]) assert isinstance(instance.hstore_type, dict) assert isinstance(instance.uuid_type, UUID) assert isinstance(instance.mut_nested_arry_inet[0], str) assert ip_network(instance.mut_nested_arry_inet[0]) assert isinstance(instance.pg_json_type, dict) for value in instance.pg_json_type.values(): assert isinstance(value, (str, int, bool, float)) assert isinstance(instance.pg_jsonb_type, dict) for value in instance.pg_jsonb_type.values(): assert isinstance(value, (str, int, bool, float)) assert isinstance(instance.common_json_type, dict) for value in instance.common_json_type.values(): assert isinstance(value, (str, int, bool, float)) assert isinstance(instance.mysql_json, dict) for value in instance.mysql_json.values(): assert isinstance(value, (str, int, bool, float)) assert isinstance(instance.sqlite_json, dict) for value in instance.sqlite_json.values(): assert isinstance(value, (str, int, bool, float)) assert isinstance(instance.mssql_json, dict) for value in instance.mssql_json.values(): assert isinstance(value, (str, int, bool, float)) assert isinstance(instance.multible_pg_json_type, dict) assert isinstance(instance.multible_pg_jsonb_type, dict) assert isinstance(instance.multible_common_json_type, dict) assert isinstance(instance.multible_mysql_json, dict) assert isinstance(instance.multible_sqlite_json, dict) assert isinstance(instance.multible_mssql_json, dict) @pytest.mark.parametrize( "type_", tuple(SQLAlchemyFactory.get_sqlalchemy_types().keys()), ) def test_sqlalchemy_type_handlers_v2(type_: types.TypeEngine) -> None: class Base(orm.DeclarativeBase): ... class Model(Base): __tablename__ = "model_with_overriden_type" id: orm.Mapped[int] = orm.mapped_column(primary_key=True) overridden: orm.Mapped[Any] = orm.mapped_column(type_=type_) class ModelFactory(SQLAlchemyFactory[Model]): __model__ = Model instance = ModelFactory.build() assert instance.overridden is not None �����������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/tests/test_attrs_factory.py�����������������������������������������������0000664�0000000�0000000�00000013717�14721310225�0023142�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������import datetime as dt from decimal import Decimal from enum import Enum from typing import Any, Dict, Generic, List, Optional, Tuple, TypeVar, Union from uuid import UUID import attrs import pytest from attrs import asdict, define from polyfactory.factories.attrs_factory import AttrsFactory pytestmark = [pytest.mark.attrs] def test_is_supported_type() -> None: @define class Foo: ... assert AttrsFactory.is_supported_type(Foo) is True def test_is_supported_type_without_struct() -> None: class Foo: ... assert AttrsFactory.is_supported_type(Foo) is False def test_with_basic_types_annotated() -> None: class SampleEnum(Enum): FOO = "foo" BAR = "bar" @define class Foo: bool_field: bool int_field: int float_field: float str_field: str bytse_field: bytes bytearray_field: bytearray tuple_field: Tuple[int, str] tuple_with_variadic_args: Tuple[int, ...] list_field: List[int] dict_field: Dict[str, int] datetime_field: dt.datetime date_field: dt.date time_field: dt.time uuid_field: UUID decimal_field: Decimal enum_type: SampleEnum any_type: Any class FooFactory(AttrsFactory[Foo]): __model__ = Foo foo = FooFactory.build() foo_dict = asdict(foo) assert foo == Foo(**foo_dict) def test_with_basic_types_attrs_field() -> None: @define class Foo: bool_field = attrs.field(type=bool) # pyright: ignore int_field = attrs.field(type=int) # pyright: ignore float_field = attrs.field(type=float) # pyright: ignore str_field = attrs.field(type=str) # pyright: ignore bytes_field = attrs.field(type=bytes) # pyright: ignore bytearray_field = attrs.field(type=bytearray) # pyright: ignore tuple_field = attrs.field(type=Tuple[int, str]) # type: ignore tuple_with_variadic_args = attrs.field(type=Tuple[int, ...]) # type: ignore list_field = attrs.field(type=List[int]) # pyright: ignore dict_field = attrs.field(type=Dict[int, str]) # pyright: ignore datetime_field = attrs.field(type=dt.datetime) # pyright: ignore date_field = attrs.field(type=dt.date) # pyright: ignore time_field = attrs.field(type=dt.time) # pyright: ignore uuid_field = attrs.field(type=UUID) # pyright: ignore decimal_field = attrs.field(type=Decimal) # pyright: ignore class FooFactory(AttrsFactory[Foo]): __model__ = Foo foo = FooFactory.build() foo_dict = asdict(foo) assert foo == Foo(**foo_dict) def test_with_nested_attr_model() -> None: @define class Foo: int_field: int @define class Bar: int_field: int foo_field: Foo class BarFactory(AttrsFactory[Bar]): __model__ = Bar bar = BarFactory.build() bar_dict = asdict(bar, recurse=False) assert bar == Bar(**bar_dict) def test_with_private_fields() -> None: @define class Foo: _private: int class FooFactory(AttrsFactory[Foo]): __model__ = Foo foo = FooFactory.build() assert foo == Foo(foo._private) def test_with_aliased_fields() -> None: @define class Foo: aliased: int = attrs.field(alias="foo") class FooFactory(AttrsFactory[Foo]): __model__ = Foo foo = FooFactory.build() assert foo == Foo(foo.aliased) def test_with_generics() -> None: T = TypeVar("T") @define class Foo(Generic[T]): x: T class FooFactory(AttrsFactory[Foo[str]]): __model__ = Foo foo = FooFactory.build() foo_dict = asdict(foo) assert foo == Foo(**foo_dict) def test_with_inheritance() -> None: @define class Parent: int_field: int @define class Child: str_field: str class ChildFactory(AttrsFactory[Child]): __model__ = Child child = ChildFactory.build() child_dict = asdict(child) assert child == Child(**child_dict) def test_with_stringified_annotations() -> None: @define class Foo: int_field: "int" class FooFactory(AttrsFactory[Foo]): __model__ = Foo foo = FooFactory.build() assert isinstance(foo.int_field, int) def test_with_init_false() -> None: @define class Foo: foo: int = attrs.field(init=False) class FooFactory(AttrsFactory[Foo]): __model__ = Foo assert FooFactory.build() def test_use_default_with_callable_default() -> None: @define class Foo: default_field: int = attrs.field(default=attrs.Factory(lambda: 10, takes_self=False)) class FooFactory(AttrsFactory[Foo]): __model__ = Foo __use_defaults__ = True foo = FooFactory.build() assert foo.default_field == 10 def test_use_default_with_non_callable_default() -> None: @define class Foo: default_field: int = attrs.field(default=10) class FooFactory(AttrsFactory[Foo]): __model__ = Foo __use_defaults__ = True foo = FooFactory.build() assert foo.default_field == 10 def test_union_types() -> None: @define class A: a: Union[List[str], List[int]] b: Union[str, List[int]] c: List[Union[Tuple[int, int], Tuple[str, int]]] AFactory = AttrsFactory.create_factory(A) assert AFactory.build() def test_collection_unions_with_models() -> None: @define class A: a: int @define class B: a: str @define class C: a: Union[List[A], List[B]] b: List[Union[A, B]] CFactory = AttrsFactory.create_factory(C) assert CFactory.build() @pytest.mark.parametrize("allow_none", (True, False)) def test_optional_type(allow_none: bool) -> None: @define class A: a: Union[str, None] b: Optional[str] c: Optional[Union[str, int, List[int]]] class AFactory(AttrsFactory[A]): __model__ = A __allow_none_optionals__ = allow_none assert AFactory.build() �������������������������������������������������python-polyfactory-2.18.1/tests/test_auto_registration.py�������������������������������������������0000664�0000000�0000000�00000005020�14721310225�0024004�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from dataclasses import dataclass as vanilla_dataclass from typing import List from typing_extensions import TypedDict from pydantic import BaseModel from polyfactory.factories import DataclassFactory, TypedDictFactory from polyfactory.factories.pydantic_factory import ModelFactory class A(BaseModel): a_text: str class B(BaseModel): b_text: str a: A class C(BaseModel): b: B b_list: List[B] def test_auto_register_model_factory() -> None: class AFactory(ModelFactory): a_text = "const value" __model__ = A class BFactory(ModelFactory): b_text = "const value" __model__ = B __set_as_default_factory_for_type__ = True class CFactory(ModelFactory): __model__ = C c = CFactory.build() assert c.b.b_text == BFactory.b_text assert c.b_list[0].b_text == BFactory.b_text assert c.b.a.a_text != AFactory.a_text def test_auto_register_model_factory_using_create_factory() -> None: const_value = "const value" ModelFactory.create_factory(model=A, a_text=const_value) ModelFactory.create_factory(model=B, b_text=const_value, __set_as_default_factory_for_type__=True) factory = ModelFactory.create_factory(model=C) c = factory.build() assert c.b.b_text == const_value assert c.b_list[0].b_text == const_value assert c.b.a.a_text != const_value def test_dataclass_model_factory_auto_registration() -> None: @vanilla_dataclass class DataClass: text: str class UpperModel(BaseModel): nested_field: DataClass nested_list_field: List[DataClass] class UpperModelFactory(ModelFactory): __model__ = UpperModel class DTFactory(DataclassFactory): text = "const value" __model__ = DataClass __set_as_default_factory_for_type__ = True upper = UpperModelFactory.build() assert upper.nested_field.text == DTFactory.text assert upper.nested_list_field[0].text == DTFactory.text def test_typeddict_model_factory_auto_registration() -> None: class TD(TypedDict): text: str class UpperSchema(BaseModel): nested_field: TD nested_list_field: List[TD] class UpperModelFactory(ModelFactory): __model__ = UpperSchema class TDFactory(TypedDictFactory): text = "const value" __model__ = TD __set_as_default_factory_for_type__ = True upper = UpperModelFactory.build() assert upper.nested_field["text"] == TDFactory.text assert upper.nested_list_field[0]["text"] == TDFactory.text ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/tests/test_base_factories.py����������������������������������������������0000664�0000000�0000000�00000005402�14721310225�0023217�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from dataclasses import dataclass from typing import Any, Dict import pytest from pydantic.main import BaseModel from polyfactory.factories import DataclassFactory from polyfactory.factories.base import BaseFactory from polyfactory.factories.pydantic_factory import ModelFactory def test_multiple_base_factories() -> None: class Foo: def __init__(self, value: str) -> None: self.value = value @dataclass class MyModelWithFoo: foo: Foo class FooDataclassFactory(DataclassFactory): __is_base_factory__ = True @classmethod def get_provider_map(cls) -> Dict[Any, Any]: return {Foo: lambda: Foo("foo"), **super().get_provider_map()} # noinspection PyUnusedLocal class DummyDataclassFactory(DataclassFactory): __is_base_factory__ = True @dataclass class MyModel: nested: MyModelWithFoo class MyFactory(FooDataclassFactory): __model__ = MyModel __base_factory_overrides__ = {MyModelWithFoo: FooDataclassFactory} MyFactory.build() @pytest.mark.parametrize("override_BaseModel", [False, True]) def test_multiple_base_pydantic_factories(override_BaseModel: bool) -> None: class Foo: def __init__(self, value: str) -> None: self.value = value class MyModelWithFoo(BaseModel): foo: Foo class Config: arbitrary_types_allowed = True class FooModelFactory(ModelFactory): __is_base_factory__ = True @classmethod def get_provider_map(cls) -> Dict[Any, Any]: return {Foo: lambda: Foo("foo"), **super().get_provider_map()} # noinspection PyUnusedLocal class DummyModelFactory(ModelFactory): __is_base_factory__ = True class MyModel(BaseModel): nested: MyModelWithFoo class MyFactory(FooModelFactory): __model__ = MyModel if override_BaseModel: __base_factory_overrides__ = {BaseModel: FooModelFactory} else: __base_factory_overrides__ = {MyModelWithFoo: FooModelFactory} MyFactory.build() # XXX: remove the factory classes from _base_factories to prevent side-effects in other tests # see https://github.com/litestar-org/polyfactory/issues/198 ModelFactory._base_factories.remove(FooModelFactory) ModelFactory._base_factories.remove(DummyModelFactory) def test_create_factory_without_model_reuse_current_factory_model() -> None: @dataclass class Foo: pass factory = DataclassFactory.create_factory(model=Foo) sub_factory = factory.create_factory() assert sub_factory.__model__ == Foo def test_create_factory_from_base_factory_without_providing_a_model_raises_error() -> None: with pytest.raises(TypeError): BaseFactory.create_factory() ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/tests/test_beanie_factory.py����������������������������������������������0000664�0000000�0000000�00000004467�14721310225�0023232�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from sys import version_info from typing import Callable, List import pymongo import pytest try: from beanie import Document, Link, init_beanie from beanie.odm.fields import Indexed, PydanticObjectId from mongomock_motor import AsyncMongoMockClient from polyfactory.factories.beanie_odm_factory import BeanieDocumentFactory except ImportError: pytest.importorskip("beanie") BeanieDocumentFactory = None # type: ignore Document = None # type: ignore Link = None # type: ignore init_beanie = None # type: ignore Indexed = None # type: ignore PydanticObjectId = None # type: ignore @pytest.fixture() def mongo_connection() -> AsyncMongoMockClient: return AsyncMongoMockClient() class MyDocument(Document): id: PydanticObjectId name: str index: Indexed(str, pymongo.DESCENDING) # type: ignore siblings: List[PydanticObjectId] class MyOtherDocument(Document): id: PydanticObjectId document: Link[MyDocument] class MyFactory(BeanieDocumentFactory): __model__ = MyDocument class MyOtherFactory(BeanieDocumentFactory): __model__ = MyOtherDocument @pytest.fixture() async def beanie_init(mongo_connection: AsyncMongoMockClient) -> None: await init_beanie(database=mongo_connection.db_name, document_models=[MyDocument, MyOtherDocument]) async def test_handling_of_beanie_types(beanie_init: Callable) -> None: result = MyFactory.build() assert result.name assert result.index assert isinstance(result.index, str) async def test_beanie_persistence_of_single_instance(beanie_init: Callable) -> None: result = await MyFactory.create_async() assert result.id assert result.name assert result.index assert isinstance(result.index, str) async def test_beanie_persistence_of_multiple_instances(beanie_init: Callable) -> None: result = await MyFactory.create_batch_async(size=3) assert len(result) == 3 for instance in result: assert instance.id assert instance.name assert instance.index assert isinstance(instance.index, str) @pytest.mark.skipif(version_info < (3, 11), reason="test isolation issues on lower versions") async def test_beanie_links(beanie_init: Callable) -> None: result = await MyOtherFactory.create_async() assert isinstance(result.document, MyDocument) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/tests/test_build.py�������������������������������������������������������0000664�0000000�0000000�00000004357�14721310225�0021355�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from uuid import uuid4 from pydantic import BaseModel from polyfactory.factories.pydantic_factory import ModelFactory from tests.models import PersonFactoryWithDefaults, Pet, PetFactory def test_merges_defaults_with_kwargs() -> None: first_obj = PersonFactoryWithDefaults.build() assert first_obj.id == PersonFactoryWithDefaults.id assert first_obj.name == PersonFactoryWithDefaults.name assert first_obj.hobbies == PersonFactoryWithDefaults.hobbies assert first_obj.age == PersonFactoryWithDefaults.age assert first_obj.pets == PersonFactoryWithDefaults.pets assert first_obj.birthday == PersonFactoryWithDefaults.birthday pet = Pet( name="bluey the blowfish", species="blowfish", color="bluish-green", sound="", age=1, ) id_ = uuid4() hobbies = ["dancing"] age = 35 pets = [pet] second_obj = PersonFactoryWithDefaults.build(id=id_, hobbies=hobbies, age=age, pets=pets) assert second_obj.id == id_ assert second_obj.hobbies == hobbies assert second_obj.age == age assert second_obj.pets == [pet] assert second_obj.name == PersonFactoryWithDefaults.name assert second_obj.birthday == PersonFactoryWithDefaults.birthday def test_respects_none_overrides() -> None: result = PersonFactoryWithDefaults.build(hobbies=None) assert result.hobbies is None def test_uses_faker_to_set_values_when_none_available_on_class() -> None: result = PetFactory.build() assert isinstance(result.name, str) assert isinstance(result.species, str) assert isinstance(result.color, str) assert isinstance(result.sound, str) assert isinstance(result.age, float) def test_builds_batch() -> None: results = PetFactory.batch(10) assert isinstance(results, list) assert len(results) == 10 for result in results: assert isinstance(result.name, str) assert isinstance(result.species, str) assert isinstance(result.color, str) assert isinstance(result.sound, str) assert isinstance(result.age, float) def test_build_model_with_fields_named_like_factory_fields() -> None: class C(BaseModel): batch: int class CFactory(ModelFactory): __model__ = C assert CFactory.build() ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/tests/test_collection_extender.py�����������������������������������������0000664�0000000�0000000�00000004443�14721310225�0024303�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from typing import TYPE_CHECKING, Dict, FrozenSet, List, Set, Tuple import pytest from polyfactory.collection_extender import CollectionExtender if TYPE_CHECKING: from typing import Any pytestmark = pytest.mark.parametrize("number_of_args", [0, 1, 3]) def test_tuple_extender(number_of_args: int) -> None: annotation_alias: Any = Tuple[int, ...] type_args = (int, ...) extended_type_args = CollectionExtender.extend_type_args(annotation_alias, type_args, number_of_args) assert extended_type_args == (int,) * number_of_args def test_tuple_extender__constant_length(number_of_args: int) -> None: annotation_alias: Any = Tuple[int, int, int] type_args = (int, int, int, int) extended_type_args = CollectionExtender.extend_type_args(annotation_alias, type_args, number_of_args) assert extended_type_args == (int, int, int, int) def test_tuple_extender__not_typed(number_of_args: int) -> None: annotation_alias: Any = Tuple type_args = () extended_type_args = CollectionExtender.extend_type_args(annotation_alias, type_args, number_of_args) assert extended_type_args == () def test_list_extender(number_of_args: int) -> None: annotation_alias: Any = List[int] type_args = (int,) extended_type_args = CollectionExtender.extend_type_args(annotation_alias, type_args, number_of_args) assert extended_type_args == (int,) * number_of_args def test_set_extender(number_of_args: int) -> None: class Dummy: ... annotation_alias: Any = Set[Dummy] type_args = (Dummy,) extended_type_args = CollectionExtender.extend_type_args(annotation_alias, type_args, number_of_args) assert extended_type_args == (Dummy,) * number_of_args def test_frozen_set_extender(number_of_args: int) -> None: class Dummy: ... annotation_alias: Any = FrozenSet[Dummy] type_args = (Dummy,) extended_type_args = CollectionExtender.extend_type_args(annotation_alias, type_args, number_of_args) assert extended_type_args == (Dummy,) * number_of_args def test_dict_extender(number_of_args: int) -> None: annotation_alias: Any = Dict[str, int] type_args = (str, int) extended_type_args = CollectionExtender.extend_type_args(annotation_alias, type_args, number_of_args) assert extended_type_args == (str, int) * number_of_args �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/tests/test_collection_length.py�������������������������������������������0000664�0000000�0000000�00000013130�14721310225�0023737�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from enum import Enum from typing import Any, Dict, FrozenSet, List, Literal, Optional, Set, Tuple, get_args import pytest from pydantic import BaseModel from pydantic.dataclasses import dataclass from polyfactory.factories import DataclassFactory from polyfactory.factories.pydantic_factory import ModelFactory MIN_MAX_PARAMETERS = ((10, 15), (20, 25), (30, 40), (40, 50)) @pytest.mark.parametrize("type_", (List, Set)) @pytest.mark.parametrize(("min_val", "max_val"), MIN_MAX_PARAMETERS) def test_collection_length_with_list(min_val: int, max_val: int, type_: type) -> None: @dataclass class Foo: foo: type_[int] # type: ignore class FooFactory(DataclassFactory[Foo]): __model__ = Foo __randomize_collection_length__ = True __min_collection_length__ = min_val __max_collection_length__ = max_val foo = FooFactory.build() assert len(foo.foo) >= min_val, len(foo.foo) assert len(foo.foo) <= max_val, len(foo.foo) def test_collection_length_with_set_collision() -> None: @dataclass class Foo: foo: Set[int] provider_int_values_reversed = (list(range(9)) + list(range(7, 15)))[::-1] class FooFactory(DataclassFactory[Foo]): __model__ = Foo __randomize_collection_length__ = True __min_collection_length__ = 10 __max_collection_length__ = 10 @classmethod def get_provider_map(cls) -> Dict[Any, Any]: providers_map = super().get_provider_map() providers_map[int] = lambda: provider_int_values_reversed.pop() return providers_map foo = FooFactory.build() assert len(foo.foo) >= 10, len(foo.foo) assert len(foo.foo) <= 15, len(foo.foo) @pytest.mark.parametrize(("min_val", "max_val"), MIN_MAX_PARAMETERS) def test_collection_length_with_tuple(min_val: int, max_val: int) -> None: @dataclass class Foo: foo: Tuple[int, ...] class FooFactory(DataclassFactory[Foo]): __model__ = Foo __randomize_collection_length__ = True __min_collection_length__ = min_val __max_collection_length__ = max_val foo = FooFactory.build() assert len(foo.foo) >= min_val, len(foo.foo) assert len(foo.foo) <= max_val, len(foo.foo) @pytest.mark.parametrize(("min_val", "max_val"), MIN_MAX_PARAMETERS) def test_collection_length_with_dict(min_val: int, max_val: int) -> None: @dataclass class Foo: foo: Dict[int, int] class FooFactory(DataclassFactory[Foo]): __model__ = Foo __randomize_collection_length__ = True __min_collection_length__ = min_val __max_collection_length__ = max_val foo = FooFactory.build() assert len(foo.foo) >= min_val, len(foo.foo) assert len(foo.foo) <= max_val, len(foo.foo) @pytest.mark.parametrize(("min_val", "max_val"), MIN_MAX_PARAMETERS) def test_collection_length_with_optional_not_allowed(min_val: int, max_val: int) -> None: @dataclass class Foo: foo: Optional[List[int]] class FooFactory(DataclassFactory[Foo]): __model__ = Foo __allow_none_optionals__ = False __randomize_collection_length__ = True __min_collection_length__ = min_val __max_collection_length__ = max_val foo = FooFactory.build() assert foo.foo is not None assert len(foo.foo) >= min_val, len(foo.foo) assert len(foo.foo) <= max_val, len(foo.foo) @pytest.mark.parametrize(("min_val", "max_val"), MIN_MAX_PARAMETERS) def test_collection_length_with_optional_allowed(min_val: int, max_val: int) -> None: @dataclass class Foo: foo: Optional[List[int]] class FooFactory(DataclassFactory[Foo]): __model__ = Foo __randomize_collection_length__ = True __min_collection_length__ = min_val __max_collection_length__ = max_val for _ in range(10): foo = FooFactory.build() if foo.foo is None: continue assert len(foo.foo) >= min_val, len(foo.foo) assert len(foo.foo) <= max_val, len(foo.foo) @pytest.mark.parametrize("type_", (List, FrozenSet, Set)) @pytest.mark.parametrize("min_items", (0, 2, 4)) @pytest.mark.parametrize("max_inc", (0, 1, 4)) def test_collection_length_with_literal(type_: type, min_items: int, max_inc: int) -> None: max_items = min_items + max_inc literal_type = Literal["Dog", "Cat", "Monkey"] @dataclass class MyModel: animal_collection: type_[literal_type] # type: ignore class MyFactory(DataclassFactory): __model__ = MyModel __randomize_collection_length__ = True __min_collection_length__ = min_items __max_collection_length__ = max_items result = MyFactory.build() assert len(result.animal_collection) >= min(min_items, len(get_args(literal_type))) assert len(result.animal_collection) <= max_items @pytest.mark.parametrize("type_", (List, FrozenSet, Set)) @pytest.mark.parametrize("min_items", (0, 2, 4)) @pytest.mark.parametrize("max_inc", (0, 1, 4)) def test_collection_length_with_enum(type_: type, min_items: int, max_inc: int) -> None: max_items = min_items + max_inc class Animal(str, Enum): DOG = "Dog" CAT = "Cat" MONKEY = "Monkey" class MyModel(BaseModel): animal_collection: type_[Animal] # type: ignore class MyFactory(ModelFactory): __model__ = MyModel __randomize_collection_length__ = True __min_collection_length__ = min_items __max_collection_length__ = max_items result = MyFactory.build() assert len(result.animal_collection) >= min(min_items, len(Animal)) assert len(result.animal_collection) <= max_items ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/tests/test_complex_types.py�����������������������������������������������0000664�0000000�0000000�00000012117�14721310225�0023142�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from dataclasses import dataclass from enum import Enum from typing import ( Any, Callable, DefaultDict, Deque, Dict, FrozenSet, Generic, Iterable, List, Literal, Optional, Sequence, Set, Tuple, TypeVar, Union, ) import pytest from pydantic import BaseModel from polyfactory.exceptions import ParameterException from polyfactory.factories import DataclassFactory from polyfactory.factories.pydantic_factory import ModelFactory from tests.models import Person def test_handles_complex_typing() -> None: class MyModel(BaseModel): nested_dict: Dict[str, Dict[Union[int, str], Dict[Any, List[Dict[str, str]]]]] dict_str_any: Dict[str, Any] nested_list: List[List[List[Dict[str, List[Any]]]]] sequence_literal: Sequence[Literal[1, 2, 3]] sequence_dict: Sequence[Dict[str, Any]] iterable_float: Iterable[float] tuple_ellipsis: Tuple[int, ...] tuple_str_str: Tuple[str, str] default_dict: DefaultDict[str, List[Dict[str, int]]] deque: Deque[List[Dict[str, int]]] set_union: Set[Union[str, int]] frozen_set: FrozenSet[str] plain_list: List[Any] plain_set: Set[Any] plain_dict: Dict[str, Any] class MyFactory(ModelFactory): __model__ = MyModel result = MyFactory.build() assert result.nested_dict assert result.dict_str_any assert result.nested_list assert result.sequence_dict assert result.iterable_float assert result.tuple_ellipsis assert result.tuple_str_str assert result.default_dict assert result.deque assert result.set_union assert result.frozen_set assert result.plain_list assert result.plain_set assert result.plain_dict def test_handles_complex_typing_with_embedded_models() -> None: class MyModel(BaseModel): person_dict: Dict[str, Person] person_list: List[Person] class MyFactory(ModelFactory): __model__ = MyModel result = MyFactory.build() assert result.person_dict assert result.person_list[0].pets def test_raises_for_user_defined_types() -> None: class MyClass: def __init__(self, value: int) -> None: self.value = value class MyModel(BaseModel): my_class_field: Dict[str, MyClass] class Config: arbitrary_types_allowed = True class MyFactory(ModelFactory): __model__ = MyModel with pytest.raises(ParameterException): MyFactory.build() def test_randomizes_optional_returns() -> None: """this is a flaky test - because it depends on randomness, hence it's been re-ran multiple times.""" class MyModel(BaseModel): optional_1: Optional[List[str]] optional_2: Optional[Dict[str, str]] optional_3: Optional[Set[str]] optional_4: Optional[Dict[int, str]] class MyFactory(ModelFactory): __model__ = MyModel __random_seed__ = 1 failed = False for _ in range(5): try: result = MyFactory.build() assert any( [ not result.optional_1, not result.optional_2, not result.optional_3, not result.optional_4, ], ) assert any( [ bool(result.optional_1), bool(result.optional_2), bool(result.optional_3), bool(result.optional_4), ], ) failed = False break except AssertionError: failed = True assert not failed def test_complex_typing_with_enum() -> None: class Animal(str, Enum): DOG = "Dog" CAT = "Cat" MONKEY = "Monkey" class MyModel(BaseModel): animal_list: List[Animal] class MyFactory(ModelFactory): __model__ = MyModel result = MyFactory.build() assert result.animal_list def test_union_literal() -> None: class MyModel(BaseModel): x: Union[int, Literal["a", "b", "c"]] class MyFactory(ModelFactory): __model__ = MyModel MyFactory.build() def test_non_collection_generic() -> None: T = TypeVar("T") class LoggedVar(Generic[T]): def __init__(self, name: str = "", log: Callable[[str], None] = print) -> None: self.__name = name self.__log = log def set(self, value: T) -> None: self.__log(f"Set {self.__name} to {value}") self.__value = value def get(self) -> T: self.__log(f"Get {self.__name} = {self.__value}") return self.__value @dataclass class MyModel: x: LoggedVar[int] class MyFactory(DataclassFactory): __model__ = MyModel result = MyFactory.build() assert isinstance(result.x, LoggedVar) def test_sequence_dict() -> None: @dataclass class MyModel: sequence_dict: Sequence[Dict] class MyFactory(DataclassFactory): __model__ = MyModel result = MyFactory.build() assert result.sequence_dict �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/tests/test_data_parsing.py������������������������������������������������0000664�0000000�0000000�00000010175�14721310225�0022705�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from datetime import date from enum import Enum from typing import Callable, Literal, Optional import pytest from typing_extensions import TypeAlias from pydantic import ( AmqpDsn, AnyHttpUrl, AnyUrl, BaseConfig, BaseModel, HttpUrl, KafkaDsn, PostgresDsn, RedisDsn, ) from polyfactory.exceptions import ParameterException from polyfactory.factories.pydantic_factory import ModelFactory from tests.models import Person, PersonFactoryWithDefaults, Pet def test_enum_parsing() -> None: class MyStrEnum(str, Enum): FIRST_NAME = "Moishe Zuchmir" SECOND_NAME = "Hannah Arendt" class MyIntEnum(Enum): ONE_HUNDRED = 100 TWO_HUNDRED = 200 class MyModel(BaseModel): name: MyStrEnum worth: MyIntEnum class MyFactory(ModelFactory): __model__ = MyModel result = MyFactory.build() assert isinstance(result.name, MyStrEnum) assert isinstance(result.worth, MyIntEnum) def test_callback_parsing() -> None: today = date.today() class MyModel(BaseModel): name: str birthday: date secret: Callable class MyFactory(ModelFactory): __model__ = MyModel name = lambda: "moishe zuchmir" # noqa: E731 birthday = lambda: today # noqa: E731 result = MyFactory.build() assert result.name == "moishe zuchmir" assert result.birthday == today assert callable(result.secret) def test_literal_parsing() -> None: class MyModel(BaseModel): literal_field: "Literal['yoyos']" multi_literal_field: "Literal['nolos', 'zozos', 'kokos']" class MyFactory(ModelFactory): __model__ = MyModel assert MyFactory.build().literal_field == "yoyos" batch = MyFactory.batch(30) values = {v.multi_literal_field for v in batch} assert values == {"nolos", "zozos", "kokos"} def test_embedded_models_parsing() -> None: class MyModel(BaseModel): pet: Pet class MyFactory(ModelFactory): __model__ = MyModel result = MyFactory.build() assert isinstance(result.pet, Pet) def test_embedded_factories_parsing() -> None: class MyModel(BaseModel): person: Person class MyFactory(ModelFactory): __model__ = MyModel person = PersonFactoryWithDefaults result = MyFactory.build() assert isinstance(result.person, Person) def test_class_parsing() -> None: class TestClassWithoutKwargs: def __init__(self) -> None: self.flag = "123" class MyModel(BaseModel): class Config(BaseConfig): arbitrary_types_allowed = True class_field: TestClassWithoutKwargs # just a few select exceptions, to verify this works exception_field: Exception type_error_field: TypeError attribute_error_field: AttributeError runtime_error_field: RuntimeError class MyFactory(ModelFactory): __model__ = MyModel result = MyFactory.build() assert isinstance(result.class_field, TestClassWithoutKwargs) assert result.class_field.flag == "123" assert isinstance(result.exception_field, Exception) assert isinstance(result.type_error_field, TypeError) assert isinstance(result.attribute_error_field, AttributeError) assert isinstance(result.runtime_error_field, RuntimeError) class TestClassWithKwargs: def __init__(self, _: str) -> None: self.flag = str class MyNewModel(BaseModel): class Config(BaseConfig): arbitrary_types_allowed = True class_field: TestClassWithKwargs class MySecondFactory(ModelFactory): __model__ = MyNewModel with pytest.raises(ParameterException): MySecondFactory.build() @pytest.mark.parametrize( "type_", [AnyUrl, HttpUrl, KafkaDsn, PostgresDsn, RedisDsn, AmqpDsn, AnyHttpUrl], ) def test_optional_url_field_parsed_correctly(type_: TypeAlias) -> None: class MyModel(BaseModel): url: Optional[type_] class MyFactory(ModelFactory[MyModel]): __model__ = MyModel while not (url := MyFactory.build().url): assert not url assert MyModel(url=url) # no validation error raised ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/tests/test_dataclass_factory.py�������������������������������������������0000664�0000000�0000000�00000017664�14721310225�0023751�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������import dataclasses from dataclasses import dataclass as vanilla_dataclass from dataclasses import field from types import ModuleType from typing import Any, Callable, Dict, List, Optional, Tuple, Union from unittest.mock import ANY import pytest from pydantic.dataclasses import dataclass as pydantic_dataclass from polyfactory.factories import DataclassFactory from tests.models import Person def test_factory_vanilla_dc() -> None: @vanilla_dataclass class VanillaDC: id: int name: str list_field: List[Dict[str, int]] field_of_some_value: Optional[int] = field(default_factory=lambda: 0) class MyFactory(DataclassFactory[VanillaDC]): __model__ = VanillaDC result = MyFactory.build() assert result assert result.id assert result.name assert result.list_field assert result.list_field[0] assert [isinstance(value, int) for value in result.list_field[0].values()] def test_factory_pydantic_dc() -> None: @pydantic_dataclass class PydanticDC: id: int name: str list_field: List[Dict[str, int]] field_of_some_value: Optional[int] = field(default_factory=lambda: 0) class MyFactory(DataclassFactory[PydanticDC]): __model__ = PydanticDC result = MyFactory.build() assert result assert result.id assert result.name assert result.list_field assert result.list_field[0] assert [isinstance(value, int) for value in result.list_field[0].values()] def test_vanilla_dc_with_embedded_model() -> None: @vanilla_dataclass class VanillaDC: people: List[Person] class MyFactory(DataclassFactory[VanillaDC]): __model__ = VanillaDC result = MyFactory.build() assert result.people assert [isinstance(person, Person) for person in result.people] def test_pydantic_dc_with_embedded_model() -> None: @vanilla_dataclass class PydanticDC: people: List[Person] class MyFactory(DataclassFactory): __model__ = PydanticDC result = MyFactory.build() assert result.people assert [isinstance(person, Person) for person in result.people] def test_model_with_embedded_dataclasses() -> None: @vanilla_dataclass class VanillaDC: people: List[Person] @vanilla_dataclass class PydanticDC: people: List[Person] @vanilla_dataclass class Crowd: west: VanillaDC east: PydanticDC class MyFactory(DataclassFactory): __model__ = Crowd result = MyFactory.build() assert result.west assert result.west.people assert result.east assert result.east.people def test_complex_embedded_dataclass() -> None: @vanilla_dataclass class VanillaDC: people: List[Person] @vanilla_dataclass class MyModel: weirdly_nest_field: List[Dict[str, Dict[str, VanillaDC]]] class MyFactory(DataclassFactory): __model__ = MyModel result = MyFactory.build() assert result.weirdly_nest_field assert result.weirdly_nest_field[0] assert next(iter(result.weirdly_nest_field[0].values())).values() assert next(iter(next(iter(result.weirdly_nest_field[0].values())).values())) assert isinstance(next(iter(next(iter(result.weirdly_nest_field[0].values())).values())), VanillaDC) @pytest.mark.parametrize( "factory_config, expected_length", ( ({}, 1), ( { "__randomize_collection_length__": True, "__min_collection_length__": 3, "__max_collection_length__": 3, }, 3, ), ( { "__randomize_collection_length__": True, "__min_collection_length__": 0, "__max_collection_length__": 0, }, 0, ), ), ) def test_tuple_in_vanilla_dc(factory_config: Dict[str, Any], expected_length: int) -> None: @vanilla_dataclass class VanillaDC: ids: Tuple[int, ...] field: Tuple[int, str] MyFactory = DataclassFactory[VanillaDC].create_factory(VanillaDC, **factory_config) result = MyFactory.build() assert result assert len(result.ids) == expected_length assert len(result.field) == 2 assert isinstance(result.field[0], int) assert isinstance(result.field[1], str) coverage_results = list(MyFactory.coverage()) assert all(len(result.ids) == 1 for result in coverage_results) assert all(len(result.field) == 2 for result in coverage_results) assert all(isinstance(result.field[0], int) for result in coverage_results) assert all(isinstance(result.field[1], str) for result in coverage_results) def test_dataclass_factory_with_future_annotations(create_module: Callable[[str], ModuleType]) -> None: module = create_module( """ from __future__ import annotations from dataclasses import dataclass @dataclass class example: foo: str """, ) example: type = module.example assert example.__annotations__ == {"foo": "str"} class MyFactory(DataclassFactory[example]): # type:ignore[valid-type] __model__ = example assert MyFactory.process_kwargs() == {"foo": ANY} def test_dataclass_with_forward_reference(create_module: Callable[[str], ModuleType]) -> None: module = create_module( """ from __future__ import annotations from dataclasses import dataclass from polyfactory.factories import DataclassFactory @dataclass class Foo: bar: Bar @dataclass class Bar: ... """, ) Foo: type = module.Foo class FooFactory(DataclassFactory[Foo]): # type:ignore[valid-type] __model__ = Foo foo = FooFactory.build() assert isinstance(foo, Foo) def test_dataclass_with_init_false() -> None: @vanilla_dataclass class VanillaDC: id_: int = field(init=False) class MyFactory(DataclassFactory[VanillaDC]): __model__ = VanillaDC result = MyFactory.build() assert result def test_use_default_with_callable_default() -> None: @vanilla_dataclass class Foo: default_field: int = dataclasses.field(default_factory=lambda: 10) class FooFactory(DataclassFactory[Foo]): __model__ = Foo __use_defaults__ = True foo = FooFactory.build() assert foo.default_field == 10 def test_use_default_with_non_callable_default() -> None: @vanilla_dataclass class Foo: default_field: int = 10 class FooFactory(DataclassFactory[Foo]): __model__ = Foo __use_defaults__ = True foo = FooFactory.build() assert foo.default_field == 10 def test_union_types() -> None: @vanilla_dataclass class A: a: Union[List[str], List[int]] b: Union[str, List[int]] c: List[Union[Tuple[int, int], Tuple[str, int]]] AFactory = DataclassFactory.create_factory(A) assert AFactory.build() def test_collection_unions_with_models() -> None: @vanilla_dataclass class A: a: int @vanilla_dataclass class B: a: str @vanilla_dataclass class C: a: Union[List[A], List[B]] b: List[Union[A, B]] CFactory = DataclassFactory.create_factory(C) c = CFactory.build() assert isinstance(c.a, list) assert all(isinstance(value, A) for value in c.a) or all(isinstance(value, B) for value in c.a) assert isinstance(c.b, list) assert all(isinstance(value, (A, B)) for value in c.b) @pytest.mark.parametrize("allow_none", (True, False)) def test_optional_type(allow_none: bool) -> None: @vanilla_dataclass class A: a: Union[str, None] b: Optional[str] c: Optional[Union[str, int, List[int]]] class AFactory(DataclassFactory[A]): __model__ = A __allow_none_optionals__ = allow_none a = AFactory.build() if not allow_none: assert isinstance(a.a, str) assert isinstance(a.b, str) assert isinstance(a.c, (str, int, list)) if isinstance(a.c, list): assert all(isinstance(value, int) for value in a.c) ����������������������������������������������������������������������������python-polyfactory-2.18.1/tests/test_dicts.py�������������������������������������������������������0000664�0000000�0000000�00000002323�14721310225�0021353�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from typing import Dict, Union import pytest from pydantic import VERSION, BaseModel from polyfactory.factories.pydantic_factory import ModelFactory def test_passing_nested_dict() -> None: class MyMappedClass(BaseModel): val: str class MyClass(BaseModel): my_mapping_obj: Dict[str, MyMappedClass] my_mapping_str: Dict[str, str] class MyClassFactory(ModelFactory[MyClass]): __model__ = MyClass obj = MyClassFactory.build( my_mapping_str={"foo": "bar"}, my_mapping_obj={"baz": MyMappedClass(val="bar")}, ) assert obj.dict() == {"my_mapping_obj": {"baz": {"val": "bar"}}, "my_mapping_str": {"foo": "bar"}} @pytest.mark.skipif( VERSION.startswith("2"), reason="indeterminate behaviour in pydantic 2.0", ) def test_dict_with_union_random_types() -> None: class MyClass(BaseModel): val: Dict[str, Union[int, str]] class MyClassFactory(ModelFactory[MyClass]): __model__ = MyClass MyClassFactory.seed_random(10) test_obj_1 = MyClassFactory.build() test_obj_2 = MyClassFactory.build() assert isinstance(next(iter(test_obj_1.val.values())), str) assert isinstance(next(iter(test_obj_2.val.values())), int) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/tests/test_factory_configuration.py���������������������������������������0000664�0000000�0000000�00000003273�14721310225�0024650�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from dataclasses import dataclass from typing import Any, Callable, Dict, List, Type from typing_extensions import TypeGuard from polyfactory.factories.base import BaseFactory, T from polyfactory.factories.dataclass_factory import DataclassFactory def test_setting_set_as_default_factory_for_type_on_base_factory() -> None: """Setting the value to `True` shouldn't raise exception when initializing.""" class CustomBaseFactory(BaseFactory[T]): __is_base_factory__ = True __set_as_default_factory_for_type__ = True @classmethod def is_supported_type(cls, value: Any) -> TypeGuard[Type[T]]: # Set this as false since this factory will be injected into the # list of base factories, but this obviously shouldn't be ran # for any of the types. return False def test_inheriting_config() -> None: class CustomType: def __init__(self, a: int) -> None: self.a = a @dataclass class Child: a: List[int] custom_type: CustomType @dataclass class Parent: children: List[Child] class ParentFactory(DataclassFactory[Parent]): __randomize_collection_length__ = True __min_collection_length__ = 5 __max_collection_length__ = 5 @classmethod def get_provider_map(cls) -> Dict[Any, Callable[[], Any]]: return { **super().get_provider_map(), int: lambda: 42, CustomType: lambda: CustomType(a=5), } result = ParentFactory.build() assert len(result.children) == 5 assert result.children[0].a == [42] * 5 assert result.children[0].custom_type.a == 5 �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/tests/test_factory_fields.py����������������������������������������������0000664�0000000�0000000�00000014414�14721310225�0023246�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������import random from dataclasses import dataclass from datetime import datetime, timedelta from typing import Any, ClassVar, List, Optional, Union import pytest from pydantic import BaseModel from polyfactory.decorators import post_generated from polyfactory.exceptions import ConfigurationException, MissingBuildKwargException from polyfactory.factories.dataclass_factory import DataclassFactory from polyfactory.factories.pydantic_factory import ModelFactory from polyfactory.fields import Ignore, PostGenerated, Require, Use def test_use() -> None: class MyClass: name: str @classmethod def builder(cls, name: str) -> "MyClass": instance = MyClass() instance.name = name return instance default_name = "Moishe Zuchmir" class MyModel(BaseModel): my_class: MyClass class Config: arbitrary_types_allowed = True class MyFactory(ModelFactory): __model__ = MyModel my_class = Use(fn=MyClass.builder, name=default_name) result = MyFactory.build() assert result.my_class.name == default_name def test_sub_factory() -> None: default_name = "Moishe Zuchmir" class FirstModel(BaseModel): name: str class SecondModel(BaseModel): first_model: FirstModel class MyFactory(ModelFactory): __model__ = SecondModel first_model = Use(fn=ModelFactory.create_factory(FirstModel).build, name=default_name) result = MyFactory.build() assert result.first_model.name == default_name def test_build_kwarg() -> None: class MyModel(BaseModel): name: str class MyFactory(ModelFactory): __model__ = MyModel name = Require() with pytest.raises(MissingBuildKwargException): MyFactory.build() assert MyFactory.build(name="moishe").name == "moishe" def test_ignored() -> None: class MyModel(BaseModel): name: Optional[str] = None class MyFactory(ModelFactory): __model__ = MyModel name = Ignore() assert MyFactory.build().name is None def test_post_generation() -> None: random_delta = timedelta(days=random.randint(0, 12), seconds=random.randint(13, 13000)) def add_timedelta(name: str, values: Any, **kwargs: Any) -> datetime: assert name == "to_dt" assert "from_dt" in values assert isinstance(values["from_dt"], datetime) return values["from_dt"] + random_delta def decide_long(name: str, values: Any, **kwargs: Any) -> bool: assert name == "is_long" assert "from_dt" in values assert "to_dt" in values assert "threshold" in kwargs assert isinstance(values["from_dt"], datetime) assert isinstance(values["to_dt"], datetime) difference = values["to_dt"] - values["from_dt"] return difference.days > kwargs["threshold"] # type: ignore def make_caption(name: str, values: Any, **kwargs: Any) -> str: assert name == "caption" assert "is_long" in values return "this was really long for me" if values["is_long"] else "just this" class MyModel(BaseModel): from_dt: datetime to_dt: datetime is_long: bool caption: str class MyFactory(ModelFactory): __model__ = MyModel to_dt = PostGenerated(add_timedelta) is_long = PostGenerated(decide_long, threshold=1) caption = PostGenerated(make_caption) result = MyFactory.build() assert result.to_dt - result.from_dt == random_delta assert result.is_long == (random_delta.days > 1) if result.is_long: assert result.caption == "this was really long for me" else: assert result.caption == "just this" def test_post_generation_classmethod() -> None: class MyModel(BaseModel): from_dt: datetime to_dt: datetime is_long: bool caption: str class MyFactory(ModelFactory): __model__ = MyModel random_delta: timedelta @post_generated @classmethod def to_dt(cls, from_dt: datetime) -> datetime: # save it to cls for test purposes only cls.random_delta = timedelta(days=cls.__random__.randint(0, 12), seconds=cls.__random__.randint(13, 13000)) return from_dt + cls.random_delta @post_generated @classmethod def is_long(cls, from_dt: datetime, to_dt: datetime) -> bool: return (to_dt - from_dt).days > 1 @post_generated @classmethod def caption(cls, is_long: bool) -> str: return "this was really long for me" if is_long else "just this" result = MyFactory.build() assert result.to_dt - result.from_dt == MyFactory.random_delta assert result.is_long == (MyFactory.random_delta.days > 1) if result.is_long: assert result.caption == "this was really long for me" else: assert result.caption == "just this" @pytest.mark.parametrize( "factory_field", [ Use(lambda: "foo"), PostGenerated(lambda: "foo"), Require(), Ignore(), ], ) def test_non_existing_model_fields_does_not_raise_by_default( factory_field: Union[Use, PostGenerated, Require, Ignore], ) -> None: class NoFieldModel(BaseModel): pass ModelFactory.create_factory(NoFieldModel, bases=None, unknown_field=factory_field) @pytest.mark.parametrize( "factory_field", [ Use(lambda: "foo"), PostGenerated(lambda: "foo"), Require(), Ignore(), ], ) def test_non_existing_model_fields_raises_with__check__model__( factory_field: Union[Use, PostGenerated, Require, Ignore], ) -> None: class NoFieldModel(BaseModel): pass with pytest.raises( ConfigurationException, match="unknown_field is declared on the factory NoFieldModelFactory but it is not part of the model NoFieldModel", ): ModelFactory.create_factory(NoFieldModel, bases=None, __check_model__=True, unknown_field=factory_field) def test_mutable_defaults() -> None: @dataclass class A: a: List[str] class AFactory(DataclassFactory[A]): a: ClassVar[List[str]] = [] AFactory.build().a.append("a") assert AFactory.build().a == [] next(iter(AFactory.coverage())).a.append("value") assert next(iter(AFactory.coverage())).a == [] ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/tests/test_factory_subclassing.py�����������������������������������������0000664�0000000�0000000�00000004127�14721310225�0024315�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from dataclasses import dataclass import pytest from pydantic import BaseModel from polyfactory import ConfigurationException from polyfactory.factories import DataclassFactory from polyfactory.factories.pydantic_factory import ModelFactory from polyfactory.field_meta import Null def test_factory_raises_config_error_for_unsupported_model_with_supported_factory() -> None: @dataclass class DataclassModel: id: int with pytest.raises(ConfigurationException): class MyFactory1(ModelFactory): __model__ = DataclassModel class MyFactory2(DataclassFactory): __model__ = DataclassModel def test_factory_raises_config_error_for_unsupported_model() -> None: with pytest.raises(ConfigurationException, match="Model type Null is not supported"): class MyFactory(ModelFactory): __model__ = Null def test_inherit_concrete_factory() -> None: class Parent(BaseModel): name: str class Child(Parent): n: int class ParentFactory(ModelFactory): __model__ = Parent @classmethod def name(cls) -> str: return cls.__model__.__name__ class ChildFactory(ParentFactory): __model__ = Child # type: ignore[assignment] assert ParentFactory.build().name == "Parent" assert ChildFactory.build().name == "Child" def test_inherit_base_factory() -> None: class Parent(BaseModel): name: str class Child(Parent): n: int class ParentFactory(ModelFactory): __is_base_factory__ = True @classmethod def name(cls) -> str: return cls.__model__.__name__ class ChildFactory(ParentFactory): __model__ = Child exc_info = pytest.raises(AttributeError, ParentFactory.build) assert "'ParentFactory' has no attribute '__model__'" in str(exc_info.value) assert ChildFactory.build().name == "Child" # remove the ParentFactory from _base_factories to prevent side effects in other tests # see https://github.com/litestar-org/polyfactory/issues/198 ModelFactory._base_factories.remove(ParentFactory) �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/tests/test_faker_customization.py�����������������������������������������0000664�0000000�0000000�00000000612�14721310225�0024324�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from faker import Faker from polyfactory.factories.pydantic_factory import ModelFactory from tests.models import Pet def test_allows_user_to_define_faker_instance() -> None: my_faker = Faker() setattr(my_faker, "__test__attr__", None) class MyFactory(ModelFactory): __model__ = Pet __faker__ = my_faker assert hasattr(MyFactory.__faker__, "__test__attr__") ����������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/tests/test_generics.py����������������������������������������������������0000664�0000000�0000000�00000004060�14721310225�0022044�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from typing import Generic, List, Optional, TypeVar, Union from pydantic import BaseModel from polyfactory.factories.pydantic_factory import ModelFactory try: from pydantic.generics import GenericModel except ImportError: GenericModel = BaseModel Inner = TypeVar("Inner") APIResponseData = TypeVar("APIResponseData") class Attributes(GenericModel, Generic[Inner]): # type: ignore attributes: Inner class OneInner(BaseModel): one: str id: Optional[int] description: Optional[str] class OneResponse(BaseModel): one: Attributes[OneInner] class TwoInner(BaseModel): two: str id: Optional[int] description: Optional[str] class TwoResponse(BaseModel): two: Attributes[TwoInner] class ThreeInner(BaseModel): three: str relation: int class ThreeResponse(BaseModel): three: Attributes[ThreeInner] class APIResponse(GenericModel, Generic[APIResponseData]): # type: ignore data: List[APIResponseData] def test_generic_factory_one_response() -> None: class APIResponseFactory(ModelFactory[APIResponse[OneResponse]]): __model__ = APIResponse[OneResponse] result = APIResponseFactory.build() assert result.data assert isinstance(result.data[0], OneResponse) def test_generic_factory_two_response() -> None: class APIResponseFactory(ModelFactory): __model__ = APIResponse[TwoResponse] result = APIResponseFactory.build() assert result.data assert isinstance(result.data[0], TwoResponse) def test_generic_factory_three_response() -> None: class APIResponseFactory(ModelFactory): __model__ = APIResponse[ThreeResponse] result = APIResponseFactory.build() assert result.data assert isinstance(result.data[0], ThreeResponse) def test_generic_factory_union_response() -> None: class APIResponseFactory(ModelFactory): __model__ = APIResponse[Union[OneResponse, TwoResponse, ThreeResponse]] result = APIResponseFactory.build() assert result.data assert isinstance(result.data[0], (OneResponse, TwoResponse, ThreeResponse)) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/tests/test_msgspec_factory.py���������������������������������������������0000664�0000000�0000000�00000022736�14721310225�0023447�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������import datetime as dt import sys from decimal import Decimal from enum import Enum from typing import Any, Dict, FrozenSet, Generic, List, NewType, Optional, Set, Tuple, Type, TypeVar, Union from uuid import UUID import msgspec import pytest from msgspec import Meta, Struct, structs from typing_extensions import Annotated from polyfactory.exceptions import ParameterException from polyfactory.factories.msgspec_factory import MsgspecFactory def test_is_supported_type() -> None: class Foo(Struct): ... assert MsgspecFactory.is_supported_type(Foo) is True def test_is_supported_type_without_struct() -> None: class Foo: ... assert MsgspecFactory.is_supported_type(Foo) is False def test_with_basic_types_without_constraints() -> None: class Foo(Struct): bool_field: bool int_field: int float_field: float str_field: str bytse_field: bytes bytearray_field: bytearray tuple_field: Tuple[int, str] tuple_with_variadic_args: Tuple[int, ...] list_field: List[int] dict_field: Dict[str, int] datetime_field: dt.datetime date_field: dt.date time_field: dt.time uuid_field: UUID decimal_field: Decimal any_type: Any class FooFactory(MsgspecFactory[Foo]): __model__ = Foo foo = FooFactory.build() foo_dict = structs.asdict(foo) validated_foo = msgspec.convert(foo_dict, type=Foo) assert foo == validated_foo def test_other_basic_types() -> None: # These types are tested separately since they can't be validated # using `convert`. # REFERENCE: https://github.com/jcrist/msgspec/issues/417 class SampleEnum(Enum): FOO = "foo" BAR = "bar" class Foo(Struct): set_field: Set[int] frozenset_field: FrozenSet[int] enum_type: SampleEnum class FooFactory(MsgspecFactory[Foo]): __model__ = Foo foo = FooFactory.build() assert isinstance(foo.set_field, set) assert isinstance(foo.frozenset_field, frozenset) assert isinstance(foo.enum_type, SampleEnum) def test_with_nested_struct() -> None: class Foo(Struct): int_field: int class Bar(Struct): int_field: int foo_field: Foo class BarFactory(MsgspecFactory[Bar]): __model__ = Bar bar = BarFactory.build() bar_dict = structs.asdict(bar) bar_dict["foo_field"] = structs.asdict(bar_dict["foo_field"]) validated_bar = msgspec.convert(bar_dict, type=Bar) assert validated_bar == bar def test_with_new_type() -> None: UnixName = NewType("UnixName", str) class User(Struct): name: UnixName groups: List[UnixName] constrained_name: Annotated[UnixName, Meta(min_length=20)] class UserFactory(MsgspecFactory[User]): __model__ = User user = UserFactory.build() user_dict = structs.asdict(user) validated_user = msgspec.convert(user_dict, type=User) assert user == validated_user def test_msgspec_types() -> None: class Foo(Struct): unset: msgspec.UnsetType ext: msgspec.msgpack.Ext raw: msgspec.Raw class FooFactory(MsgspecFactory[Foo]): __model__ = Foo foo = FooFactory.build() assert foo.unset == msgspec.UNSET assert isinstance(foo.ext, msgspec.msgpack.Ext) @pytest.mark.skipif(sys.version_info < (3, 9), reason="flaky in 3.8") def test_with_constraints() -> None: class Foo(Struct): int_field: Annotated[int, msgspec.Meta(ge=10, le=500, multiple_of=2)] float_field: Annotated[float, msgspec.Meta(ge=10, le=500, multiple_of=2)] str_field: Annotated[str, msgspec.Meta(min_length=100, max_length=500, pattern=r"\w")] bytes_field: Annotated[bytes, msgspec.Meta(min_length=100, max_length=500)] tuple_field: Annotated[Tuple[int, ...], msgspec.Meta(min_length=10, max_length=100)] list_field: Annotated[List[int], msgspec.Meta(min_length=10, max_length=100)] class FooFactory(MsgspecFactory[Foo]): __model__ = Foo foo = FooFactory.build() foo_dict = structs.asdict(foo) validated_foo = msgspec.convert(foo_dict, type=Foo) assert foo == validated_foo @pytest.mark.skipif(sys.version_info < (3, 9), reason="flaky in 3.8") def test_dict_constraints() -> None: class Foo(Struct): dict_field: Annotated[Dict[str, int], msgspec.Meta(min_length=1)] class FooFactory(MsgspecFactory[Foo]): __model__ = Foo foo = FooFactory.build() foo_dict = structs.asdict(foo) validated_foo = msgspec.convert(foo_dict, type=Foo) assert foo == validated_foo @pytest.mark.skipif(sys.version_info < (3, 9), reason="flaky in 3.8") @pytest.mark.parametrize("t", (dt.datetime, dt.time)) def test_datetime_constraints(t: Union[Type[dt.datetime], Type[dt.time]]) -> None: class Foo(Struct): date_field: Annotated[t, msgspec.Meta(tz=True)] # type: ignore[valid-type] class FooFactory(MsgspecFactory[Foo]): __model__ = Foo with pytest.raises(ParameterException): _ = FooFactory.build() def test_inheritence() -> None: class Foo(Struct): int_field: int class Bar(Foo): pass class BarFactory(MsgspecFactory[Bar]): __model__ = Bar bar = BarFactory.build() bar_dict = structs.asdict(bar) validated_bar = msgspec.convert(bar_dict, type=Bar) assert validated_bar == bar def test_inheritence_with_generics() -> None: T = TypeVar("T") class Foo(Struct, Generic[T]): int_field: int generic_field: T class Bar(Foo[str]): pass class BarFactory(MsgspecFactory[Bar]): __model__ = Bar bar = BarFactory.build() bar_dict = structs.asdict(bar) validated_bar = msgspec.convert(bar_dict, type=Bar) assert validated_bar == bar def test_sequence_with_constrained_item_types() -> None: ConstrainedInt = Annotated[int, Meta(ge=100, le=200)] class Foo(Struct): list_field: List[ConstrainedInt] tuple_field: Tuple[ConstrainedInt] variable_tuple_field: Tuple[ConstrainedInt, ...] set_field: Set[ConstrainedInt] class FooFactory(MsgspecFactory[Foo]): __model__ = Foo foo = FooFactory.build() validated_foo = msgspec.convert(structs.asdict(foo), Foo) assert validated_foo == foo def test_mapping_with_constrained_item_types() -> None: ConstrainedInt = Annotated[int, Meta(ge=100, le=200)] ConstrainedStr = Annotated[str, Meta(min_length=1, max_length=3)] class Foo(Struct): dict_field = Dict[ConstrainedStr, ConstrainedInt] class FooFactory(MsgspecFactory[Foo]): __model__ = Foo foo = FooFactory.build() validated_foo = msgspec.convert(structs.asdict(foo), Foo) assert validated_foo == foo def test_use_default_with_callable_default() -> None: class Foo(Struct): default_field: int = msgspec.field(default_factory=lambda: 10) class FooFactory(MsgspecFactory[Foo]): __model__ = Foo __use_defaults__ = True foo = FooFactory.build() assert foo.default_field == 10 def test_use_default_with_non_callable_default() -> None: class Foo(Struct): default_field: int = 10 class FooFactory(MsgspecFactory[Foo]): __model__ = Foo __use_defaults__ = True foo = FooFactory.build() assert foo.default_field == 10 def test_union_types() -> None: class A(Struct): a: Union[List[str], int] b: Union[str, List[int]] c: List[Union[Tuple[int, int], float]] AFactory = MsgspecFactory.create_factory(A) a = AFactory.build() assert msgspec.convert(structs.asdict(a), A) == a def test_collection_unions_with_models() -> None: class A(Struct): a: int class B(Struct): a: str class C(Struct): a: Union[List[A], str] b: List[Union[A, int]] CFactory = MsgspecFactory.create_factory(C) c = CFactory.build() assert msgspec.convert(structs.asdict(c), C) == c def test_constrained_union_types() -> None: class A(Struct): a: Union[Annotated[List[str], Meta(min_length=10)], Annotated[int, Meta(ge=1000)]] b: Union[List[Annotated[str, Meta(min_length=20)]], int] c: Optional[Annotated[int, Meta(ge=1000)]] d: Union[Annotated[List[int], Meta(min_length=100)], Annotated[str, Meta(min_length=100)]] e: Optional[Union[Annotated[List[int], Meta(min_length=100)], Annotated[str, Meta(min_length=100)]]] f: Optional[Union[Annotated[List[int], Meta(min_length=100)], str]] AFactory = MsgspecFactory.create_factory(A, __allow_none_optionals__=False) a = AFactory.build() assert msgspec.convert(structs.asdict(a), A) == a @pytest.mark.parametrize("allow_none", (True, False)) def test_optional_type(allow_none: bool) -> None: class A(Struct): a: Union[str, None] b: Optional[str] c: Optional[Union[str, int, List[int]]] class AFactory(MsgspecFactory[A]): __model__ = A __allow_none_optionals__ = allow_none a = AFactory.build() assert msgspec.convert(structs.asdict(a), A) == a def test_annotated_children() -> None: class A(Struct): a: Dict[int, Annotated[str, Meta(min_length=20)]] b: List[Annotated[int, Meta(gt=1000)]] c: Annotated[List[Annotated[int, Meta(gt=1000)]], Meta(min_length=50)] d: Dict[int, Annotated[List[Annotated[str, Meta(min_length=1)]], Meta(min_length=1)]] class AFactory(MsgspecFactory[A]): __model__ = A a = AFactory.build() assert msgspec.convert(structs.asdict(a), A) == a ����������������������������������python-polyfactory-2.18.1/tests/test_new_types.py���������������������������������������������������0000664�0000000�0000000�00000012720�14721310225�0022264�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������import sys from datetime import date from decimal import Decimal from types import ModuleType from typing import Any, Callable, Dict, List, NewType, Optional, Tuple, Union import pytest from pydantic import ( VERSION, BaseModel, PositiveFloat, conbytes, condate, condecimal, confloat, confrozenset, conint, conlist, conset, constr, ) from polyfactory.factories.dataclass_factory import DataclassFactory from polyfactory.factories.pydantic_factory import ModelFactory def test_new_types() -> None: MyInt = NewType("MyInt", int) WrappedInt = NewType("WrappedInt", MyInt) class MyModel(BaseModel): int_field: MyInt wrapped_int_field: WrappedInt class MyModelFactory(ModelFactory): __model__ = MyModel result = MyModelFactory.build() assert isinstance(result.int_field, int) assert isinstance(result.wrapped_int_field, int) def test_complex_new_types() -> None: MyStr = NewType("MyStr", str) MyInt = NewType("MyInt", int) class NestedModel(BaseModel): nested_int_field: MyInt MyNestedModel = NewType("MyNestedModel", NestedModel) class MyModel(BaseModel): list_int_field: List[MyInt] union_field: Union[MyInt, MyStr] optional_str_field: Optional[MyStr] tuple_str_str: Tuple[MyStr, MyStr] dict_field: Dict[MyStr, Any] complex_dict_field: Dict[MyStr, Dict[Union[MyInt, MyStr], MyInt]] nested_model_field: MyNestedModel class MyModelFactory(ModelFactory): __model__ = MyModel result = MyModelFactory.build() assert isinstance(result.list_int_field[0], int) assert isinstance(result.union_field, (int, str)) assert result.optional_str_field is None or isinstance(result.optional_str_field, str) assert isinstance(result.tuple_str_str, tuple) assert isinstance(result.dict_field, dict) assert isinstance(result.nested_model_field, NestedModel) assert isinstance(result.nested_model_field.nested_int_field, int) @pytest.mark.skipif(VERSION.startswith("2"), reason="https://github.com/pydantic/pydantic/issues/5907") def test_constrained_new_types() -> None: ConBytes = NewType("ConBytes", conbytes(min_length=2, max_length=4)) # type: ignore[misc] ConStr = NewType("ConStr", constr(min_length=10, max_length=15)) # type: ignore[misc] ConInt = NewType("ConInt", conint(gt=100, lt=110)) # type: ignore[misc] ConFloat = NewType("ConFloat", confloat(lt=-100)) # type: ignore[misc] ConDecimal = NewType("ConDecimal", condecimal(ge=Decimal(6), le=Decimal(8))) # type: ignore[misc] ConDate = NewType("ConDate", condate(gt=date.today())) # type: ignore[misc] ConMyPositiveFloat = NewType("ConMyPositiveFloat", PositiveFloat) if VERSION.startswith("1"): ConList = NewType("ConList", conlist(item_type=int, min_items=3)) # type: ignore ConSet = NewType("ConSet", conset(item_type=int, min_items=4)) # type: ignore ConFrozenSet = NewType("ConFrozenSet", confrozenset(item_type=str, min_items=5)) # type: ignore else: ConList = NewType("ConList", conlist(item_type=int, min_length=3)) # type: ignore ConSet = NewType("ConSet", conset(item_type=int, min_length=4)) # type: ignore ConFrozenSet = NewType("ConFrozenSet", confrozenset(item_type=str, min_length=5)) # type: ignore class ConstrainedModel(BaseModel): conbytes_field: ConBytes constr_field: ConStr conint_field: ConInt confloat_field: ConFloat condecimal_field: ConDecimal condate_field: ConDate conlist_field: ConList conset_field: ConSet confrozenset_field: ConFrozenSet conpositive_float_field: ConMyPositiveFloat class MyFactory(ModelFactory): __model__ = ConstrainedModel result = MyFactory.build() # we want to make sure that NewType is correctly unwrapped retaining # original type and its attributes. More elaborate testing of constrained # fields is done in tests/constraints/ assert isinstance(result.conbytes_field, bytes) assert 2 <= len(result.conbytes_field) <= 4 assert isinstance(result.constr_field, str) assert 10 <= len(result.constr_field) <= 15 assert isinstance(result.conint_field, int) assert 100 < result.conint_field < 110 assert isinstance(result.confloat_field, float) assert result.confloat_field < -100 assert isinstance(result.condecimal_field, Decimal) assert Decimal(6) <= result.condecimal_field <= Decimal(8) assert isinstance(result.condate_field, date) assert result.condate_field > date.today() assert isinstance(result.conlist_field, list) assert len(result.conlist_field) >= 3 assert isinstance(result.conset_field, set) assert len(result.conset_field) >= 4 assert isinstance(result.confrozenset_field, frozenset) assert len(result.confrozenset_field) >= 5 assert isinstance(result.conpositive_float_field, float) assert result.conpositive_float_field > 0 @pytest.mark.skipif(sys.version_info < (3, 12), reason="3.12 only syntax") def test_type_alias(create_module: Callable[[str], ModuleType]) -> None: module = create_module( """ from typing import Literal from dataclasses import dataclass type LiteralAlias = Literal["a", "b"] @dataclass class A: field: LiteralAlias """, ) factory = DataclassFactory.create_factory(module.A) # type: ignore[var-annotated] result = factory.build() assert result.field in {"a", "b"} ������������������������������������������������python-polyfactory-2.18.1/tests/test_number_generation.py�������������������������������������������0000664�0000000�0000000�00000001632�14721310225�0023752�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from random import Random import pytest from polyfactory.value_generators.constrained_numbers import ( generate_constrained_number, passes_pydantic_multiple_validator, ) from polyfactory.value_generators.primitives import create_random_float @pytest.mark.parametrize( ("maximum", "minimum", "multiple_of"), ((100, 2, 8), (-100, -187, -10), (7.55, 0.13, 0.0123)), ) def test_generate_constrained_number(maximum: float, minimum: float, multiple_of: float) -> None: assert passes_pydantic_multiple_validator( multiple_of=multiple_of, value=generate_constrained_number( random=Random(), minimum=minimum, maximum=maximum, multiple_of=multiple_of, method=create_random_float, ), ) def test_passes_pydantic_multiple_validator_handles_zero_multiplier() -> None: assert passes_pydantic_multiple_validator(1.0, 0) ������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/tests/test_odmantic_factory.py��������������������������������������������0000664�0000000�0000000�00000006375�14721310225�0023605�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from datetime import datetime from typing import Any, List from uuid import UUID import bson import pytest from bson import ObjectId from polyfactory.decorators import post_generated try: from odmantic import AIOEngine, EmbeddedModel, Model from polyfactory.factories.odmantic_odm_factory import OdmanticModelFactory except ImportError: AIOEngine, EmbeddedModel, Model, OdmanticModelFactory = None, None, None, None # type: ignore pytest.importorskip("odmantic") class OtherEmbeddedDocument(EmbeddedModel): # type: ignore name: str serial: UUID created_on: datetime bson_id: bson.ObjectId bson_int64: bson.Int64 bson_dec128: bson.Decimal128 bson_binary: bson.Binary class MyEmbeddedDocument(EmbeddedModel): # type: ignore name: str serial: UUID other_embedded_document: OtherEmbeddedDocument created_on: datetime bson_id: bson.ObjectId bson_int64: bson.Int64 bson_dec128: bson.Decimal128 bson_binary: bson.Binary class MyModel(Model): # type: ignore created_on: datetime bson_id: bson.ObjectId bson_int64: bson.Int64 bson_dec128: bson.Decimal128 bson_binary: bson.Binary name: str embedded: MyEmbeddedDocument embedded_list: List[MyEmbeddedDocument] @pytest.fixture() async def odmantic_engine(mongo_connection: Any) -> AIOEngine: return AIOEngine(client=mongo_connection, database=mongo_connection.db_name) def test_handles_odmantic_models() -> None: class MyFactory(OdmanticModelFactory): __model__ = MyModel result = MyFactory.build() assert isinstance(result, MyModel) assert isinstance(result.id, bson.ObjectId) assert isinstance(result.created_on, datetime) assert isinstance(result.bson_id, bson.ObjectId) assert isinstance(result.bson_int64, bson.Int64) assert isinstance(result.bson_dec128, bson.Decimal128) assert isinstance(result.bson_binary, bson.Binary) assert isinstance(result.name, str) assert isinstance(result.embedded, MyEmbeddedDocument) assert isinstance(result.embedded_list, list) for item in result.embedded_list: assert isinstance(item, MyEmbeddedDocument) assert isinstance(item.name, str) assert isinstance(item.serial, UUID) assert isinstance(item.created_on, datetime) assert isinstance(item.bson_id, bson.ObjectId) assert isinstance(item.bson_int64, bson.Int64) assert isinstance(item.bson_dec128, bson.Decimal128) assert isinstance(item.bson_binary, bson.Binary) other = item.other_embedded_document assert isinstance(other, OtherEmbeddedDocument) assert isinstance(other.name, str) assert isinstance(other.serial, UUID) assert isinstance(other.created_on, datetime) assert isinstance(other.bson_id, bson.ObjectId) assert isinstance(other.bson_int64, bson.Int64) assert isinstance(other.bson_dec128, bson.Decimal128) assert isinstance(other.bson_binary, bson.Binary) def test_post_generated_from_id() -> None: class MyFactory(OdmanticModelFactory): __model__ = MyModel @post_generated @classmethod def name(cls, id: ObjectId) -> str: return f"{cls.__faker__.name()} [{id.generation_time}]" MyFactory.build() �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/tests/test_optional_model_field_inference.py������������������������������0000664�0000000�0000000�00000007632�14721310225�0026443�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from typing import Any, Dict, Generic, Type, TypedDict, TypeVar import pytest from attrs import define from msgspec import Struct from sqlalchemy import Column, Integer from sqlalchemy.orm.decl_api import DeclarativeMeta, registry from pydantic import BaseModel from pydantic.generics import GenericModel from polyfactory import ConfigurationException from polyfactory.factories import TypedDictFactory from polyfactory.factories.attrs_factory import AttrsFactory from polyfactory.factories.base import BaseFactory from polyfactory.factories.msgspec_factory import MsgspecFactory from polyfactory.factories.pydantic_factory import ModelFactory from polyfactory.factories.sqlalchemy_factory import SQLAlchemyFactory try: from odmantic import Model from polyfactory.factories.odmantic_odm_factory import OdmanticModelFactory except ImportError: Model, OdmanticModelFactory = None, None # type: ignore try: from beanie import Document from polyfactory.factories.beanie_odm_factory import BeanieDocumentFactory except ImportError: BeanieDocumentFactory = None # type: ignore Document = None # type: ignore @define class AttrsBase: bool_field: bool class ModelBase(BaseModel): dict_field: Dict[str, int] class MsgspecBase(Struct): int_field: int class Base(metaclass=DeclarativeMeta): __abstract__ = True registry = registry() class SQLAlchemyBase(Base): __tablename__ = "model" id: Any = Column(Integer(), primary_key=True) class TypedDictBase(TypedDict): name: str @pytest.mark.parametrize( "base_factory, generic_arg", [ (AttrsFactory, AttrsBase), (ModelFactory, ModelBase), (MsgspecFactory, MsgspecBase), (SQLAlchemyFactory, SQLAlchemyBase), (TypedDictFactory, TypedDictBase), ], ) def test_modeL_inference_ok(base_factory: Type[BaseFactory], generic_arg: Type[Any]) -> None: class Foo(base_factory[generic_arg]): # type: ignore ... assert getattr(Foo, "__model__") is generic_arg @pytest.mark.skipif(Model is None, reason="Odmantic import error") def test_odmantic_model_inference_ok() -> None: class OdmanticModelBase(Model): # type: ignore name: str class Foo(OdmanticModelFactory[OdmanticModelBase]): ... assert getattr(Foo, "__model__") is OdmanticModelBase @pytest.mark.skipif(Document is None, reason="Beanie import error") def test_beanie_model_inference_ok() -> None: class BeanieBase(Document): name: str class Foo(BeanieDocumentFactory[BeanieBase]): ... assert getattr(Foo, "__model__") is BeanieBase @pytest.mark.parametrize( "base_factory", [ AttrsFactory, ModelFactory, MsgspecFactory, SQLAlchemyFactory, TypedDictFactory, ], ) def test_model_without_generic_type_inference_error(base_factory: Type[BaseFactory]) -> None: with pytest.raises(ConfigurationException): class Foo(base_factory): # type: ignore ... @pytest.mark.parametrize( "base_factory", [ AttrsFactory, ModelFactory, MsgspecFactory, SQLAlchemyFactory, TypedDictFactory, ], ) def test_model_type_error(base_factory: Type[BaseFactory]) -> None: with pytest.raises(ConfigurationException): class Foo(base_factory[int]): # type: ignore ... def test_model_multiple_inheritance_cannot_infer_error() -> None: class PFoo(BaseModel): val: int class TDFoo(TypedDict): val: str with pytest.raises(ConfigurationException): class Foo(ModelFactory[PFoo], TypedDictFactory[TDFoo]): # type: ignore ... def test_generic_model_is_not_an_error() -> None: T = TypeVar("T") P = TypeVar("P") class Foo(GenericModel, Generic[T, P]): # type: ignore[misc] val1: T val2: P class FooFactory(ModelFactory[Foo[str, int]]): ... assert getattr(FooFactory, "__model__") is Foo[str, int] ������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/tests/test_options_validation.py������������������������������������������0000664�0000000�0000000�00000002325�14721310225�0024154�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������import pytest from polyfactory import ConfigurationException from polyfactory.factories.pydantic_factory import ModelFactory from tests.models import Person def test_validates_model_is_set_on_definition_of_factory() -> None: with pytest.raises(ConfigurationException): class MyFactory(ModelFactory): pass def test_validates_connection_in_create_sync() -> None: class MyFactory(ModelFactory): __model__ = Person with pytest.raises(ConfigurationException): MyFactory.create_sync() def test_validates_connection_in_create_batch_sync() -> None: class MyFactory(ModelFactory): __model__ = Person with pytest.raises(ConfigurationException): MyFactory.create_batch_sync(2) @pytest.mark.asyncio() async def test_validates_connection_in_create_async() -> None: class MyFactory(ModelFactory): __model__ = Person with pytest.raises(ConfigurationException): await MyFactory.create_async() @pytest.mark.asyncio() async def test_validates_connection_in_create_batch_async() -> None: class MyFactory(ModelFactory): __model__ = Person with pytest.raises(ConfigurationException): await MyFactory.create_batch_async(2) �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/tests/test_passing_build_args_to_child_factories.py�����������������������0000664�0000000�0000000�00000012056�14721310225�0030014�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from typing import List, Mapping, Optional from pydantic import BaseModel from polyfactory.factories.pydantic_factory import ModelFactory from polyfactory.field_meta import FieldMeta class Address(BaseModel): city: str country: str class Material(BaseModel): name: str origin: str class Toy(BaseModel): name: str weight: float materials: List[Material] class Pet(BaseModel): name: str age: int toys: List[Toy] class Person(BaseModel): name: str age: int pets: List[Pet] address: Address class PersonFactory(ModelFactory): __model__ = Person def test_factory_child_model_list() -> None: data = { "name": "Jean", "pets": [ { "name": "dog", "toys": [ { "name": "ball", "materials": [{"name": "yarn"}, {"name": "plastic"}], }, { "name": "bone", }, ], }, { "name": "cat", }, ], "address": { "country": "France", }, } person = PersonFactory.build(factory_use_construct=False, **data) assert person.name == "Jean" assert len(person.pets) == 2 assert person.pets[0].name == "dog" dog = person.pets[0] assert len(dog.toys) == 2 dog_toys = dog.toys assert dog_toys[0].name == "ball" assert len(dog.toys[0].materials) == 2 assert dog.toys[0].materials[0].name == "yarn" assert dog.toys[0].materials[1].name == "plastic" assert len(dog.toys[1].materials) > 0 assert dog.toys[1].name == "bone" assert person.pets[1].name == "cat" assert person.address.country == "France" def test_factory_child_pydantic_model() -> None: """Given a Pydantic Factory, When I build a model using the factory passing a Pydantic model as attribute, Then the pydantic model is correctly built. """ address = Address(city="Paris", country="France") person = PersonFactory.build(address=address) assert person.address.city == "Paris" assert person.address.country == "France" def test_factory_child_none() -> None: """Given a Pydantic Factory, When I build a model using the factory passing None as attribute, Then the pydantic model is correctly built. """ class PersonOptional(BaseModel): name: str address: Optional[Address] class PersonOptionalFactory(ModelFactory): __model__ = PersonOptional person = PersonOptionalFactory.build(address=None) assert person.address is None def test_factory_with_partial_fields() -> None: """Given a Pydantic Model with nested Mapping field_meta, When I build the model using the factory passing only partial attributes, Then the model is correctly built. """ class NestedSchema(BaseModel): v: str z: int class UpperSchema(BaseModel): a: int b: Mapping[str, str] nested: Mapping[str, NestedSchema] class UpperSchemaFactory(ModelFactory): __model__ = UpperSchema nested = NestedSchema(v="hello", z=0) some_dict = {"test": "fine"} upper = UpperSchemaFactory.build(b=some_dict, nested={"nested_key": nested}) assert upper.b["test"] == "fine" assert "nested_key" in upper.nested assert upper.nested["nested_key"].v == nested.v assert upper.nested["nested_key"].z == nested.z def test_factory_with_nested_dict() -> None: """Given a Pydantic Model with nested Dict field_meta, When I build the model using the factory passing only partial attributes, Then the model is correctly built. """ class NestedSchema(BaseModel): z: int class UpperSchema(BaseModel): nested: Mapping[str, NestedSchema] class UpperSchemaFactory(ModelFactory): __model__ = UpperSchema nested = NestedSchema(z=0) upper = UpperSchemaFactory.build(nested={"nested_dict": nested}) assert "nested_dict" in upper.nested assert upper.nested["nested_dict"].z == nested.z def test_factory_with_partial_kwargs_deep_in_tree() -> None: class A(BaseModel): name: str age: int class B(BaseModel): a: A class C(BaseModel): b: B class D(BaseModel): c: C class DFactory(ModelFactory): __model__ = D build_result = DFactory.build(factory_use_construct=False, **{"c": {"b": {"a": {"name": "test"}}}}) assert build_result assert build_result.c.b.a.name == "test" def test_factory_with_nested_optional_field_overrides_in_dict() -> None: class MyChildModel(BaseModel): name: str class MyParentModel(BaseModel): child: Optional[MyChildModel] class MyParentModelFactory(ModelFactory): __model__ = MyParentModel @classmethod def should_set_none_value(cls, field_meta: FieldMeta) -> bool: return True result = MyParentModelFactory.build(child={"name": "test"}) assert result.child is not None assert result.child.name == "test" ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/tests/test_persistence_handlers.py����������������������������������������0000664�0000000�0000000�00000004071�14721310225�0024453�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from typing import Any import pytest from pydantic import BaseModel from polyfactory import AsyncPersistenceProtocol, SyncPersistenceProtocol from polyfactory.factories.pydantic_factory import ModelFactory class MyModel(BaseModel): name: str class MySyncPersistenceHandler(SyncPersistenceProtocol): def save(self, data: Any, *args: Any, **kwargs: Any) -> Any: return data def save_many(self, data: Any, *args: Any, **kwargs: Any) -> Any: return data class MyAsyncPersistenceHandler(AsyncPersistenceProtocol): async def save(self, data: Any, *args: Any, **kwargs: Any) -> Any: return data async def save_many(self, data: Any, *args: Any, **kwargs: Any) -> Any: return data def test_sync_persistence_handler_is_set_and_called_with_instance() -> None: class MyFactory(ModelFactory): __model__ = MyModel __sync_persistence__ = MySyncPersistenceHandler() assert MyFactory.create_sync().name assert [instance.name for instance in MyFactory.create_batch_sync(size=2)] def test_sync_persistence_handler_is_set_and_called_with_class() -> None: class MyFactory(ModelFactory): __model__ = MyModel __sync_persistence__ = MySyncPersistenceHandler assert MyFactory.create_sync().name assert [instance.name for instance in MyFactory.create_batch_sync(size=2)] @pytest.mark.asyncio() async def test_async_persistence_handler_is_set_and_called_with_instance() -> None: class MyFactory(ModelFactory): __model__ = MyModel __async_persistence__ = MyAsyncPersistenceHandler() assert (await MyFactory.create_async()).name assert [instance.name for instance in (await MyFactory.create_batch_async(size=2))] @pytest.mark.asyncio() async def test_async_persistence_handler_is_set_and_called_with_class() -> None: class MyFactory(ModelFactory): __model__ = MyModel __async_persistence__ = MyAsyncPersistenceHandler assert (await MyFactory.create_async()).name assert [instance.name for instance in (await MyFactory.create_batch_async(size=2))] �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/tests/test_provider_map.py������������������������������������������������0000664�0000000�0000000�00000003003�14721310225�0022730�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from dataclasses import dataclass from typing import Any, Callable, Dict, Generic, TypeVar from polyfactory.factories.base import BaseFactory from polyfactory.factories.dataclass_factory import DataclassFactory def test_provider_map() -> None: provider_map = BaseFactory.get_provider_map() provider_map.pop(Any) for type_, handler in provider_map.items(): value = handler() assert isinstance(value, type_) def test_provider_map_with_any() -> None: @dataclass class Foo: foo: Any class FooFactory(DataclassFactory[Foo]): @classmethod def get_provider_map(cls) -> Dict[Any, Callable[[], Any]]: provider_map = super().get_provider_map() provider_map[Any] = lambda: "any" return provider_map foo = FooFactory.build() assert foo.foo == "any" coverage_result = list(FooFactory.coverage()) assert all(result.foo == "any" for result in coverage_result) def test_provider_map_with_typevar() -> None: T = TypeVar("T") @dataclass class Foo(Generic[T]): foo: T class FooFactory(DataclassFactory[Foo]): @classmethod def get_provider_map(cls) -> Dict[Any, Callable[[], Any]]: provider_map = super().get_provider_map() provider_map[T] = lambda: "any" return provider_map foo = FooFactory.build() assert foo.foo == "any" coverage_result = list(FooFactory.coverage()) assert all(result.foo == "any" for result in coverage_result) �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/tests/test_pydantic_factory.py��������������������������������������������0000664�0000000�0000000�00000103166�14721310225�0023616�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������import re import sys from collections import Counter, deque from dataclasses import dataclass from datetime import date, datetime, time, timedelta from decimal import Decimal from ipaddress import ( IPv4Address, IPv4Interface, IPv4Network, IPv6Address, IPv6Interface, IPv6Network, ) from pathlib import Path from typing import Callable, Dict, FrozenSet, List, Literal, Optional, Sequence, Set, Tuple, Type, Union from uuid import UUID import pytest from annotated_types import Ge, Gt, Le, LowerCase, MinLen, UpperCase from typing_extensions import Annotated, TypeAlias import pydantic from pydantic import ( UUID1, UUID3, UUID4, UUID5, AmqpDsn, AnyHttpUrl, AnyUrl, BaseModel, ByteSize, DirectoryPath, EmailStr, Field, FilePath, FutureDate, HttpUrl, IPvAnyAddress, IPvAnyInterface, IPvAnyNetwork, Json, KafkaDsn, NameEmail, NegativeFloat, NegativeInt, NonNegativeInt, NonPositiveFloat, PastDate, PositiveFloat, PositiveInt, PostgresDsn, RedisDsn, SecretBytes, SecretStr, StrictBool, StrictBytes, StrictFloat, StrictInt, StrictStr, ValidationError, conbytes, condecimal, confloat, confrozenset, conint, conlist, conset, constr, validator, ) from polyfactory.factories import DataclassFactory from polyfactory.factories.pydantic_factory import _IS_PYDANTIC_V1, ModelFactory from tests.models import Person, PetFactory IS_PYDANTIC_V1 = _IS_PYDANTIC_V1 IS_PYDANTIC_V2 = not _IS_PYDANTIC_V1 REGEX_PATTERN = r"(a|b|c)zz" @pytest.mark.skipif(IS_PYDANTIC_V2, reason="pydantic v1 only functionality") def test_const() -> None: class A(BaseModel): v: int = Field(1, const=True) # type: ignore[call-arg] class AFactory(ModelFactory[A]): __model__ = A for _ in range(5): assert AFactory.build() def test_optional_with_constraints() -> None: class A(BaseModel): a: Optional[float] = Field(None, ge=0, le=1) class AFactory(ModelFactory[A]): __model__ = A # Setting random seed so that we get a non-optional value random_seed = 1 __random_seed__ = random_seed # verify no pydantic.ValidationError is thrown assert isinstance(AFactory.build().a, float) @pytest.mark.skipif(sys.version_info < (3, 10), reason="requires python3.9 or higher") def test_list_unions() -> None: # issue: https://github.com/litestar-org/polyfactory/issues/300, no error reproduced class A(BaseModel): a: str class B(BaseModel): b: str class C(BaseModel): c: list[A] | list[B] class CFactory(ModelFactory[C]): __forward_ref_resolution_type_mapping__ = {"A": A, "B": B, "C": C} __model__ = C assert isinstance(CFactory.build().c, list) assert len(CFactory.build().c) > 0 assert isinstance(CFactory.build().c[0], (A, B)) @pytest.mark.skipif(IS_PYDANTIC_V1, reason="only for Pydantic v2") def test_json_type() -> None: class A(BaseModel): a: Json[int] class AFactory(ModelFactory[A]): __model__ = A assert isinstance(AFactory.build(), A) @pytest.mark.skipif(IS_PYDANTIC_V1, reason="only for Pydantic v2") def test_nested_json_type() -> None: class A(BaseModel): a: int class B(BaseModel): b: Json[A] class BFactory(ModelFactory[B]): __model__ = B assert isinstance(BFactory.build(), B) def test_sequence_with_annotated_item_types() -> None: ConstrainedInt = Annotated[int, Field(ge=100, le=200)] class Foo(BaseModel): list_field: List[ConstrainedInt] tuple_field: Tuple[ConstrainedInt] variable_tuple_field: Tuple[ConstrainedInt, ...] set_field: Set[ConstrainedInt] class FooFactory(ModelFactory[Foo]): __model__ = Foo assert FooFactory.build() def test_mapping_with_annotated_item_types() -> None: ConstrainedInt = Annotated[int, Field(ge=100, le=200)] ConstrainedStr = Annotated[str, Field(min_length=1, max_length=3)] class Foo(BaseModel): dict_field: Dict[ConstrainedStr, ConstrainedInt] class FooFactory(ModelFactory[Foo]): __model__ = Foo assert FooFactory.build() def test_use_default_with_callable_default() -> None: class Foo(BaseModel): default_field: int = Field(default_factory=lambda: 10) class FooFactory(ModelFactory[Foo]): __model__ = Foo __use_defaults__ = True foo = FooFactory.build() assert foo.default_field == 10 def test_use_default_with_non_callable_default() -> None: class Foo(BaseModel): default_field: int = Field(default=10) class FooFactory(ModelFactory[Foo]): __model__ = Foo __use_defaults__ = True foo = FooFactory.build() assert foo.default_field == 10 def test_factory_nested_model_collection_coverage() -> None: class Nested(BaseModel): foo: int class CollectionModel(BaseModel): collection: List[Nested] class CollectionModelFactory(ModelFactory[CollectionModel]): __model__ = CollectionModel instances = list(CollectionModelFactory.coverage()) assert len(instances) == 1 instance = instances[0] assert len(instance.collection) == 1 assert isinstance(instance.collection[0], Nested) def test_factory_nested_model_collection_construct_coverage() -> None: class Nested(BaseModel): foo: int @validator("foo") @classmethod def always_invalid(cls, v: int) -> None: raise ValueError("invalid by validator") class CollectionModel(BaseModel): collection: List[Nested] class CollectionModelFactory(ModelFactory[CollectionModel]): __model__ = CollectionModel instances = list(CollectionModelFactory.coverage(factory_use_construct=True)) assert len(instances) == 1 instance = instances[0] assert len(instance.collection) == 1 assert isinstance(instance.collection[0], Nested) def test_factory_use_construct() -> None: # factory should pass values without validation invalid_age = "non_valid_age" non_validated_pet = PetFactory.build(factory_use_construct=True, age=invalid_age) assert non_validated_pet.age == invalid_age with pytest.raises(ValidationError): PetFactory.build(age=invalid_age) def test_factory_use_construct_coverage() -> None: class Foo(BaseModel): invalid: int @validator("invalid") @classmethod def always_invalid(cls, v: int) -> None: raise ValueError("invalid by validator") class FooFactory(ModelFactory[Foo]): __model__ = Foo non_validated = list(FooFactory.coverage(factory_use_construct=True)) assert len(non_validated) == 1 with pytest.raises(ValidationError): FooFactory.build() def test_factory_use_construct_nested() -> None: class Child(BaseModel): a: int = Field(ge=0) class Parent(BaseModel): child: Child class ParentFactory(ModelFactory[Parent]): __model__ = Parent non_validated_parent = ParentFactory.build(factory_use_construct=True, child={"a": -1}) assert non_validated_parent.child.a == -1 with pytest.raises(ValidationError): ParentFactory.build(child={"a": -1}) def test_factory_use_construct_validator() -> None: class Foo(BaseModel): invalid: int @validator("invalid") @classmethod def always_invalid(cls, v: int) -> None: raise ValueError("invalid by validator") class FooFactory(ModelFactory[Foo]): __model__ = Foo non_validated = FooFactory.build(factory_use_construct=True) assert isinstance(non_validated.invalid, int) with pytest.raises(ValidationError): FooFactory.build() @pytest.mark.parametrize("sequence_type", (Tuple, List)) def test_factory_use_construct_nested_sequence(sequence_type: Type[Sequence]) -> None: class Child(BaseModel): a: int = Field(ge=0) class Parent(BaseModel): child: sequence_type[Child] # type: ignore[valid-type] class ParentFactory(ModelFactory[Parent]): __model__ = Parent non_validated_parent = ParentFactory.build(factory_use_construct=True, child=[{"a": -1}]) assert len(non_validated_parent.child) == 1 with pytest.raises(ValidationError): ParentFactory.build(child=[{"a": -1}]) @pytest.mark.parametrize("set_type", (FrozenSet, Set)) def test_factory_use_construct_nested_set(set_type: Union[Type[FrozenSet], Type[Set]]) -> None: class Child(BaseModel): invalid: int = Field() @validator("invalid", allow_reuse=True) @classmethod def always_invalid(cls, v: int) -> None: raise ValueError("invalid by validator") def __hash__(self) -> int: return hash(self.invalid) class Parent(BaseModel): child: set_type[Child] # type: ignore[valid-type] class ParentFactory(ModelFactory[Parent]): __model__ = Parent non_validated_parent = ParentFactory.build(factory_use_construct=True) assert len(non_validated_parent.child) == 1 assert isinstance(non_validated_parent.child, set_type) with pytest.raises(ValidationError): ParentFactory.build() def test_mapping_with_annotated_nested_model() -> None: class ChildValue(BaseModel): a: int = Field(ge=0) class Parent(BaseModel): dict_field: Dict[str, ChildValue] class ParentFactory(ModelFactory[Parent]): __model__ = Parent non_validated_parent = ParentFactory.build(factory_use_construct=True, dict_field={"arb": {"a": -1}}) assert set(non_validated_parent.dict_field) == {"arb"} # not converted assert non_validated_parent.dict_field["arb"] == {"a": -1} # type: ignore[comparison-overlap] with pytest.raises(ValidationError): assert ParentFactory.build(dict_field={"arb": {"a": -1}}) @pytest.mark.skipif( True, reason=( "pydantic 1 only test, " "get_args function not returning the origin type as expected for pydantic v1 constrained values, " "ex. ConstrainedListValue. " ), ) def test_factory_use_construct_nested_constraint_list_v1() -> None: class Child(BaseModel): a: int = Field(ge=0) class Parent(BaseModel): child: conlist(Child, min_items=1, max_items=4) # type: ignore[valid-type] child_annotated: Annotated[List[Child], Field(min_items=1, max_items=4)] class ParentFactory(ModelFactory[Parent]): __model__ = Parent non_validated_parent = ParentFactory.build( factory_use_construct=True, child=[{"a": -1}], child_annotated=[{"a": -2}] ) assert non_validated_parent.child[0].a == -1 assert non_validated_parent.child_annotated[0].a == -2 with pytest.raises(ValidationError): ParentFactory.build(child=[{"a": -1}]) with pytest.raises(ValidationError): ParentFactory.build(child_annotated=[{"a": -1}]) @pytest.mark.skipif(IS_PYDANTIC_V1, reason="pydantic 2 only test") def test_factory_use_construct_nested_constraint_list_v2() -> None: class Child(BaseModel): a: int = Field(ge=0) class Parent(BaseModel): child: conlist(Child, min_length=1, max_length=4) # type: ignore[valid-type] child_annotated: Annotated[List[Child], Field(min_length=1, max_length=4)] class ParentFactory(ModelFactory[Parent]): __model__ = Parent non_validated_parent = ParentFactory.build( factory_use_construct=True, child=[{"a": -1}], child_annotated=[{"a": -2}] ) assert non_validated_parent.child[0].a == -1 assert non_validated_parent.child_annotated[0].a == -2 with pytest.raises(ValidationError): ParentFactory.build(child=[{"a": -1}]) with pytest.raises(ValidationError): ParentFactory.build(child_annotated=[{"a": -1}]) @pytest.mark.skipif(IS_PYDANTIC_V2, reason="pydantic 1 only test") def test_build_instance_by_field_alias_with_allow_population_by_field_name_flag_pydantic_v1() -> None: class MyModel(BaseModel): aliased_field: str = Field(..., alias="special_field") class Config: allow_population_by_field_name = True class MyFactory(ModelFactory): __model__ = MyModel instance = MyFactory.build(aliased_field="some") assert instance.aliased_field == "some" @pytest.mark.skipif(IS_PYDANTIC_V1, reason="pydantic 2 only test") def test_build_instance_by_field_alias_with_populate_by_name_flag_pydantic_v2() -> None: class MyModel(BaseModel): model_config = {"populate_by_name": True} aliased_field: str = Field(..., alias="special_field") class MyFactory(ModelFactory): __model__ = MyModel instance = MyFactory.build(aliased_field="some") assert instance.aliased_field == "some" def test_build_instance_by_field_name_with_allow_population_by_field_name_flag() -> None: class MyModel(BaseModel): aliased_field: str = Field(..., alias="special_field") class Config: allow_population_by_field_name = True class MyFactory(ModelFactory): __model__ = MyModel instance = MyFactory.build(special_field="some") assert instance.aliased_field == "some" def test_alias_parsing() -> None: class MyModel(BaseModel): aliased_field: str = Field(alias="special_field") class MyFactory(ModelFactory): __model__ = MyModel assert isinstance(MyFactory.build().aliased_field, str) def test_type_property_parsing() -> None: class Base(BaseModel): if IS_PYDANTIC_V2: MongoDsn_pydantic_type: pydantic.networks.MongoDsn MariaDBDsn_pydantic_type: pydantic.networks.MariaDBDsn CockroachDsn_pydantic_type: pydantic.networks.CockroachDsn MySQLDsn_pydantic_type: pydantic.networks.MySQLDsn PastDatetime_pydantic_type: pydantic.PastDatetime FutureDatetime_pydantic_type: pydantic.FutureDatetime AwareDatetime_pydantic_type: pydantic.AwareDatetime NaiveDatetime_pydantic_type: pydantic.NaiveDatetime else: PyObject_pydantic_type: pydantic.types.PyObject Color_pydantic_type: pydantic.color.Color class MyModel(Base): object_field: object float_field: float int_field: int bool_field: bool str_field: str bytes_field: bytes # built-in objects dict_field: dict tuple_field: tuple list_field: list set_field: set frozenset_field: frozenset deque_field: deque # standard library objects Path_field: Path Decimal_field: Decimal UUID_field: UUID # datetime datetime_field: datetime date_field: date time_field: time timedelta_field: timedelta # ip addresses IPv4Address_field: IPv4Address IPv4Interface_field: IPv4Interface IPv4Network_field: IPv4Network IPv6Address_field: IPv6Address IPv6Interface_field: IPv6Interface IPv6Network_field: IPv6Network # types Callable_field: Callable # pydantic specific ByteSize_pydantic_type: ByteSize PositiveInt_pydantic_type: PositiveInt FilePath_pydantic_type: FilePath NegativeFloat_pydantic_type: NegativeFloat NegativeInt_pydantic_type: NegativeInt PositiveFloat_pydantic_type: PositiveFloat NonPositiveFloat_pydantic_type: NonPositiveFloat NonNegativeInt_pydantic_type: NonNegativeInt StrictInt_pydantic_type: StrictInt StrictBool_pydantic_type: StrictBool StrictBytes_pydantic_type: StrictBytes StrictFloat_pydantic_type: StrictFloat StrictStr_pydantic_type: StrictStr DirectoryPath_pydantic_type: DirectoryPath EmailStr_pydantic_type: EmailStr NameEmail_pydantic_type: NameEmail Json_pydantic_type: Json AnyUrl_pydantic_type: AnyUrl AnyHttpUrl_pydantic_type: AnyHttpUrl HttpUrl_pydantic_type: HttpUrl PostgresDsn_pydantic_type: PostgresDsn RedisDsn_pydantic_type: RedisDsn UUID1_pydantic_type: UUID1 UUID3_pydantic_type: UUID3 UUID4_pydantic_type: UUID4 UUID5_pydantic_type: UUID5 SecretBytes_pydantic_type: SecretBytes SecretStr_pydantic_type: SecretStr IPvAnyAddress_pydantic_type: IPvAnyAddress IPvAnyInterface_pydantic_type: IPvAnyInterface IPvAnyNetwork_pydantic_type: IPvAnyNetwork AmqpDsn_pydantic_type: AmqpDsn KafkaDsn_pydantic_type: KafkaDsn PastDate_pydantic_type: PastDate FutureDate_pydantic_type: FutureDate Counter_pydantic_type: Counter class MyFactory(ModelFactory): __model__ = MyModel result = MyFactory.build() for key in MyFactory.get_provider_map(): key_name = key.__name__ if hasattr(key, "__name__") else key._name if hasattr(result, f"{key_name}_field"): assert isinstance(getattr(result, f"{key_name}_field"), key) elif hasattr(result, f"{key_name}_pydantic_type"): assert getattr(result, f"{key_name}_pydantic_type") is not None @pytest.mark.parametrize( "type_", [AnyUrl, HttpUrl, KafkaDsn, PostgresDsn, RedisDsn, AmqpDsn, AnyHttpUrl], ) def test_optional_url_field_parsed_correctly(type_: TypeAlias) -> None: class MyModel(BaseModel): url: Optional[type_] class MyFactory(ModelFactory[MyModel]): __model__ = MyModel while not (url := MyFactory.build().url): assert not url assert MyModel(url=url) # no validation error raised @pytest.mark.skipif(IS_PYDANTIC_V2, reason="pydantic 1 only test") def test_handles_complex_typing_with_custom_root_type() -> None: class MyModel(BaseModel): __root__: List[int] class MyFactory(ModelFactory[MyModel]): __model__ = MyModel result = MyFactory.build() assert result.__root__ assert isinstance(result.__root__, list) def test_union_types() -> None: class A(BaseModel): a: Union[List[str], List[int]] b: Union[str, List[int]] c: List[Union[Tuple[int, int], Tuple[str, int]]] AFactory = ModelFactory.create_factory(A) assert AFactory.build() def test_collection_unions_with_models() -> None: class A(BaseModel): a: int class B(BaseModel): a: str class C(BaseModel): a: Union[List[A], List[B]] b: List[Union[A, B]] CFactory = ModelFactory.create_factory(C) assert CFactory.build() def test_constrained_union_types() -> None: class A(BaseModel): a: Union[Annotated[List[str], MinLen(100)], Annotated[int, Ge(1000)]] b: Union[List[Annotated[str, MinLen(100)]], int] c: Union[Annotated[List[int], MinLen(100)], None] d: Union[Annotated[List[int], MinLen(100)], Annotated[List[str], MinLen(100)]] e: Optional[Union[Annotated[List[int], MinLen(10)], Annotated[List[str], MinLen(10)]]] f: Optional[Union[Annotated[List[int], MinLen(10)], List[str]]] AFactory = ModelFactory.create_factory(A, __allow_none_optionals__=False) assert AFactory.build() @pytest.mark.parametrize("allow_none", (True, False)) def test_optional_type(allow_none: bool) -> None: class A(BaseModel): a: Union[str, None] b: Optional[str] c: Optional[Union[str, int, List[int]]] class AFactory(ModelFactory[A]): __model__ = A __allow_none_optionals__ = allow_none assert AFactory.build() def test_discriminated_unions() -> None: class BasePet(BaseModel): name: str class BlackCat(BasePet): pet_type: Literal["cat"] color: Literal["black"] class WhiteCat(BasePet): pet_type: Literal["cat"] color: Literal["white"] class Dog(BasePet): pet_type: Literal["dog"] class Owner(BaseModel): pet: Annotated[ Union[Annotated[Union[BlackCat, WhiteCat], Field(discriminator="color")], Dog], Field(discriminator="pet_type"), ] name: str class OwnerFactory(ModelFactory): __model__ = Owner assert OwnerFactory.build() def test_predicated_fields() -> None: @dataclass class PredicatedMusician: name: Annotated[str, UpperCase] band: Annotated[str, LowerCase] class PredicatedMusicianFactory(DataclassFactory): __model__ = PredicatedMusician assert PredicatedMusicianFactory.build() def test_tuple_with_annotated_constraints() -> None: class Location(BaseModel): long_lat: Tuple[Annotated[float, Ge(-180), Le(180)], Annotated[float, Ge(-90), Le(90)]] class LocationFactory(ModelFactory[Location]): __model__ = Location assert LocationFactory.build() def test_optional_tuple_with_annotated_constraints() -> None: class Location(BaseModel): long_lat: Union[Tuple[Annotated[float, Ge(-180), Le(180)], Annotated[float, Ge(-90), Le(90)]], None] class LocationFactory(ModelFactory[Location]): __model__ = Location assert LocationFactory.build() def test_legacy_tuple_with_annotated_constraints() -> None: class Location(BaseModel): long_lat: Tuple[Annotated[float, Ge(-180), Le(180)], Annotated[float, Ge(-90), Le(90)]] class LocationFactory(ModelFactory[Location]): __model__ = Location assert LocationFactory.build() def test_legacy_optional_tuple_with_annotated_constraints() -> None: class Location(BaseModel): long_lat: Union[Tuple[Annotated[float, Ge(-180), Le(180)], Annotated[float, Ge(-90), Le(90)]], None] class LocationFactory(ModelFactory[Location]): __model__ = Location assert LocationFactory.build() @pytest.mark.skipif(IS_PYDANTIC_V2, reason="pydantic 1 only test") def test_constrained_attribute_parsing_pydantic_v1() -> None: class ConstrainedModel(BaseModel): conbytes_field: conbytes() # type: ignore[valid-type] condecimal_field: condecimal() # type: ignore[valid-type] confloat_field: confloat() # type: ignore[valid-type] conint_field: conint() # type: ignore[valid-type] conlist_field: conlist(str, min_items=5, max_items=10) # type: ignore[valid-type] conset_field: conset(str, min_items=5, max_items=10) # type: ignore[valid-type] confrozenset_field: confrozenset(str, min_items=5, max_items=10) # type: ignore[valid-type] constr_field: constr(to_lower=True) # type: ignore[valid-type] str_field1: str = Field(min_length=11) str_field2: str = Field(max_length=11) str_field3: str = Field(min_length=8, max_length=11, regex=REGEX_PATTERN) # type: ignore[call-arg] int_field: int = Field(gt=1, multiple_of=5) float_field: float = Field(gt=100, lt=1000) decimal_field: Decimal = Field(ge=100, le=1000) list_field: List[str] = Field(min_items=1, max_items=10) # type: ignore[call-arg] constant_field: int = Field(const=True, default=100) # type: ignore[call-arg] optional_field: Optional[constr(min_length=1)] # type: ignore[valid-type] class MyFactory(ModelFactory): __model__ = ConstrainedModel result = MyFactory.build() assert isinstance(result.conbytes_field, bytes) assert isinstance(result.conint_field, int) assert isinstance(result.confloat_field, float) assert isinstance(result.condecimal_field, Decimal) assert isinstance(result.conlist_field, list) assert isinstance(result.conset_field, set) assert isinstance(result.confrozenset_field, frozenset) assert isinstance(result.str_field1, str) assert isinstance(result.constr_field, str) assert len(result.conlist_field) >= 5 assert len(result.conlist_field) <= 10 assert len(result.conset_field) >= 5 assert len(result.conset_field) <= 10 assert len(result.confrozenset_field) >= 5 assert len(result.confrozenset_field) <= 10 assert result.constr_field.lower() == result.constr_field assert len(result.str_field1) >= 11 assert len(result.str_field2) <= 11 assert len(result.str_field3) >= 8 assert len(result.str_field3) <= 11 match = re.search(REGEX_PATTERN, result.str_field3) assert match assert match[0] assert result.int_field >= 1 assert result.int_field % 5 == 0 assert result.float_field > 100 assert result.float_field < 1000 assert result.decimal_field > 100 assert result.decimal_field < 1000 assert len(result.list_field) >= 1 assert len(result.list_field) <= 10 assert all(isinstance(r, str) for r in result.list_field) assert result.constant_field == 100 assert result.optional_field is None or len(result.optional_field) >= 1 @pytest.mark.skipif(IS_PYDANTIC_V2, reason="pydantic 1 only test") def test_complex_constrained_attribute_parsing_pydantic_v1() -> None: class MyModel(BaseModel): conlist_with_model_field: conlist(Person, min_items=3) # type: ignore[valid-type] conlist_with_complex_type: conlist( # type: ignore[valid-type] Dict[str, Tuple[Person, Person, Person]], min_items=1, ) class MyFactory(ModelFactory): __model__ = MyModel result = MyFactory.build() assert len(result.conlist_with_model_field) >= 3 assert all(isinstance(v, Person) for v in result.conlist_with_model_field) assert result.conlist_with_complex_type assert isinstance(result.conlist_with_complex_type[0], dict) assert isinstance(next(iter(result.conlist_with_complex_type[0].values())), tuple) assert len(next(iter(result.conlist_with_complex_type[0].values()))) == 3 assert all(isinstance(v, Person) for v in next(iter(result.conlist_with_complex_type[0].values()))) @pytest.mark.skipif(IS_PYDANTIC_V2, reason="pydantic 1 only test") def test_nested_constrained_attribute_handling_pydantic_1() -> None: # subclassing the constrained fields is not documented by pydantic, # but is supported apparently from pydantic import ( ConstrainedBytes, ConstrainedDecimal, ConstrainedFloat, ConstrainedInt, ConstrainedStr, ) class MyConstrainedString(ConstrainedStr): # type: ignore[misc,valid-type] regex = re.compile("^vpc-.*$") class MyConstrainedBytes(ConstrainedBytes): # type: ignore[misc,valid-type] min_length = 11 class MyConstrainedInt(ConstrainedInt): # type: ignore[misc,valid-type] ge = 11 class MyConstrainedFloat(ConstrainedFloat): # type: ignore[misc,valid-type] ge = 11.0 class MyConstrainedDecimal(ConstrainedDecimal): # type: ignore[misc,valid-type] ge = Decimal("11.0") class MyModel(BaseModel): conbytes_list_field: List[conbytes()] # type: ignore[valid-type] condecimal_list_field: List[condecimal()] # type: ignore[valid-type] confloat_list_field: List[confloat()] # type: ignore[valid-type] conint_list_field: List[conint()] # type: ignore[valid-type] conlist_list_field: List[conlist(str)] # type: ignore[valid-type] conset_list_field: List[conset(str)] # type: ignore[valid-type] constr_list_field: List[constr(to_lower=True)] # type: ignore[valid-type] my_bytes_list_field: List[MyConstrainedBytes] my_decimal_list_field: List[MyConstrainedDecimal] my_float_list_field: List[MyConstrainedFloat] my_int_list_field: List[MyConstrainedInt] my_str_list_field: List[MyConstrainedString] my_bytes_dict_field: Dict[str, MyConstrainedBytes] my_decimal_dict_field: Dict[str, MyConstrainedDecimal] my_float_dict_field: Dict[str, MyConstrainedFloat] my_int_dict_field: Dict[str, MyConstrainedInt] my_str_dict_field: Dict[str, MyConstrainedString] class MyFactory(ModelFactory): __model__ = MyModel result = MyFactory.build() assert result.conbytes_list_field assert result.condecimal_list_field assert result.confloat_list_field assert result.conint_list_field assert result.conlist_list_field assert result.conset_list_field assert result.constr_list_field assert result.my_bytes_list_field assert result.my_decimal_list_field assert result.my_float_list_field assert result.my_int_list_field assert result.my_str_list_field assert result.my_bytes_dict_field assert result.my_decimal_dict_field assert result.my_float_dict_field assert result.my_int_dict_field assert result.my_str_dict_field @pytest.mark.skipif( IS_PYDANTIC_V1 or sys.version_info < (3, 9), reason="pydantic 2 only test, does not work correctly in py 3.8", ) def test_nested_constrained_attribute_handling_pydantic_2() -> None: # subclassing the constrained fields is not documented by pydantic, # but is supported apparently class MyModel(BaseModel): conbytes_list_field: List[conbytes()] # type: ignore[valid-type] condecimal_list_field: List[condecimal()] # type: ignore[valid-type] confloat_list_field: List[confloat()] # type: ignore[valid-type] conint_list_field: List[conint()] # type: ignore[valid-type] conlist_list_field: List[conlist(str)] # type: ignore[valid-type] conset_list_field: List[conset(str)] # type: ignore[valid-type] constr_list_field: List[constr(to_lower=True)] # type: ignore[valid-type] class MyFactory(ModelFactory): __model__ = MyModel result = MyFactory.build() assert result.conbytes_list_field assert result.condecimal_list_field assert result.confloat_list_field assert result.conint_list_field assert result.conlist_list_field assert result.conset_list_field assert result.constr_list_field @pytest.mark.skipif( IS_PYDANTIC_V1 or sys.version_info < (3, 9), reason="pydantic 2 only test, does not work correctly in py 3.8", ) def test_constrained_attribute_parsing_pydantic_v2() -> None: class ConstrainedModel(BaseModel): conbytes_field: conbytes() # type: ignore[valid-type] condecimal_field: condecimal() # type: ignore[valid-type] confloat_field: confloat() # type: ignore[valid-type] conint_field: conint() # type: ignore[valid-type] conlist_field: conlist(str, min_length=5, max_length=10) # type: ignore[valid-type] conset_field: conset(str, min_length=5, max_length=10) # type: ignore[valid-type] confrozenset_field: confrozenset(str, min_length=5, max_length=10) # type: ignore[valid-type] constr_field: constr(to_lower=True) # type: ignore[valid-type] str_field1: str = Field(min_length=11) str_field2: str = Field(max_length=11) str_field3: str = Field(min_length=8, max_length=11, pattern=REGEX_PATTERN) int_field: int = Field(gt=1, multiple_of=5) float_field: float = Field(gt=100, lt=1000) decimal_field: Decimal = Field(ge=100, le=1000) list_field: List[str] = Field(min_length=1, max_length=10) optional_field: Optional[constr(min_length=1)] # type: ignore[valid-type] class MyFactory(ModelFactory): __model__ = ConstrainedModel result = MyFactory.build() assert isinstance(result.conbytes_field, bytes) assert isinstance(result.conint_field, int) assert isinstance(result.confloat_field, float) assert isinstance(result.condecimal_field, Decimal) assert isinstance(result.conlist_field, list) assert isinstance(result.conset_field, set) assert isinstance(result.confrozenset_field, frozenset) assert isinstance(result.str_field1, str) assert isinstance(result.constr_field, str) assert len(result.conlist_field) >= 5 assert len(result.conlist_field) <= 10 assert len(result.conset_field) >= 5 assert len(result.conset_field) <= 10 assert len(result.confrozenset_field) >= 5 assert len(result.confrozenset_field) <= 10 assert result.constr_field.lower() == result.constr_field assert len(result.str_field1) >= 11 assert len(result.str_field2) <= 11 assert len(result.str_field3) >= 8 assert len(result.str_field3) <= 11 match = re.search(REGEX_PATTERN, result.str_field3) assert match assert match[0] assert result.int_field >= 1 assert result.int_field % 5 == 0 assert result.float_field > 100 assert result.float_field < 1000 assert result.decimal_field > 100 assert result.decimal_field < 1000 assert len(result.list_field) >= 1 assert len(result.list_field) <= 10 assert all(isinstance(r, str) for r in result.list_field) assert result.optional_field is None or len(result.optional_field) >= 1 @pytest.mark.skipif(IS_PYDANTIC_V1, reason="pydantic 2 only test") def test_complex_constrained_attribute_parsing_pydantic_v2() -> None: class MyModel(BaseModel): conlist_with_model_field: conlist(Person, min_length=3) # type: ignore[valid-type] conlist_with_complex_type: conlist( # type: ignore[valid-type] Dict[str, Tuple[Person, Person, Person]], min_length=1, ) class MyFactory(ModelFactory): __model__ = MyModel result = MyFactory.build() assert len(result.conlist_with_model_field) >= 3 assert all(isinstance(v, Person) for v in result.conlist_with_model_field) assert result.conlist_with_complex_type assert isinstance(result.conlist_with_complex_type[0], dict) assert isinstance(next(iter(result.conlist_with_complex_type[0].values())), tuple) assert len(next(iter(result.conlist_with_complex_type[0].values()))) == 3 assert all(isinstance(v, Person) for v in next(iter(result.conlist_with_complex_type[0].values()))) def test_annotated_children() -> None: class A(BaseModel): a: Dict[int, Annotated[str, MinLen(min_length=20)]] b: List[Annotated[int, Gt(gt=1000)]] c: Annotated[List[Annotated[int, Gt(gt=1000)]], MinLen(min_length=50)] d: Dict[int, Annotated[List[Annotated[str, MinLen(1)]], MinLen(1)]] AFactory = ModelFactory.create_factory(A) assert AFactory.build() ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/tests/test_pydantic_v1_v2.py����������������������������������������������0000664�0000000�0000000�00000005022�14721310225�0023074�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������"""Tests to check that usage of pydantic v1 and v2 at the same time works.""" from typing import Dict, List, Optional, Type, Union import pytest from typing_extensions import Annotated import pydantic from polyfactory.factories.pydantic_factory import ModelFactory if pydantic.VERSION.startswith("1"): pytest.skip("only for pydantic v2", allow_module_level=True) from pydantic import BaseModel as BaseModelV2 try: from pydantic.v1 import BaseModel as BaseModelV1 except ImportError: from pydantic import BaseModel as BaseModelV1 # type: ignore[assignment] @pytest.mark.parametrize("base_model", [BaseModelV1, BaseModelV2]) def test_is_supported_type(base_model: Type[Union[BaseModelV1, BaseModelV2]]) -> None: class Foo(base_model): # type: ignore[valid-type, misc] ... assert ModelFactory.is_supported_type(Foo) is True @pytest.mark.parametrize("base_model", [BaseModelV1, BaseModelV2]) def test_build(base_model: Type[Union[BaseModelV1, BaseModelV2]]) -> None: class Foo(base_model): # type: ignore[valid-type, misc] a: int b: str c: bool FooFactory = ModelFactory.create_factory(Foo) foo = FooFactory.build() assert isinstance(foo.a, int) assert isinstance(foo.b, str) assert isinstance(foo.c, bool) def test_build_v1_with_contrained_fields() -> None: from pydantic.v1.fields import Field ConstrainedInt = Annotated[int, Field(ge=100, le=200)] ConstrainedStr = Annotated[str, Field(min_length=1, max_length=3)] class Foo(pydantic.v1.BaseModel): # pyright: ignore[reportGeneralTypeIssues] a: ConstrainedInt b: ConstrainedStr c: Union[ConstrainedInt, ConstrainedStr] d: Optional[ConstrainedInt] e: Optional[Union[ConstrainedInt, ConstrainedStr]] f: List[ConstrainedInt] g: Dict[ConstrainedInt, ConstrainedStr] ModelFactory.create_factory(Foo).build() # type: ignore[type-var] def test_build_v2_with_contrained_fields() -> None: from pydantic.fields import Field ConstrainedInt = Annotated[int, Field(ge=100, le=200)] ConstrainedStr = Annotated[str, Field(min_length=1, max_length=3)] class Foo(pydantic.BaseModel): # pyright: ignore[reportGeneralTypeIssues] a: ConstrainedInt b: ConstrainedStr c: Union[ConstrainedInt, ConstrainedStr] d: Optional[ConstrainedInt] e: Optional[Union[ConstrainedInt, ConstrainedStr]] f: List[ConstrainedInt] g: Dict[ConstrainedInt, ConstrainedStr] ModelFactory.create_factory(Foo).build() ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/tests/test_pytest_plugin.py�����������������������������������������������0000664�0000000�0000000�00000004461�14721310225�0023160�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from typing import List import pytest from pydantic import BaseModel from polyfactory.exceptions import ParameterException from polyfactory.factories.pydantic_factory import ModelFactory from polyfactory.fields import Fixture from polyfactory.pytest_plugin import register_fixture from tests.models import Person, PersonFactoryWithoutDefaults @register_fixture class PersonFactoryFixture(PersonFactoryWithoutDefaults): """Person Factory Fixture.""" @register_fixture(name="another_fixture") class AnotherPersonFactoryFixture(PersonFactoryWithoutDefaults): """Another Person Factory Fixture.""" def test_fixture_register_decorator( person_factory_fixture: PersonFactoryFixture, ) -> None: person = person_factory_fixture.build() assert isinstance(person, Person) def test_custom_naming_fixture_register_decorator( another_fixture: AnotherPersonFactoryFixture, ) -> None: person = another_fixture.build() assert isinstance(person, Person) def test_register_with_function_error() -> None: with pytest.raises(ParameterException): @register_fixture # type: ignore def foo() -> None: pass def test_register_with_class_not_model_factory_error() -> None: with pytest.raises(ParameterException): @register_fixture # type: ignore class Foo: pass def test_using_a_fixture_as_field_value() -> None: class MyModel(BaseModel): best_friend: Person all_friends: List[Person] enemies: List[Person] class MyFactory(ModelFactory[MyModel]): __model__ = MyModel best_friend = Fixture(PersonFactoryFixture, name="mike") all_friends = Fixture(PersonFactoryFixture, size=5) enemies = Fixture(PersonFactoryFixture, size=0) result = MyFactory.build() assert result.best_friend.name == "mike" assert len(result.all_friends) == 5 assert result.enemies == [] def test_using_non_fixture_with_the_fixture_field_raises() -> None: class MyModel(BaseModel): best_friend: Person all_friends: List[Person] class MyFactory(ModelFactory[MyModel]): __model__ = MyModel best_friend = Fixture(PersonFactoryFixture, name="mike") all_friends = Fixture(123) # type: ignore with pytest.raises(ParameterException): MyFactory.build() ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/tests/test_random_configuration.py����������������������������������������0000664�0000000�0000000�00000006150�14721310225�0024456�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from dataclasses import dataclass from random import Random from typing import List, Union import pytest from faker import Faker from faker.config import AVAILABLE_LOCALES from polyfactory.factories.dataclass_factory import DataclassFactory FakerLocaleType = Union[str, List[str]] RANDINT_MAP = {i: Random(i).randint(0, 10) for i in range(3)} FAKER_LOCALES: List[FakerLocaleType] = [ AVAILABLE_LOCALES[0], AVAILABLE_LOCALES[1], AVAILABLE_LOCALES[2], AVAILABLE_LOCALES[:3], ] @pytest.mark.parametrize("seed", RANDINT_MAP.keys()) def test_setting_random(seed: int) -> None: @dataclass class Foo: foo: int class FooFactory(DataclassFactory[Foo]): __model__ = Foo __random__ = Random(seed) @classmethod def foo(cls) -> int: return cls.__random__.randint(0, 10) assert FooFactory.build().foo == RANDINT_MAP[seed] @pytest.mark.parametrize("seed", RANDINT_MAP.keys()) def test_setting_random_seed_on_random(seed: int) -> None: @dataclass class Foo: foo: int class FooFactory(DataclassFactory[Foo]): __model__ = Foo __random_seed__ = seed @classmethod def foo(cls) -> int: return cls.__random__.randint(0, 10) assert FooFactory.build().foo == RANDINT_MAP[seed] @pytest.mark.parametrize("seed", RANDINT_MAP.keys()) def test_setting_random_seed_on_faker(seed: int) -> None: @dataclass class Foo: foo: int class FooFactory(DataclassFactory[Foo]): __model__ = Foo __random_seed__ = seed @classmethod def foo(cls) -> int: return cls.__faker__.random_digit() assert FooFactory.build().foo == RANDINT_MAP[seed] def test_setting_random_seed_on_multiple_factories() -> None: foo_seed = 0 bar_seed = 1 @dataclass class Foo: foo: int @dataclass class Bar: bar: int class FooFactory(DataclassFactory[Foo]): __model__ = Foo __random_seed__ = foo_seed @classmethod def foo(cls) -> int: return cls.__random__.randint(0, 10) class BarFactory(DataclassFactory[Bar]): __model__ = Bar __random_seed__ = bar_seed @classmethod def bar(cls) -> int: return cls.__random__.randint(0, 10) assert FooFactory.build().foo == RANDINT_MAP[foo_seed] assert BarFactory.build().bar == RANDINT_MAP[bar_seed] def test_no_override_of_faker() -> None: faker = Faker() @dataclass class Foo: foo: int class FooFactory(DataclassFactory[Foo]): __model__ = Foo __faker__ = faker __random_seed__ = 10 assert FooFactory.__faker__ is faker @pytest.mark.parametrize("locale", FAKER_LOCALES) def test_faker_locale_preserved(locale: FakerLocaleType) -> None: @dataclass class Foo: foo: int class FooFactory(DataclassFactory[Foo]): __model__ = Foo __faker__ = Faker(locale=locale) __random_seed__ = 10 expected_locales = [locale] if isinstance(locale, str) else locale assert FooFactory.__faker__.locales == expected_locales ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/tests/test_random_seed.py�������������������������������������������������0000664�0000000�0000000�00000003015�14721310225�0022524�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from random import randint from typing import Optional from pydantic import VERSION, BaseModel, Field from polyfactory.factories.pydantic_factory import ModelFactory def test_random_seed() -> None: class MyModel(BaseModel): id: int special_id: str = ( Field(pattern=r"ID-[1-9]{3}\.[1-9]{3}") if VERSION.startswith("2") else Field(regex=r"ID-[1-9]{3}\.[1-9]{3}") # type: ignore[call-arg] ) class MyModelFactory(ModelFactory): __model__ = MyModel ModelFactory.seed_random(1651) ins = MyModelFactory.build() assert ins.id == 4 assert ins.special_id == "ID-515.943" def test_deterministic_optionals_seeding() -> None: class ModelWithOptionalValues(BaseModel): name: Optional[str] class FactoryWithNoneOptionals(ModelFactory): __model__ = ModelWithOptionalValues seed = randint(0, 1000) ModelFactory.seed_random(seed) first_build = [FactoryWithNoneOptionals.build() for _ in range(10)] ModelFactory.seed_random(seed) second_build = [FactoryWithNoneOptionals.build() for _ in range(10)] assert first_build == second_build def test_deterministic_constrained_strings() -> None: class MyModel(BaseModel): id: int special_id: str = Field(min_length=10, max_length=24) class MyModelFactory(ModelFactory): __model__ = MyModel ModelFactory.seed_random(1651) ins = MyModelFactory.build() assert ins.id == 4 assert ins.special_id == "48489ab53c59b24acfe1" �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/tests/test_recursive_models.py��������������������������������������������0000664�0000000�0000000�00000005470�14721310225�0023625�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from __future__ import annotations from dataclasses import dataclass, field from typing import Any, Dict, List, Optional, Union import pytest from pydantic import BaseModel, Field from polyfactory.factories.dataclass_factory import DataclassFactory from polyfactory.factories.pydantic_factory import ModelFactory class _Sentinel: ... @dataclass class Node: value: int union_child: Union[Node, int] # noqa: UP007 list_child: List[Node] # noqa: UP006 optional_child: Optional[Node] # noqa: UP007 child: Node = field(default=_Sentinel) # type: ignore[assignment] def __post_init__(self) -> None: # Emulate recursive models set by external init, e.g. ORM relationships if self.child is _Sentinel: # type: ignore[comparison-overlap] self.child = self def test_recusive_model() -> None: factory = DataclassFactory.create_factory(Node) result = factory.build() assert result.child is result, "Default is not used" assert isinstance(result.union_child, int) assert result.optional_child is None assert result.list_child == [] assert factory.build(child={"child": None}).child.child is None class PydanticNode(BaseModel): value: int union_child: Union[PydanticNode, int] # noqa: UP007 list_child: List[PydanticNode] # noqa: UP006 optional_union_child: Union[PydanticNode, None] # noqa: UP007 optional_child: Optional[PydanticNode] # noqa: UP007 child: PydanticNode = Field(default=_Sentinel) # type: ignore[assignment] recursive_key: Dict[PydanticNode, Any] # noqa: UP006 recursive_value: Dict[str, PydanticNode] # noqa: UP006 @pytest.mark.parametrize("factory_use_construct", (True, False)) def test_recursive_pydantic_models(factory_use_construct: bool) -> None: factory = ModelFactory[PydanticNode].create_factory(PydanticNode) result = factory.build(factory_use_construct) assert result.child is _Sentinel, "Default is not used" # type: ignore[comparison-overlap] assert isinstance(result.union_child, int) assert result.optional_union_child is None assert result.optional_child is None assert result.list_child == [] assert result.recursive_key == {} assert result.recursive_value == {} @dataclass class Author: name: str books: List[Book] # noqa: UP006 _DEFAULT_AUTHOR = Author(name="default", books=[]) @dataclass class Book: name: str author: Author = field(default_factory=lambda: _DEFAULT_AUTHOR) def test_recusive_list_model() -> None: factory = DataclassFactory.create_factory(Author) assert factory.build().books[0].author is _DEFAULT_AUTHOR assert factory.build(books=[]).books == [] book_factory = DataclassFactory.create_factory(Book) assert book_factory.build().author.books == [] assert book_factory.build(author=None).author is None ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/tests/test_regex_factory.py�����������������������������������������������0000664�0000000�0000000�00000007365�14721310225�0023121�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������"""The tests in this file have been adapted from: https://github.com/crdoconnor/xeger/blob/master/xeger/tests/test_xeger.py """ import re from random import Random from typing import TYPE_CHECKING, Union import pytest from polyfactory.value_generators.regex import RegexFactory if TYPE_CHECKING: from re import Pattern def match(pattern: Union[str, "Pattern"]) -> None: for _ in range(100): assert re.match(pattern, RegexFactory(random=Random())(pattern)) def test_single_dot() -> None: """Verify that the dot character produces only a single character.""" match(r"^.$") def test_dot() -> None: """Verify that the dot character doesn't produce newlines. See: https://bitbucket.org/leapfrogdevelopment/rstr/issue/1/ """ for _ in range(100): match(r".+") def test_date() -> None: match(r"^([1-9]|0[1-9]|[12][0-9]|3[01])\D([1-9]|0[1-9]|1[012])\D(19[0-9][0-9]|20[0-9][0-9])$") def test_up_to_closing_tag() -> None: match(r"([^<]*)") def test_ipv4() -> None: match(r"^(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]){3}$") def test_year_1900_2099() -> None: match(r"^(19|20)[\d]{2,2}$") def test_positive_or_negative_number() -> None: match(r"^-{0,1}\d*\.{0,1}\d+$") def test_positive_integers() -> None: match(r"^\d+$") def test_email_complicated() -> None: match(r'^([0-9a-zA-Z]([\+\-_\.][0-9a-zA-Z]+)*)+"@(([0-9a-zA-Z][-\w]*[0-9a-zA-Z]*\.)+[a-zA-Z0-9]{2,17})$') def test_email() -> None: match(r"(.*?)\@(.*?)\.(.*?)") def test_alpha() -> None: match(r"[:alpha:]") def test_zero_or_more_anything_non_greedy() -> None: match(r"(.*?)") def test_literals() -> None: match(r"foo") def test_digit() -> None: match(r"\d") def test_nondigits() -> None: match(r"\D") def test_literal_with_repeat() -> None: match(r"A{3}") def test_literal_with_range_repeat() -> None: match(r"A{2, 5}") def test_word() -> None: match(r"\w") def test_nonword() -> None: match(r"\W") def test_or() -> None: match(r"foo|bar") def test_or_with_subpattern() -> None: match(r"(foo|bar)") def test_range() -> None: match(r"[A-F]") def test_character_group() -> None: match(r"[ABC]") def test_caret() -> None: match(r"^foo") def test_dollarsign() -> None: match(r"foo$") def test_not_literal() -> None: match(r"[^a]") def test_negation_group() -> None: match(r"[^AEIOU]") def test_lookahead() -> None: match(r"foo(?=bar)") def test_lookbehind() -> None: pattern = r"(?<=foo)bar" assert re.search(pattern, RegexFactory(random=Random())(pattern)) def test_backreference() -> None: match(r"(foo|bar)baz\1") def test_zero_or_more_greedy() -> None: match(r"a*") match(r"(.*)") def test_zero_or_more_non_greedy() -> None: match(r"a*?") @pytest.mark.parametrize("limit", range(5)) def test_incoherent_limit_and_qualifier(limit: int) -> None: r = RegexFactory(limit=limit, random=Random()) o = r(r"a{2}") assert len(o) == 2 @pytest.mark.parametrize("seed", [777, 1234, 369, 8031]) def test_regex_factory_object_seeding(seed: int) -> None: xg1 = RegexFactory(random=Random(x=seed)) string1 = xg1(r"\w{3,4}") xg2 = RegexFactory(random=Random(x=seed)) string2 = xg2(r"\w{3,4}") assert string1 == string2 def test_regex_factory_random_instance() -> None: xg1 = RegexFactory(random=Random()) xg_random = xg1._random xg2 = RegexFactory(random=Random()) xg2._random = xg_random assert xg1._random == xg2._random # xg_random is used by both, so if we give # the same seed, the result should be the same xg_random.seed(90) string1 = xg1(r"\w\d\w") xg_random.seed(90) string2 = xg2(r"\w\d\w") assert string1 == string2 ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/tests/test_type_coverage_generation.py������������������������������������0000664�0000000�0000000�00000025446�14721310225�0025327�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# ruff: noqa: UP007, UP006 from __future__ import annotations from dataclasses import dataclass, make_dataclass from datetime import date from typing import Any, Dict, FrozenSet, Iterable, List, Literal, Optional, Set, Tuple, Type, Union from uuid import UUID import pytest from typing_extensions import TypedDict from pydantic import BaseModel from polyfactory.decorators import post_generated from polyfactory.exceptions import ParameterException from polyfactory.factories.dataclass_factory import DataclassFactory from polyfactory.factories.pydantic_factory import ModelFactory from polyfactory.factories.typed_dict_factory import TypedDictFactory from polyfactory.utils.types import NoneType from tests.test_pydantic_factory import IS_PYDANTIC_V1 def test_coverage_count() -> None: @dataclass class Profile: name: str high_score: Union[int, float] dob: date data: Union[str, date, int, float] class ProfileFactory(DataclassFactory[Profile]): __model__ = Profile results = list(ProfileFactory.coverage()) assert len(results) == 4 for result in results: assert isinstance(result, Profile) def test_coverage_tuple() -> None: @dataclass class Pair: tuple_: Tuple[Union[int, str], Tuple[Union[int, float], int]] class TupleFactory(DataclassFactory[Pair]): __model__ = Pair results = list(TupleFactory.coverage()) assert len(results) == 2 a0, (b0, c0) = results[0].tuple_ a1, (b1, c1) = results[1].tuple_ assert isinstance(a0, int) and isinstance(b0, int) and isinstance(c0, int) assert isinstance(a1, str) and isinstance(b1, float) and isinstance(c1, int) @pytest.mark.parametrize( "collection_annotation", (Set[Union[int, str]], List[Union[int, str]], FrozenSet[Union[int, str]]), ) def test_coverage_collection(collection_annotation: type) -> None: Collective = make_dataclass("Collective", [("collection", collection_annotation)]) class CollectiveFactory(DataclassFactory[Collective]): # type: ignore __model__ = Collective results = list(CollectiveFactory.coverage()) assert len(results) == 1 result = results[0] collection = result.collection # type: ignore assert len(collection) == 2 v0, v1 = collection assert {type(v0), type(v1)} == {int, str} def test_coverage_literal() -> None: @dataclass class Literally: literal: Literal["a", "b", 1, 2] class LiterallyFactory(DataclassFactory[Literally]): __model__ = Literally results = list(LiterallyFactory.coverage()) assert len(results) == 4 assert results[0].literal == "a" assert results[1].literal == "b" assert results[2].literal == 1 assert results[3].literal == 2 def test_coverage_dict() -> None: @dataclass class Thesaurus: dict_simple: Dict[str, int] dict_more_key_types: Dict[Union[str, int, float], Union[int, str]] dict_more_value_types: Dict[str, Union[int, str]] class ThesaurusFactory(DataclassFactory[Thesaurus]): __model__ = Thesaurus results = list(ThesaurusFactory.coverage()) assert len(results) == 3 @pytest.mark.skip(reason="Does not support recursive types yet.") def test_coverage_recursive() -> None: @dataclass class Recursive: r: Union[Recursive, None] class RecursiveFactory(DataclassFactory[Recursive]): __model__ = Recursive results = list(RecursiveFactory.coverage()) assert len(results) == 2 def test_coverage_typed_dict() -> None: class TypedThesaurus(TypedDict): number: int string: str union: Union[int, str] collection: List[Union[int, str]] class TypedThesaurusFactory(TypedDictFactory[TypedThesaurus]): __model__ = TypedThesaurus results = list(TypedThesaurusFactory.coverage()) assert len(results) == 2 example = TypedThesaurusFactory.build() for result in results: assert result.keys() == example.keys() def test_coverage_typed_dict_field() -> None: class TypedThesaurus(TypedDict): number: int string: str union: Union[int, str] collection: List[Union[int, str]] class TypedThesaurusFactory(TypedDictFactory[TypedThesaurus]): __model__ = TypedThesaurus results = list(TypedThesaurusFactory.coverage()) assert len(results) == 2 example = TypedThesaurusFactory.build() for result in results: assert result.keys() == example.keys() def test_coverage_values_unique() -> None: @dataclass class Unique: uuid: UUID data: Union[int, str] class UniqueFactory(DataclassFactory[Unique]): __model__ = Unique results = list(UniqueFactory.coverage()) assert len(results) == 2 assert results[0].uuid != results[1].uuid def test_coverage_post_generated() -> None: @dataclass class Model: i: int j: int class Factory(DataclassFactory[Model]): __model__ = Model @post_generated @classmethod def i(cls, j: int) -> int: return j + 10 results = list(Factory.coverage()) assert len(results) == 1 assert results[0].i == results[0].j + 10 class CustomInt: def __init__(self, value: int) -> None: self.value = value def test_coverage_parameter_exception() -> None: @dataclass class Model: i: CustomInt class Factory(DataclassFactory[Model]): __model__ = Model with pytest.raises(ParameterException): list(Factory.coverage()) def test_coverage_optional_field() -> None: @dataclass class OptionalInt: i: Optional[int] class OptionalIntFactory(DataclassFactory[OptionalInt]): __model__ = OptionalInt results = list(OptionalIntFactory.coverage()) assert len(results) == 2 assert isinstance(results[0].i, int) assert results[1].i is None def type_exists_at_path_any(objs: Iterable, path: List[Union[int, str]], target_type: Type) -> bool: return any(type_exists_at_path(obj, path, target_type) for obj in objs) def type_exists_at_path(obj: Any, path: List[Union[int, str]], target_type: Type) -> bool: """Determine if a type exists at a path through a given object type_exists_at_path(obj, ["i", "*"], int) returns true if 'obj' contains an iterable attribute called 'i' with an 'int' value '*' is used to mean any of an iterable type_exists_at_path(obj, ["i", 5], int) returns true if 'obj' contains an iterable attribute called 'i' with an 'int' value at the index 5 Direct indexing is useful for checking tuples :param obj: Object to search through :param path: List of either indexes or attr keys to dereferrence :param target_type: Type to match :returns: A boolean, True if the type exists at the path, False otherwise """ # Handle fully dereferenced item and the end of path if len(path) == 0: return isinstance(obj, target_type) if path[0] == "*": if not isinstance(obj, Iterable): return False for piece in obj: if type_exists_at_path(piece, path[1:], target_type): return True return False item, success = get_or_index(obj, path[0]) if not success: return False return type_exists_at_path(item, path[1:], target_type) def get_or_index(obj: Any, idx: Union[int, str]) -> Tuple[Any, bool]: if isinstance(idx, str): if idx not in dir(obj): return None, False return getattr(obj, idx), True if len(obj) < idx: return None, False return obj[idx], True def test_coverage_optional_list() -> None: @dataclass class OptionalIntList: i: Optional[List[int]] class OptionalIntFactory(DataclassFactory[OptionalIntList]): __model__ = OptionalIntList results = list(OptionalIntFactory.coverage()) assert type_exists_at_path_any(results, ["i"], list) assert type_exists_at_path_any(results, ["i", "*"], int) assert type_exists_at_path_any(results, ["i"], NoneType) def test_optional_lists() -> None: class Model(BaseModel): just_a_list: List[int] optional_list: Optional[List[int]] optional_nested_list: Optional[List[List[List[int]]]] results = list(ModelFactory.create_factory(Model).coverage()) assert type_exists_at_path_any(results, ["just_a_list"], list) assert type_exists_at_path_any(results, ["optional_list"], list) assert type_exists_at_path_any(results, ["optional_list"], NoneType) assert type_exists_at_path_any(results, ["optional_nested_list"], NoneType) assert type_exists_at_path_any(results, ["optional_nested_list", "*"], list) assert type_exists_at_path_any(results, ["optional_nested_list", "*", "*"], list) assert type_exists_at_path_any(results, ["optional_nested_list", "*", "*", "*"], int) def test_tuple_types() -> None: class Model(BaseModel): tii: Tuple[int, int] results = list(ModelFactory.create_factory(Model).coverage()) assert type_exists_at_path_any(results, ["tii"], tuple) assert type_exists_at_path_any(results, ["tii", 0], int) assert type_exists_at_path_any(results, ["tii", 1], int) def test_hetero_tuple_types() -> None: class Model(BaseModel): tis: Tuple[int, str] results = list(ModelFactory.create_factory(Model).coverage()) assert type_exists_at_path_any(results, ["tis"], tuple) assert type_exists_at_path_any(results, ["tis", 0], int) assert type_exists_at_path_any(results, ["tis", 1], str) def test_optional_list_uuid() -> None: class Model(BaseModel): maybe_uuids: Optional[List[UUID]] results = list(ModelFactory.create_factory(Model).coverage()) assert type_exists_at_path_any(results, ["maybe_uuids"], list) assert type_exists_at_path_any(results, ["maybe_uuids", "*"], UUID) assert type_exists_at_path_any(results, ["maybe_uuids"], NoneType) def test_optional_set_uuid() -> None: class Model(BaseModel): maybe_uuids: Optional[Set[UUID]] results = list(ModelFactory.create_factory(Model).coverage()) assert type_exists_at_path_any(results, ["maybe_uuids"], set) assert type_exists_at_path_any(results, ["maybe_uuids", "*"], UUID) assert type_exists_at_path_any(results, ["maybe_uuids"], NoneType) @pytest.mark.skipif( IS_PYDANTIC_V1, reason="This should be possible but more work needs to be done", ) def test_optional_mixed_collecions() -> None: class Model(BaseModel): maybe_uuids: Optional[Union[Set[UUID], List[UUID]]] results = list(ModelFactory.create_factory(Model).coverage()) assert type_exists_at_path_any(results, ["maybe_uuids"], set) assert type_exists_at_path_any(results, ["maybe_uuids"], list) assert type_exists_at_path_any(results, ["maybe_uuids", "*"], UUID) assert type_exists_at_path_any(results, ["maybe_uuids"], NoneType) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/tests/test_typeddict_factory.py�������������������������������������������0000664�0000000�0000000�00000004001�14721310225�0023760�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from typing import Dict, List, Optional from annotated_types import Ge from typing_extensions import Annotated, NotRequired, Required, TypedDict from pydantic import BaseModel from polyfactory.factories import TypedDictFactory from polyfactory.factories.pydantic_factory import ModelFactory class TypedDictModel(TypedDict): id: int name: str list_field: List[Dict[str, int]] int_field: Optional[int] def test_factory_with_typeddict() -> None: class MyFactory(TypedDictFactory[TypedDictModel]): __model__ = TypedDictModel result = MyFactory.build() assert isinstance(result, dict) assert result["id"] assert result["name"] assert result["list_field"][0] assert type(result["int_field"]) in (type(None), int) def test_factory_model_with_typeddict_attribute_value() -> None: class MyModel(BaseModel): td: TypedDictModel name: str list_field: List[Dict[str, int]] int_field: Optional[int] class MyFactory(ModelFactory[MyModel]): __model__ = MyModel result = MyFactory.build() assert isinstance(result.td, dict) assert result.td["id"] assert result.td["name"] assert result.td["list_field"][0] assert type(result.td["int_field"]) in (type(None), int) def test_typeddict_with_required_and_non_required_fields() -> None: class TypedDictModel(TypedDict): id: Required[int] name: NotRequired[str] annotated: Required[Annotated[int, Ge(100)]] list_field: List[Dict[str, int]] optional_int: Required[Optional[int]] class TypedDictModelFactory(TypedDictFactory[TypedDictModel]): __model__ = TypedDictModel result = TypedDictModelFactory.build() assert isinstance(result["id"], int) assert isinstance(result["annotated"], int) assert result["annotated"] >= 100 assert isinstance(result["list_field"], list) assert isinstance(result["optional_int"], (type(None), int)) assert "name" in result assert isinstance(result["name"], str) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/tests/test_utils.py�������������������������������������������������������0000664�0000000�0000000�00000014065�14721310225�0021413�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������import random import sys from decimal import Decimal from typing import Any, NewType, Union import pytest from hypothesis import given from hypothesis.strategies import decimals, floats, integers from pydantic import BaseModel from polyfactory.factories.pydantic_factory import ModelFactory from polyfactory.utils.helpers import unwrap_new_type from polyfactory.utils.predicates import is_new_type, is_union from polyfactory.value_generators.constrained_numbers import ( is_multiply_of_multiple_of_in_range, ) def test_is_union() -> None: class UnionTest(BaseModel): union: Union[int, str] no_union: Any class UnionTestFactory(ModelFactory): __model__ = UnionTest for field_meta in UnionTestFactory.get_model_fields(): if field_meta.name == "union": assert is_union(field_meta.annotation) else: assert not is_union(field_meta.annotation) # for python 3.10 we need to run the test as well with the union_pipe operator if sys.version_info >= (3, 10): class UnionTestWithPipe(BaseModel): union_pipe: int | str | None # Pipe syntax supported from Python 3.10 onwards union_normal: Union[int, str] no_union: Any class UnionTestWithPipeFactory(ModelFactory): __model__ = UnionTestWithPipe for field_meta in UnionTestWithPipeFactory.get_model_fields(): if field_meta.name in ("union_pipe", "union_normal"): assert is_union(field_meta.annotation) else: assert not is_union(field_meta.annotation) def test_is_new_type() -> None: assert is_new_type(NewType("MyInt", int)) assert not is_new_type(int) def test_unwrap_new_type_is_needed() -> None: MyInt = NewType("MyInt", int) WrappedInt = NewType("WrappedInt", MyInt) assert unwrap_new_type(MyInt) is int assert unwrap_new_type(WrappedInt) is int assert unwrap_new_type(int) is int def test_is_multiply_of_multiple_of_in_range_extreme_cases() -> None: assert is_multiply_of_multiple_of_in_range(minimum=0.0, maximum=10.0, multiple_of=20.0) assert not is_multiply_of_multiple_of_in_range(minimum=5.0, maximum=10.0, multiple_of=20.0) assert is_multiply_of_multiple_of_in_range(minimum=1.0, maximum=1.0, multiple_of=0.33333333333) assert is_multiply_of_multiple_of_in_range( minimum=Decimal(1), maximum=Decimal(1), multiple_of=Decimal("0.33333333333"), ) assert not is_multiply_of_multiple_of_in_range(minimum=Decimal(1), maximum=Decimal(1), multiple_of=Decimal("0.333")) assert is_multiply_of_multiple_of_in_range(minimum=5, maximum=5, multiple_of=5) # while multiple_of=0.0 leads to ZeroDivision exception in pydantic # it can handle values close to zero properly, so we should support this too assert is_multiply_of_multiple_of_in_range(minimum=10.0, maximum=20.0, multiple_of=1e-10) # test corner case found by peterschutt assert not is_multiply_of_multiple_of_in_range( minimum=Decimal("999999999.9999999343812775"), maximum=Decimal("999999999.990476"), multiple_of=Decimal("-0.556"), ) @given( floats(allow_nan=False, allow_infinity=False, min_value=1e-6, max_value=1000000000), integers(min_value=-100000, max_value=100000), ) def test_is_multiply_of_multiple_of_in_range_for_floats(base_multiple_of: float, multiplier: int) -> None: if multiplier != 0: for multiple_of in [base_multiple_of, -base_multiple_of]: minimum, maximum = sorted( [ multiplier * multiple_of + random.random() * 100, (multiplier + random.randint(1, 100)) * multiple_of + random.random() * 100, ], ) assert is_multiply_of_multiple_of_in_range(minimum=minimum, maximum=maximum, multiple_of=multiple_of) minimum, maximum = sorted( [ (multiplier + (random.random() / 2 + 0.01)) * multiple_of, (multiplier + (random.random() / 2 + 0.45)) * multiple_of, ], ) assert not is_multiply_of_multiple_of_in_range(minimum=minimum, maximum=maximum, multiple_of=multiple_of) @given( integers(min_value=-1000000000, max_value=1000000000), integers(min_value=-100000, max_value=100000), ) def test_is_multiply_of_multiple_of_in_range_for_int(base_multiple_of: int, multiplier: int) -> None: if multiplier != 0 and base_multiple_of not in [-1, 0, 1]: for multiple_of in [base_multiple_of, -base_multiple_of]: minimum, maximum = sorted( [ multiplier * multiple_of + random.randint(1, 100), (multiplier + random.randint(1, 100)) * multiple_of + random.randint(1, 100), ], ) assert is_multiply_of_multiple_of_in_range(minimum=minimum, maximum=maximum, multiple_of=multiple_of) @pytest.mark.skip(reason="fails on edge cases") @given( decimals(min_value=Decimal("-1000000000"), max_value=Decimal("1000000000")), integers(min_value=-100000, max_value=100000), ) def test_is_multiply_of_multiple_of_in_range_for_decimals(base_multiple_of: Decimal, multiplier: int) -> None: if multiplier != 0 and base_multiple_of != 0: for multiple_of in [base_multiple_of, -base_multiple_of]: minimum, maximum = sorted( [ multiplier * multiple_of + Decimal(random.random() * 100), (multiplier + random.randint(1, 100)) * multiple_of + Decimal(random.random() * 100), ], ) assert is_multiply_of_multiple_of_in_range(minimum=minimum, maximum=maximum, multiple_of=multiple_of) minimum, maximum = sorted( [ (multiplier + Decimal(random.random() / 2 + 0.01)) * multiple_of, (multiplier + Decimal(random.random() / 2 + 0.45)) * multiple_of, ], ) assert not is_multiply_of_multiple_of_in_range(minimum=minimum, maximum=maximum, multiple_of=multiple_of) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/tests/typing_test_strict.py�����������������������������������������������0000664�0000000�0000000�00000001705�14721310225�0023152�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������"""Module exists only to test generic boundaries. Filename should not start with "test_". """ import dataclasses from typing import TypedDict import pydantic.dataclasses from pydantic import BaseModel from polyfactory.factories import DataclassFactory, TypedDictFactory from polyfactory.factories.pydantic_factory import ModelFactory class PydanticClass(BaseModel): field: str class PydanticClassFactory(ModelFactory[PydanticClass]): __model__ = PydanticClass @pydantic.dataclasses.dataclass class PydanticDataClass: field: str class PydanticDataClassFactory(DataclassFactory[PydanticDataClass]): __model__ = PydanticDataClass @dataclasses.dataclass() class PythonDataClass: field: str class PythonDataClassFactory(DataclassFactory[PythonDataClass]): __model__ = PythonDataClass class TypedDictClass(TypedDict): field: str class TypedDictClassFactory(TypedDictFactory[TypedDictClass]): __model__ = TypedDictClass �����������������������������������������������������������python-polyfactory-2.18.1/tests/utils/��������������������������������������������������������������0000775�0000000�0000000�00000000000�14721310225�0017774�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/tests/utils/test_deprecation.py�������������������������������������������0000664�0000000�0000000�00000000776�14721310225�0023714�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from __future__ import annotations import pytest from polyfactory.utils.deprecation import check_for_deprecated_parameters def test_parameter_deprecation() -> None: def my_func(a: int, b: int | None = None) -> None: check_for_deprecated_parameters("5", parameters=(("b", b),)) with pytest.warns( DeprecationWarning, match="Use of deprecated parameter 'b'. Deprecated in polyfactory 5. This parameter will be removed in the next major version", ): my_func(1, 2) ��python-polyfactory-2.18.1/tests/utils/test_frozendict.py��������������������������������������������0000664�0000000�0000000�00000000524�14721310225�0023555�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������import pytest from polyfactory.utils.types import Frozendict def test_frozendict_immutable() -> None: instance = Frozendict({"bar": "foo"}) with pytest.raises(TypeError, match="Unable to mutate Frozendict"): instance["foo"] = "bar" def test_frozendict_hashable() -> None: assert isinstance(hash(Frozendict()), int) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/tools/��������������������������������������������������������������������0000775�0000000�0000000�00000000000�14721310225�0016632�5����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������python-polyfactory-2.18.1/tools/build_docs.py�������������������������������������������������������0000664�0000000�0000000�00000002622�14721310225�0021315�0����������������������������������������������������������������������������������������������������ustar�00root����������������������������root����������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������from __future__ import annotations import argparse import shutil import subprocess from contextlib import contextmanager from pathlib import Path REDIRECT_TEMPLATE = """ <!DOCTYPE HTML> <html lang="en-US"> <head> <title>Page Redirection You are being redirected. If this does not work, click this link """ parser = argparse.ArgumentParser() parser.add_argument("output") @contextmanager def checkout(branch: str) -> None: subprocess.run(["git", "checkout", branch], check=True) # noqa: S603 S607 yield subprocess.run(["git", "checkout", "-"], check=True) # noqa: S603 S607 def build(output_dir: str) -> None: subprocess.run(["make", "docs"], check=True) # noqa: S603 S607 output_dir = Path(output_dir) output_dir.mkdir() output_dir.joinpath(".nojekyll").touch(exist_ok=True) output_dir.joinpath("index.html").write_text(REDIRECT_TEMPLATE.format(target="latest")) docs_src_path = Path("docs/_build/html") shutil.copytree(docs_src_path, output_dir / "latest", dirs_exist_ok=True) def main() -> None: args = parser.parse_args() build(output_dir=args.output) if __name__ == "__main__": main() python-polyfactory-2.18.1/tools/convert_docs.sh000077500000000000000000000002721472131022500216620ustar00rootroot00000000000000#!/bin/bash CHANGELOG=docs/changelog.rst filename="${CHANGELOG%.*}" echo "Converting $CHANGELOG to $filename.md" pandoc --wrap=preserve $CHANGELOG -f rst -t markdown -o "$filename".md