pax_global_header00006660000000000000000000000064151044607450014520gustar00rootroot0000000000000052 comment=a6b2d3869f24c9c04cd7c024e59ccec3e5422a56 annotated-doc-0.0.4/000077500000000000000000000000001510446074500142415ustar00rootroot00000000000000annotated-doc-0.0.4/.github/000077500000000000000000000000001510446074500156015ustar00rootroot00000000000000annotated-doc-0.0.4/.github/DISCUSSION_TEMPLATE/000077500000000000000000000000001510446074500205575ustar00rootroot00000000000000annotated-doc-0.0.4/.github/DISCUSSION_TEMPLATE/questions.yml000066400000000000000000000101761510446074500233410ustar00rootroot00000000000000labels: [question] body: - type: markdown attributes: value: | Thanks for your interest in the project! 🚀 Please follow these instructions, fill every question, and do every step. 🙏 I'm asking this because answering questions and solving problems in GitHub is what consumes most of the time. I end up not being able to add new features, fix bugs, review pull requests, etc. as fast as I wish because I have to spend too much time handling questions. By asking questions in a structured way (following this) it will be much easier to help you. And there's a high chance that you will find the solution along the way and you won't even have to submit it and wait for an answer. 😎 As there are too many questions, I'll have to discard and close the incomplete ones. That will allow me (and others) to focus on helping people like you that follow the whole process and help us help you. 🤓 - type: checkboxes id: checks attributes: label: First Check description: Please confirm and check all the following options. options: - label: I added a very descriptive title here. required: true - label: I used the GitHub search to find a similar question and didn't find it. required: true - label: I already searched in Google "How to X with annotated-doc" and didn't find any information. required: true - label: I already read and followed all the tutorial in the docs and didn't find an answer. required: true - label: I already checked if it is not related to annotated-doc but to [FastAPI](https://github.com/fastapi/fastapi) or another specific project. required: true - type: textarea id: example attributes: label: Example Code description: | Please add a self-contained, [minimal, reproducible, example](https://stackoverflow.com/help/minimal-reproducible-example) with your use case. If I (or someone) can copy it, run it, and see it right away, there's a much higher chance I (or someone) will be able to help you. placeholder: | from typing import Annotated from annotated_doc import Doc def hi(name: Annotated[str, Doc("Who to say hi to")]) -> None: print(f"Hi!") render: python validations: required: true - type: textarea id: description attributes: label: Description description: | What is the problem, question, or error? Write a short description telling me what you are doing, what you expect to happen, and what is currently happening. placeholder: | * Create a function with one parameter documented with annotated-doc. * Call the function with the parameter. * I expected the code to do what the docs say, but it doesn't unless I implement that code. validations: required: true - type: dropdown id: os attributes: label: Operating System description: What operating system are you on? multiple: true options: - Linux - Windows - macOS - Other validations: required: true - type: textarea id: os-details attributes: label: Operating System Details description: You can add more details about your operating system here, in particular if you chose "Other". - type: input id: version attributes: label: Version description: | What version are you using? You can find the version with: ```bash python -c "import annotated_doc; print(annotated_doc.__version__)" ``` validations: required: true - type: input id: python-version attributes: label: Python Version description: | What Python version are you using? You can find the Python version with: ```bash python --version ``` validations: required: true - type: textarea id: context attributes: label: Additional Context description: Add any additional context information or screenshots you think are useful. annotated-doc-0.0.4/.github/FUNDING.yml000066400000000000000000000000231510446074500174110ustar00rootroot00000000000000github: [tiangolo] annotated-doc-0.0.4/.github/ISSUE_TEMPLATE/000077500000000000000000000000001510446074500177645ustar00rootroot00000000000000annotated-doc-0.0.4/.github/ISSUE_TEMPLATE/config.yml000066400000000000000000000014171510446074500217570ustar00rootroot00000000000000blank_issues_enabled: false contact_links: - name: Security Contact about: Please report security vulnerabilities to security@tiangolo.com - name: Question or Problem about: Ask a question or ask about a problem in GitHub Discussions. url: https://github.com/fastapi/annotated-doc/discussions/categories/questions - name: Feature Request about: To suggest an idea or ask about a feature, please start with a question saying what you would like to achieve. There might be a way to do it already. url: https://github.com/fastapi/annotated-doc/discussions/categories/questions - name: Show and tell about: Show what you built with annotated-doc and where you use it. url: https://github.com/fastapi/annotated-doc/discussions/categories/show-and-tell annotated-doc-0.0.4/.github/ISSUE_TEMPLATE/privileged.yml000066400000000000000000000016041510446074500226420ustar00rootroot00000000000000name: Privileged description: You are @tiangolo or he asked you directly to create an issue here. If not, check the other options. 👇 body: - type: markdown attributes: value: | Thanks for your interest in annotated-doc! 🚀 If you are not @tiangolo or he didn't ask you directly to create an issue here, please start the conversation in a [Question in GitHub Discussions](https://github.com/fastapi/annotated-doc/discussions/categories/questions) instead. - type: checkboxes id: privileged attributes: label: Privileged issue description: Confirm that you are allowed to create an issue here. options: - label: I'm @tiangolo or he asked me directly to create an issue here. required: true - type: textarea id: content attributes: label: Issue Content description: Add the content of the issue here. annotated-doc-0.0.4/.github/dependabot.yml000066400000000000000000000004661510446074500204370ustar00rootroot00000000000000version: 2 updates: # GitHub Actions - package-ecosystem: "github-actions" directory: "/" schedule: interval: "daily" commit-message: prefix: ⬆ # Python - package-ecosystem: "uv" directory: "/" schedule: interval: "monthly" commit-message: prefix: ⬆ annotated-doc-0.0.4/.github/labeler.yml000066400000000000000000000003671510446074500177400ustar00rootroot00000000000000internal: - all: - changed-files: - any-glob-to-any-file: - .github/** - scripts/** - .gitignore - .pre-commit-config.yaml - all-globs-to-all-files: - '!src/**' - '!pyproject.toml' annotated-doc-0.0.4/.github/workflows/000077500000000000000000000000001510446074500176365ustar00rootroot00000000000000annotated-doc-0.0.4/.github/workflows/add-to-project.yml000066400000000000000000000005701510446074500231770ustar00rootroot00000000000000name: Add to Project on: pull_request_target: issues: types: - opened - reopened jobs: add-to-project: name: Add to project runs-on: ubuntu-latest steps: - uses: actions/add-to-project@v1.0.2 with: project-url: https://github.com/orgs/fastapi/projects/2 github-token: ${{ secrets.FASTAPI_PROJECTS_TOKEN }} annotated-doc-0.0.4/.github/workflows/detect-conflicts.yml000066400000000000000000000007631510446074500236210ustar00rootroot00000000000000name: Conflict detector on: push: pull_request_target: types: - synchronize jobs: main: permissions: contents: read pull-requests: write runs-on: ubuntu-latest steps: - name: Check if PRs have merge conflicts uses: eps1lon/actions-label-merge-conflict@v3 with: dirtyLabel: conflicts repoToken: "${{ secrets.GITHUB_TOKEN }}" commentOnDirty: This pull request has a merge conflict that needs to be resolved. annotated-doc-0.0.4/.github/workflows/issue-manager.yml000066400000000000000000000030651510446074500231250ustar00rootroot00000000000000name: Issue Manager on: schedule: - cron: "13 22 * * *" issue_comment: types: - created issues: types: - labeled pull_request_target: types: - labeled workflow_dispatch: permissions: issues: write pull-requests: write jobs: issue-manager: if: github.repository_owner == 'fastapi' runs-on: ubuntu-latest steps: - name: Dump GitHub context env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - uses: tiangolo/issue-manager@0.6.0 with: token: ${{ secrets.GITHUB_TOKEN }} config: > { "answered": { "delay": 864000, "message": "Assuming the original need was handled, this will be automatically closed now. But feel free to add more comments or create new issues or PRs." }, "waiting": { "delay": 2628000, "message": "As this PR has been waiting for the original user for a while but seems to be inactive, it's now going to be closed. But if there's anyone interested, feel free to create a new PR.", "reminder": { "before": "P3D", "message": "Heads-up: this will be closed in 3 days unless there's new activity." } }, "invalid": { "delay": 0, "message": "This was marked as invalid and will be closed now. If this is an error, please provide additional details." } } annotated-doc-0.0.4/.github/workflows/labeler.yml000066400000000000000000000014741510446074500217750ustar00rootroot00000000000000name: Labels on: pull_request_target: types: - opened - synchronize - reopened # For label-checker - labeled - unlabeled jobs: labeler: permissions: contents: read pull-requests: write runs-on: ubuntu-latest steps: - uses: actions/labeler@v6 if: ${{ github.event.action != 'labeled' && github.event.action != 'unlabeled' }} - run: echo "Done adding labels" # Run this after labeler applied labels check-labels: needs: - labeler permissions: pull-requests: read runs-on: ubuntu-latest steps: - uses: docker://agilepathway/pull-request-label-checker:latest with: one_of: breaking,security,feature,bug,refactor,upgrade,docs,lang-all,internal repo_token: ${{ secrets.GITHUB_TOKEN }} annotated-doc-0.0.4/.github/workflows/latest-changes.yml000066400000000000000000000024661510446074500232730ustar00rootroot00000000000000name: Latest Changes on: pull_request_target: branches: - main types: - closed workflow_dispatch: inputs: number: description: PR number required: true debug_enabled: description: 'Run the build with tmate debugging enabled (https://github.com/marketplace/actions/debugging-with-tmate)' required: false default: 'false' jobs: latest-changes: runs-on: ubuntu-latest steps: - name: Dump GitHub context env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - uses: actions/checkout@v5 with: # To allow latest-changes to commit to the main branch token: ${{ secrets.ANNOTATED_DOC_LATEST_CHANGES }} # Allow debugging with tmate - name: Setup tmate session uses: mxschmitt/action-tmate@v3 if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.debug_enabled == 'true' }} with: limit-access-to-actor: true - uses: tiangolo/latest-changes@0.4.0 with: token: ${{ secrets.GITHUB_TOKEN }} latest_changes_file: release-notes.md latest_changes_header: '## Latest Changes' end_regex: '^## ' debug_logs: true label_header_prefix: '### ' annotated-doc-0.0.4/.github/workflows/publish.yml000066400000000000000000000013771510446074500220370ustar00rootroot00000000000000name: Publish on: release: types: - created jobs: publish: runs-on: ubuntu-latest permissions: id-token: write steps: - name: Dump GitHub context env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - uses: actions/checkout@v5 - name: Set up Python uses: actions/setup-python@v6 with: python-version: "3.10" - name: Install build dependencies run: pip install build - name: Build distribution run: python -m build - name: Publish uses: pypa/gh-action-pypi-publish@v1.13.0 - name: Dump GitHub context env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" annotated-doc-0.0.4/.github/workflows/smokeshow.yml000066400000000000000000000034041510446074500224010ustar00rootroot00000000000000name: Smokeshow on: workflow_run: workflows: - Test types: - completed permissions: statuses: write env: UV_SYSTEM_PYTHON: 1 jobs: smokeshow: if: ${{ github.event.workflow_run.conclusion == 'success' }} runs-on: ubuntu-latest steps: - name: Dump GitHub context env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - uses: actions/checkout@v5 - uses: actions/setup-python@v6 with: python-version: '3.9' - name: Setup uv uses: astral-sh/setup-uv@v7 with: version: "0.4.15" enable-cache: true cache-dependency-glob: | requirements**.txt pyproject.toml - run: uv pip install -r requirements-tests.txt - uses: actions/download-artifact@v6 with: name: coverage-html path: htmlcov github-token: ${{ secrets.GITHUB_TOKEN }} run-id: ${{ github.event.workflow_run.id }} # Try 5 times to upload coverage to smokeshow - name: Upload coverage to Smokeshow run: | for i in 1 2 3 4 5; do if smokeshow upload htmlcov; then echo "Smokeshow upload success!" break fi echo "Smokeshow upload error, sleep 1 sec and try again." sleep 1 done env: SMOKESHOW_GITHUB_STATUS_DESCRIPTION: Coverage {coverage-percentage} SMOKESHOW_GITHUB_COVERAGE_THRESHOLD: 100 SMOKESHOW_GITHUB_CONTEXT: coverage SMOKESHOW_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} SMOKESHOW_GITHUB_PR_HEAD_SHA: ${{ github.event.workflow_run.head_sha }} SMOKESHOW_AUTH_KEY: ${{ secrets.SMOKESHOW_AUTH_KEY }} annotated-doc-0.0.4/.github/workflows/test-redistribute.yml000066400000000000000000000030331510446074500240420ustar00rootroot00000000000000name: Test Redistribute on: push: branches: - main pull_request: types: - opened - synchronize env: UV_SYSTEM_PYTHON: 1 jobs: test-redistribute: runs-on: ubuntu-latest steps: - name: Dump GitHub context env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - uses: actions/checkout@v5 - name: Set up Python uses: actions/setup-python@v6 with: python-version: "3.10" - name: Install build dependencies run: pip install build - name: Build source distribution run: python -m build --sdist - name: Decompress source distribution run: | cd dist tar xvf annotated_doc*.tar.gz - name: Install test dependencies run: | cd dist/annotated_doc*/ pip install -r requirements-tests.txt - name: Run source distribution tests run: | cd dist/annotated_doc*/ bash scripts/test.sh - name: Build wheel distribution run: | cd dist pip wheel --no-deps annotated_doc*.tar.gz # https://github.com/marketplace/actions/alls-green#why test-redistribute-alls-green: # This job does nothing and is only used for the branch protection if: always() needs: - test-redistribute runs-on: ubuntu-latest steps: - name: Decide whether the needed jobs succeeded or failed uses: re-actors/alls-green@release/v1 with: jobs: ${{ toJSON(needs) }} annotated-doc-0.0.4/.github/workflows/test.yml000066400000000000000000000100341510446074500213360ustar00rootroot00000000000000name: Test on: push: branches: - main pull_request: types: - opened - synchronize workflow_dispatch: inputs: debug_enabled: description: 'Run the build with tmate debugging enabled (https://github.com/marketplace/actions/debugging-with-tmate)' required: false default: 'false' schedule: # cron every week on monday - cron: "0 0 * * 1" env: UV_SYSTEM_PYTHON: 1 jobs: test: strategy: matrix: os: - ubuntu-latest - windows-latest - macos-latest python-version: - "3.14" include: - os: macos-latest python-version: "3.8" - os: windows-latest python-version: "3.9" - os: ubuntu-latest python-version: "3.10" - os: macos-latest python-version: "3.11" - os: windows-latest python-version: "3.12" - os: ubuntu-latest python-version: "3.13" - os: macos-latest python-version: "3.13" fail-fast: false runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v5 - name: Set up Python uses: actions/setup-python@v6 with: python-version: ${{ matrix.python-version }} - name: Setup uv uses: astral-sh/setup-uv@v7 with: version: "0.4.15" enable-cache: true cache-dependency-glob: | requirements**.txt pyproject.toml # Allow debugging with tmate - name: Setup tmate session uses: mxschmitt/action-tmate@v3 if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.debug_enabled == 'true' }} with: limit-access-to-actor: true - name: Install Dependencies run: uv pip install -r requirements-tests.txt - name: Lint run: bash scripts/lint.sh - run: mkdir coverage - name: Test run: bash scripts/test.sh env: COVERAGE_FILE: coverage/.coverage.${{ runner.os }}-py${{ matrix.python-version }} CONTEXT: ${{ runner.os }}-py${{ matrix.python-version }} - name: Store coverage files uses: actions/upload-artifact@v5 with: name: coverage-${{ runner.os }}-${{ matrix.python-version }} path: coverage include-hidden-files: true coverage-combine: needs: - test runs-on: ubuntu-latest steps: - uses: actions/checkout@v5 - uses: actions/setup-python@v6 with: python-version: '3.13' - name: Setup uv uses: astral-sh/setup-uv@v7 with: version: "0.4.15" enable-cache: true cache-dependency-glob: | requirements**.txt pyproject.toml - name: Get coverage files uses: actions/download-artifact@v6 with: pattern: coverage-* path: coverage merge-multiple: true # Allow debugging with tmate - name: Setup tmate session uses: mxschmitt/action-tmate@v3 if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.debug_enabled == 'true' }} with: limit-access-to-actor: true - name: Install Dependencies run: uv pip install -r requirements-tests.txt - run: ls -la coverage - run: coverage combine coverage - run: coverage report - run: coverage html --title "Coverage for ${{ github.sha }}" - name: Store coverage HTML uses: actions/upload-artifact@v5 with: name: coverage-html path: htmlcov include-hidden-files: true # https://github.com/marketplace/actions/alls-green#why alls-green: # This job does nothing and is only used for the branch protection if: always() needs: - coverage-combine runs-on: ubuntu-latest steps: - name: Decide whether the needed jobs succeeded or failed uses: re-actors/alls-green@release/v1 with: jobs: ${{ toJSON(needs) }} annotated-doc-0.0.4/.gitignore000066400000000000000000000002141510446074500162260ustar00rootroot00000000000000# Python-generated files __pycache__/ *.py[oc] build/ dist/ wheels/ *.egg-info # Virtual environments .venv # Coverage htmlcov .coverage* annotated-doc-0.0.4/.pre-commit-config.yaml000066400000000000000000000013361510446074500205250ustar00rootroot00000000000000# See https://pre-commit.com for more information # See https://pre-commit.com/hooks.html for more hooks default_language_version: python: python3.10 repos: - repo: https://github.com/pre-commit/pre-commit-hooks rev: v6.0.0 hooks: - id: check-added-large-files - id: check-toml - id: check-yaml args: - --unsafe - id: end-of-file-fixer - id: trailing-whitespace - repo: https://github.com/astral-sh/ruff-pre-commit rev: v0.13.3 hooks: - id: ruff args: - --fix - id: ruff-format ci: autofix_commit_msg: 🎨 [pre-commit.ci] Auto format from pre-commit.com hooks autoupdate_commit_msg: ⬆ [pre-commit.ci] pre-commit autoupdate annotated-doc-0.0.4/CITATION.cff000066400000000000000000000012461510446074500161360ustar00rootroot00000000000000# This CITATION.cff file was generated with cffinit. # Visit https://bit.ly/cffinit to generate yours today! cff-version: 1.2.0 title: annotated-doc message: >- If you use this software, please cite it using the metadata from this file. type: software authors: - given-names: Sebastián family-names: Ramírez email: tiangolo@gmail.com identifiers: repository-code: 'https://github.com/fastapi/annotated-doc' url: 'https://github.com/fastapi/annotated-doc' abstract: >- Document parameters, class attributes, return types, and variables inline, with Annotated. keywords: - annotated - documentation - fastapi - typer - sqlmodel - asyncer license: MIT annotated-doc-0.0.4/LICENSE000066400000000000000000000020761510446074500152530ustar00rootroot00000000000000The MIT License (MIT) Copyright (c) 2025 Sebastián Ramírez 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. annotated-doc-0.0.4/README.md000066400000000000000000000113221510446074500155170ustar00rootroot00000000000000# Annotated Doc Document parameters, class attributes, return types, and variables inline, with `Annotated`. Test Coverage Package version Supported Python versions ## Installation ```bash pip install annotated-doc ``` Or with `uv`: ```Python uv add annotated-doc ``` ## Usage Import `Doc` and pass a single literal string with the documentation for the specific parameter, class attribute, return type, or variable. For example, to document a parameter `name` in a function `hi` you could do: ```Python from typing import Annotated from annotated_doc import Doc def hi(name: Annotated[str, Doc("Who to say hi to")]) -> None: print(f"Hi, {name}!") ``` You can also use it to document class attributes: ```Python from typing import Annotated from annotated_doc import Doc class User: name: Annotated[str, Doc("The user's name")] age: Annotated[int, Doc("The user's age")] ``` The same way, you could document return types and variables, or anything that could have a type annotation with `Annotated`. ## Who Uses This `annotated-doc` was made for: * [FastAPI](https://fastapi.tiangolo.com/) * [Typer](https://typer.tiangolo.com/) * [SQLModel](https://sqlmodel.tiangolo.com/) * [Asyncer](https://asyncer.tiangolo.com/) `annotated-doc` is supported by [griffe-typingdoc](https://github.com/mkdocstrings/griffe-typingdoc), which powers reference documentation like the one in the [FastAPI Reference](https://fastapi.tiangolo.com/reference/). ## Reasons not to use `annotated-doc` You are already comfortable with one of the existing docstring formats, like: * Sphinx * numpydoc * Google * Keras Your team is already comfortable using them. You prefer having the documentation about parameters all together in a docstring, separated from the code defining them. You care about a specific set of users, using one specific editor, and that editor already has support for the specific docstring format you use. ## Reasons to use `annotated-doc` * No micro-syntax to learn for newcomers, it’s **just Python** syntax. * **Editing** would be already fully supported by default by any editor (current or future) supporting Python syntax, including syntax errors, syntax highlighting, etc. * **Rendering** would be relatively straightforward to implement by static tools (tools that don't need runtime execution), as the information can be extracted from the AST they normally already create. * **Deduplication of information**: the name of a parameter would be defined in a single place, not duplicated inside of a docstring. * **Elimination** of the possibility of having **inconsistencies** when removing a parameter or class variable and **forgetting to remove** its documentation. * **Minimization** of the probability of adding a new parameter or class variable and **forgetting to add its documentation**. * **Elimination** of the possibility of having **inconsistencies** between the **name** of a parameter in the **signature** and the name in the docstring when it is renamed. * **Access** to the documentation string for each symbol at **runtime**, including existing (older) Python versions. * A more formalized way to document other symbols, like type aliases, that could use Annotated. * **Support** for apps using FastAPI, Typer and others. * **AI Accessibility**: AI tools will have an easier way understanding each parameter as the distance from documentation to parameter is much closer. ## History I ([@tiangolo](https://github.com/tiangolo)) originally wanted for this to be part of the Python standard library (in [PEP 727](https://peps.python.org/pep-0727/)), but the proposal was withdrawn as there was a fair amount of negative feedback and opposition. The conclusion was that this was better done as an external effort, in a third-party library. So, here it is, with a simpler approach, as a third-party library, in a way that can be used by others, starting with FastAPI and friends. ## License This project is licensed under the terms of the MIT license. annotated-doc-0.0.4/pyproject.toml000066400000000000000000000055431510446074500171640ustar00rootroot00000000000000[project] name = "annotated-doc" dynamic = ["version"] license = "MIT" license-files = ["LICENSE"] description = "Document parameters, class attributes, return types, and variables inline, with Annotated." readme = "README.md" authors = [ { name = "Sebastián Ramírez", email = "tiangolo@gmail.com" } ] requires-python = ">=3.8" classifiers = [ "Intended Audience :: Information Technology", "Intended Audience :: System Administrators", "Operating System :: OS Independent", "Programming Language :: Python :: 3", "Programming Language :: Python", "Topic :: Internet", "Topic :: Software Development :: Libraries :: Application Frameworks", "Topic :: Software Development :: Libraries :: Python Modules", "Topic :: Software Development :: Libraries", "Topic :: Software Development", "Typing :: Typed", "Development Status :: 4 - Beta", "Intended Audience :: Developers", "Programming Language :: Python :: 3 :: Only", "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 :: 3.13", "Programming Language :: Python :: 3.14", ] dependencies = [] [project.urls] Homepage = "https://github.com/fastapi/annotated-doc" Documentation = "https://github.com/fastapi/annotated-doc" Repository = "https://github.com/fastapi/annotated-doc" Issues = "https://github.com/fastapi/annotated-doc/issues" Changelog = "https://github.com/fastapi/annotated-doc/release-notes.md" [build-system] requires = ["pdm-backend"] build-backend = "pdm.backend" [tool.mypy] strict = true [tool.pytest.ini_options] addopts = [ "--strict-config", "--strict-markers", ] xfail_strict = true junit_family = "xunit2" [tool.coverage.run] parallel = true data_file = "coverage/.coverage" source = [ "src/annotated_doc", "tests", ] context = '${CONTEXT}' dynamic_context = "test_function" relative_files = true [tool.coverage.report] show_missing = true sort = "-Cover" [tool.coverage.html] show_contexts = true [tool.ruff.lint] select = [ "E", # pycodestyle errors "W", # pycodestyle warnings "F", # pyflakes "I", # isort "B", # flake8-bugbear "C4", # flake8-comprehensions "UP", # pyupgrade ] ignore = [ "E501", # line too long, handled by black "B008", # do not perform function calls in argument defaults "C901", # too complex "W191", # indentation contains tabs ] [tool.ruff.lint.pyupgrade] # Preserve types, even if a file imports `from __future__ import annotations`. keep-runtime-typing = true [tool.pdm] version = { source = "file", path = "src/annotated_doc/__init__.py" } distribution = true [tool.pdm.build] source-includes = [ "tests/", "requirements*.txt", "scripts/", ] annotated-doc-0.0.4/release-notes.md000066400000000000000000000044501510446074500173340ustar00rootroot00000000000000# Release Notes ## Latest Changes ## 0.0.4 ### Fixes * 👷 Switch to dynamic versioning with `pdm` build system. PR [#19](https://github.com/fastapi/annotated-doc/pull/19) by [@svlandeg](https://github.com/svlandeg). ### Upgrades * ⬆ Bump ruff from 0.14.1 to 0.14.3. PR [#17](https://github.com/fastapi/annotated-doc/pull/17) by [@dependabot[bot]](https://github.com/apps/dependabot). ### Internal * ➕ Add `typing-extensions` to test requirements for Python < 3.9. PR [#12](https://github.com/fastapi/annotated-doc/pull/12) by [@musicinmybrain](https://github.com/musicinmybrain). * ⬆ Bump actions/upload-artifact from 4 to 5. PR [#14](https://github.com/fastapi/annotated-doc/pull/14) by [@dependabot[bot]](https://github.com/apps/dependabot). * ⬆ Bump actions/download-artifact from 5 to 6. PR [#13](https://github.com/fastapi/annotated-doc/pull/13) by [@dependabot[bot]](https://github.com/apps/dependabot). ## 0.0.3 ### Docs * 📝 Add mention to `griffe-typingdoc`. PR [#10](https://github.com/fastapi/annotated-doc/pull/10) by [@tiangolo](https://github.com/tiangolo). * 📝 Update README with use cases. PR [#9](https://github.com/fastapi/annotated-doc/pull/9) by [@tiangolo](https://github.com/tiangolo). * 📝 Add badges to docs. PR [#8](https://github.com/fastapi/annotated-doc/pull/8) by [@tiangolo](https://github.com/tiangolo). ### Internal * 🔧 Add PEP-639 license metadata. PR [#11](https://github.com/fastapi/annotated-doc/pull/11) by [@bollwyvl](https://github.com/bollwyvl). ## 0.0.2 ### Features * ✨ Add implementation. ### Internal * ✅ Migrate/add tests. PR [#7](https://github.com/fastapi/annotated-doc/pull/7) by [@tiangolo](https://github.com/tiangolo). * 👷 Add setup to run tests on CI. PR [#6](https://github.com/fastapi/annotated-doc/pull/6) by [@tiangolo](https://github.com/tiangolo). * 👷 Add templates and admin CI workflows. PR [#3](https://github.com/fastapi/annotated-doc/pull/3) by [@tiangolo](https://github.com/tiangolo). * 🔧 Add configs for `.github`. PR [#1](https://github.com/fastapi/annotated-doc/pull/1) by [@tiangolo](https://github.com/tiangolo). * 🔧 Update latest-changes config to point to `main` as the main branch. PR [#2](https://github.com/fastapi/annotated-doc/pull/2) by [@tiangolo](https://github.com/tiangolo). ## 0.0.1 Reserve PyPI package. annotated-doc-0.0.4/requirements-tests.txt000066400000000000000000000002041510446074500206610ustar00rootroot00000000000000-e . pytest >=8.3.5 typing-extensions; python_version < "3.9" coverage[toml] >=7.6.1 mypy ==1.14.1 ruff ==0.14.3 smokeshow >=0.5.0 annotated-doc-0.0.4/scripts/000077500000000000000000000000001510446074500157305ustar00rootroot00000000000000annotated-doc-0.0.4/scripts/coverage.sh000077500000000000000000000001231510446074500200560ustar00rootroot00000000000000#!/usr/bin/env bash set -e set -x coverage combine coverage report coverage html annotated-doc-0.0.4/scripts/format.sh000077500000000000000000000001351510446074500175560ustar00rootroot00000000000000#!/usr/bin/env bash set -x ruff check src tests scripts --fix ruff format src tests scripts annotated-doc-0.0.4/scripts/lint.sh000077500000000000000000000001501510446074500172310ustar00rootroot00000000000000#!/usr/bin/env bash set -e set -x mypy src ruff check src tests scripts ruff format src tests --check annotated-doc-0.0.4/scripts/test-cov-html.sh000077500000000000000000000001271510446074500207750ustar00rootroot00000000000000#!/usr/bin/env bash set -e set -x bash scripts/test.sh ${@} bash scripts/coverage.sh annotated-doc-0.0.4/scripts/test.sh000077500000000000000000000001061510446074500172430ustar00rootroot00000000000000#!/usr/bin/env bash set -e set -x coverage run -m pytest tests ${@} annotated-doc-0.0.4/src/000077500000000000000000000000001510446074500150305ustar00rootroot00000000000000annotated-doc-0.0.4/src/annotated_doc/000077500000000000000000000000001510446074500176325ustar00rootroot00000000000000annotated-doc-0.0.4/src/annotated_doc/__init__.py000066400000000000000000000000641510446074500217430ustar00rootroot00000000000000from .main import Doc as Doc __version__ = "0.0.4" annotated-doc-0.0.4/src/annotated_doc/main.py000066400000000000000000000020631510446074500211310ustar00rootroot00000000000000class Doc: """Define the documentation of a type annotation using `Annotated`, to be used in class attributes, function and method parameters, return values, and variables. The value should be a positional-only string literal to allow static tools like editors and documentation generators to use it. This complements docstrings. The string value passed is available in the attribute `documentation`. Example: ```Python from typing import Annotated from annotated_doc import Doc def hi(name: Annotated[str, Doc("Who to say hi to")]) -> None: print(f"Hi, {name}!") ``` """ def __init__(self, documentation: str, /) -> None: self.documentation = documentation def __repr__(self) -> str: return f"Doc({self.documentation!r})" def __hash__(self) -> int: return hash(self.documentation) def __eq__(self, other: object) -> bool: if not isinstance(other, Doc): return NotImplemented return self.documentation == other.documentation annotated-doc-0.0.4/src/annotated_doc/py.typed000066400000000000000000000000001510446074500213170ustar00rootroot00000000000000annotated-doc-0.0.4/tests/000077500000000000000000000000001510446074500154035ustar00rootroot00000000000000annotated-doc-0.0.4/tests/__init__.py000066400000000000000000000000001510446074500175020ustar00rootroot00000000000000annotated-doc-0.0.4/tests/test_main.py000066400000000000000000000033461510446074500177460ustar00rootroot00000000000000import pickle import sys from annotated_doc import Doc if sys.version_info >= (3, 9): from typing import Annotated, get_type_hints else: from typing_extensions import Annotated, get_type_hints def test_doc_basic() -> None: doc = Doc("This is a test documentation.") assert doc.documentation == "This is a test documentation." assert repr(doc) == "Doc('This is a test documentation.')" assert hash(doc) == hash("This is a test documentation.") assert doc == Doc("This is a test documentation.") assert doc != Doc("Different documentation.") assert doc != "Not a Doc instance" def test_annotation(): def hi(name: Annotated[str, Doc("Who to say hi to")]) -> None: # pragma: no cover pass hints = get_type_hints(hi, include_extras=True) doc_info: Doc = hints["name"].__metadata__[0] assert doc_info.documentation == "Who to say hi to" assert isinstance(doc_info, Doc) def test_repr(): doc_info = Doc("Who to say hi to") assert repr(doc_info) == "Doc('Who to say hi to')" def test_hashability(): doc_info = Doc("Who to say hi to") assert isinstance(hash(doc_info), int) assert hash(doc_info) != hash(Doc("Who not to say hi to")) def test_equality(): doc_info = Doc("Who to say hi to") # Equal to itself assert doc_info == doc_info # Equal to another instance with the same string assert doc_info == Doc("Who to say hi to") # Not equal to another instance with a different string assert doc_info != Doc("Who not to say hi to") def test_pickle(): doc_info = Doc("Who to say hi to") for proto in range(pickle.HIGHEST_PROTOCOL + 1): pickled = pickle.dumps(doc_info, protocol=proto) assert doc_info == pickle.loads(pickled)