pax_global_header00006660000000000000000000000064142444436400014517gustar00rootroot0000000000000052 comment=9c5c653733fc55d638b831ec6845c1eea9491d38 python-legacy-0.2.3/000077500000000000000000000000001424444364000143045ustar00rootroot00000000000000python-legacy-0.2.3/.copier-answers.yml000066400000000000000000000013041424444364000200440ustar00rootroot00000000000000# Changes here will be overwritten by Copier _commit: 0.9.7 _src_path: gh:pawamoy/copier-pdm author_email: pawamoy@pm.me author_fullname: Timothée Mazzucotelli author_username: pawamoy copyright_date: '2021' copyright_holder: Timothée Mazzucotelli copyright_holder_email: pawamoy@pm.me copyright_license: ISC License project_description: A legacy Python handler for mkdocstrings. project_name: mkdocstrings-python (legacy) python_package_command_line_name: mkdocstrings-python-legacy python_package_distribution_name: mkdocstrings-python-legacy python_package_import_name: mkdocstrings repository_name: python-legacy repository_namespace: mkdocstrings repository_provider: github.com use_precommit: false python-legacy-0.2.3/.github/000077500000000000000000000000001424444364000156445ustar00rootroot00000000000000python-legacy-0.2.3/.github/FUNDING.yml000066400000000000000000000000721424444364000174600ustar00rootroot00000000000000github: - pawamoy custom: - https://www.paypal.me/pawamoy python-legacy-0.2.3/.github/ISSUE_TEMPLATE/000077500000000000000000000000001424444364000200275ustar00rootroot00000000000000python-legacy-0.2.3/.github/ISSUE_TEMPLATE/bug_report.md000066400000000000000000000013041424444364000225170ustar00rootroot00000000000000--- name: Bug report about: Create a report to help us improve title: '' labels: unconfirmed assignees: '' --- **Describe the bug** A clear and concise description of what the bug is. **To Reproduce** Steps to reproduce the behavior: 1. Go to '...' 2. Run command '...' 3. Scroll down to '...' 4. See error **Expected behavior** A clear and concise description of what you expected to happen. **Screenshots** If applicable, add screenshots to help explain your problem. **System (please complete the following information):** - `mkdocstrings-python (legacy)` version: [e.g. 0.2.1] - Python version: [e.g. 3.8] - OS: [Windows/Linux] **Additional context** Add any other context about the problem here. python-legacy-0.2.3/.github/ISSUE_TEMPLATE/feature_request.md000066400000000000000000000011301424444364000235470ustar00rootroot00000000000000--- name: Feature request about: Suggest an idea for this project title: '' labels: feature assignees: '' --- **Is your feature request related to a problem? Please describe.** A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] **Describe the solution you'd like** A clear and concise description of what you want to happen. **Describe alternatives you've considered** A clear and concise description of any alternative solutions or features you've considered. **Additional context** Add any other context or screenshots about the feature request here. python-legacy-0.2.3/.github/workflows/000077500000000000000000000000001424444364000177015ustar00rootroot00000000000000python-legacy-0.2.3/.github/workflows/ci.yml000066400000000000000000000045741424444364000210310ustar00rootroot00000000000000name: ci on: push: branches: - main pull_request: branches: - main defaults: run: shell: bash env: LANG: en_US.utf-8 LC_ALL: en_US.utf-8 PYTHONIOENCODING: UTF-8 jobs: quality: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v2 - name: Set up PDM uses: pdm-project/setup-pdm@v2.6 with: python-version: "3.8" - name: Set cache variables id: set_variables run: | echo "::set-output name=PIP_CACHE::$(pip cache dir)" echo "::set-output name=PDM_CACHE::$(pdm config cache_dir)" - name: Set up cache uses: actions/cache@v2 with: path: | ${{ steps.set_variables.outputs.PIP_CACHE }} ${{ steps.set_variables.outputs.PDM_CACHE }} key: checks-cache - name: Resolving dependencies run: pdm lock - name: Install dependencies run: pdm install -G duty -G docs -G quality -G typing -G security - name: Check if the documentation builds correctly run: pdm run duty check-docs - name: Check the code quality run: pdm run duty check-quality - name: Check if the code is correctly typed run: pdm run duty check-types - name: Check for vulnerabilities in dependencies run: pdm run duty check-dependencies tests: strategy: matrix: os: - ubuntu-latest - macos-latest - windows-latest python-version: - "3.7" - "3.8" - "3.9" - "3.10" - "3.11-dev" runs-on: ${{ matrix.os }} steps: - name: Checkout uses: actions/checkout@v2 - name: Set up PDM uses: pdm-project/setup-pdm@v2.6 with: python-version: ${{ matrix.python-version }} - name: Set cache variables id: set_variables run: | echo "::set-output name=PIP_CACHE::$(pip cache dir)" echo "::set-output name=PDM_CACHE::$(pdm config cache_dir)" - name: Set up cache uses: actions/cache@v2 with: path: | ${{ steps.set_variables.outputs.PIP_CACHE }} ${{ steps.set_variables.outputs.PDM_CACHE }} key: tests-cache-${{ runner.os }}-${{ matrix.python-version }} - name: Install dependencies run: pdm install --no-editable -G duty -G docs -G tests - name: Run the test suite run: pdm run duty test python-legacy-0.2.3/.gitignore000066400000000000000000000002531424444364000162740ustar00rootroot00000000000000.idea/ __pycache__/ *.py[cod] dist/ *.egg-info/ build/ htmlcov/ .coverage* pip-wheel-metadata/ .pytest_cache/ .mypy_cache/ site/ pdm.lock .pdm.toml __pypackages__/ .venv/ python-legacy-0.2.3/.gitpod.dockerfile000066400000000000000000000002211424444364000176740ustar00rootroot00000000000000FROM gitpod/workspace-full USER gitpod ENV PIP_USER=no ENV PYTHON_VERSIONS= RUN pip3 install pipx; \ pipx install pdm; \ pipx ensurepath python-legacy-0.2.3/.gitpod.yml000066400000000000000000000002171424444364000163730ustar00rootroot00000000000000vscode: extensions: - ms-python.python image: file: .gitpod.dockerfile ports: - port: 8000 onOpen: notify tasks: - init: make setup python-legacy-0.2.3/CHANGELOG.md000066400000000000000000000062011424444364000161140ustar00rootroot00000000000000# Changelog All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). ## [0.2.3](https://github.com/mkdocstrings/python-legacy/releases/tag/0.2.3) - 2022-05-28 [Compare with 0.2.2](https://github.com/mkdocstrings/python-legacy/compare/0.2.2...0.2.3) ### Packaging / Dependencies - Depend on mkdocstrings 0.19 ([71123dc](https://github.com/mkdocstrings/python-legacy/commit/71123dc4dda6ece390d94d0400920541ded76ede) by Timothée Mazzucotelli). ### Code Refactoring - Unify default configurations ([47c53fc](https://github.com/mkdocstrings/python-legacy/commit/47c53fcc1c6519025f0aec65b85bdc99e4eac2f5) by Timothée Mazzucotelli). - Stop using deprecated base classes ([5a28b12](https://github.com/mkdocstrings/python-legacy/commit/5a28b125a2ac87ddf1b804160deb11076a0ae409) by Timothée Mazzucotelli). - Use new `mkdocstrings_handlers` namespace ([d688c87](https://github.com/mkdocstrings/python-legacy/commit/d688c87dd3eca4d8cc25761d957e6855832da4b4) by Timothée Mazzucotelli). ## [0.2.2](https://github.com/mkdocstrings/python-legacy/releases/tag/0.2.2) - 2022-02-19 [Compare with 0.2.1](https://github.com/mkdocstrings/python-legacy/compare/0.2.1...0.2.2) ### Bug Fixes - Handle empty error in JSON output ([0e7ab59](https://github.com/mkdocstrings/python-legacy/commit/0e7ab594ae550b4c95a3a8b47ff190dbe88ff000) by rachmadani haryono). [PR #1](https://github.com/mkdocstrings/python-legacy/pull/1) ## [0.2.1](https://github.com/mkdocstrings/python-legacy/releases/tag/0.2.1) - 2022-02-05 [Compare with 0.2.0](https://github.com/mkdocstrings/python-legacy/compare/0.2.0...0.2.1) ### Dependencies - Require at least mkdocstrings 0.18 ([09d8e9c](https://github.com/mkdocstrings/python-legacy/commit/09d8e9c4a3d8aaf4ee1d95a702d4ad3c5b46638e) by Timothée Mazzucotelli). ## [0.2.0](https://github.com/mkdocstrings/python-legacy/releases/tag/0.2.0) - 2022-02-03 [Compare with 0.1.0](https://github.com/mkdocstrings/python-legacy/compare/0.1.0...0.2.0) ### Features - Add `show_signature` rendering option ([e741b37](https://github.com/mkdocstrings/python-legacy/commit/e741b3709e35e89372021a44f46c9b1939c8147d) by Will Da Silva). ### Dependencies - Depend on mkdocstrings ([a154c05](https://github.com/mkdocstrings/python-legacy/commit/a154c051aa6230870d2857ca911dcf797e0ec8b6) by Timothée Mazzucotelli). ### Code Refactoring - Add user warning about mkdocstrings extra ([71ea2d8](https://github.com/mkdocstrings/python-legacy/commit/71ea2d80f071e091f7a2f7b695ffcdd9dbe0351f) by Timothée Mazzucotelli). ## [0.1.0](https://github.com/mkdocstrings/python-legacy/releases/tag/0.1.0) - 2021-12-18 [Compare with first commit](https://github.com/mkdocstrings/python-legacy/compare/720f91ec264b37345d6a1fe7e77a3164c0bf642f...0.1.0) ### Features - Copy code from mkdocstrings ([720f91e](https://github.com/mkdocstrings/python-legacy/commit/720f91ec264b37345d6a1fe7e77a3164c0bf642f) by Timothée Mazzucotelli). python-legacy-0.2.3/CODE_OF_CONDUCT.md000066400000000000000000000062251424444364000171100ustar00rootroot00000000000000# Contributor Covenant Code of Conduct ## Our Pledge In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. ## Our Standards Examples of behavior that contributes to creating a positive environment include: * Using welcoming and inclusive language * Being respectful of differing viewpoints and experiences * Gracefully accepting constructive criticism * Focusing on what is best for the community * Showing empathy towards other community members Examples of unacceptable behavior by participants include: * The use of sexualized language or imagery and unwelcome sexual attention or advances * Trolling, insulting/derogatory comments, and personal or political attacks * Public or private harassment * Publishing others' private information, such as a physical or electronic address, without explicit permission * Other conduct which could reasonably be considered inappropriate in a professional setting ## Our Responsibilities Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. ## Scope This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. ## Enforcement Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at pawamoy@pm.me. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. ## Attribution This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] [homepage]: http://contributor-covenant.org [version]: http://contributor-covenant.org/version/1/4/ python-legacy-0.2.3/CONTRIBUTING.md000066400000000000000000000062701424444364000165420ustar00rootroot00000000000000# Contributing Contributions are welcome, and they are greatly appreciated! Every little bit helps, and credit will always be given. ## Environment setup Nothing easier! Fork and clone the repository, then: ```bash cd python-legacy make setup ``` > NOTE: > If it fails for some reason, > you'll need to install > [PDM](https://github.com/pdm-project/pdm) > manually. > > You can install it with: > > ```bash > python3 -m pip install --user pipx > pipx install pdm > ``` > > Now you can try running `make setup` again, > or simply `pdm install`. You now have the dependencies installed. Run `make help` to see all the available actions! ## Tasks This project uses [duty](https://github.com/pawamoy/duty) to run tasks. A Makefile is also provided. The Makefile will try to run certain tasks on multiple Python versions. If for some reason you don't want to run the task on multiple Python versions, you can do one of the following: 1. `export PYTHON_VERSIONS= `: this will run the task with only the current Python version 2. run the task directly with `pdm run duty TASK` The Makefile detects if a virtual environment is activated, so `make` will work the same with the virtualenv activated or not. ## Development As usual: 1. create a new branch: `git checkout -b feature-or-bugfix-name` 1. edit the code and/or the documentation **Before committing:** 1. run `make format` to auto-format the code 1. run `make check` to check everything (fix any warning) 1. run `make test` to run the tests (fix any issue) 1. if you updated the documentation or the project dependencies: 1. run `make docs-serve` 1. go to http://localhost:8000 and check that everything looks good 1. follow our [commit message convention](#commit-message-convention) If you are unsure about how to fix or ignore a warning, just let the continuous integration fail, and we will help you during review. Don't bother updating the changelog, we will take care of this. ## Commit message convention Commits messages must follow the [Angular style](https://gist.github.com/stephenparish/9941e89d80e2bc58a153#format-of-the-commit-message): ``` [(scope)]: Subject [Body] ``` Scope and body are optional. Type can be: - `build`: About packaging, building wheels, etc. - `chore`: About packaging or repo/files management. - `ci`: About Continuous Integration. - `docs`: About documentation. - `feat`: New feature. - `fix`: Bug fix. - `perf`: About performance. - `refactor`: Changes which are not features nor bug fixes. - `style`: A change in code style/format. - `tests`: About tests. **Subject (and body) must be valid Markdown.** If you write a body, please add issues references at the end: ``` Body. References: #10, #11. Fixes #15. ``` ## Pull requests guidelines Link to any related issue in the Pull Request message. During review, we recommend using fixups: ```bash # SHA is the SHA of the commit you want to fix git commit --fixup=SHA ``` Once all the changes are approved, you can squash your commits: ```bash git rebase -i --autosquash master ``` And force-push: ```bash git push -f ``` If this seems all too complicated, you can push or force-push each new commit, and we will squash them ourselves if needed, before merging. python-legacy-0.2.3/LICENSE000066400000000000000000000013621424444364000153130ustar00rootroot00000000000000ISC License Copyright (c) 2021, Timothée Mazzucotelli Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. python-legacy-0.2.3/Makefile000066400000000000000000000015661424444364000157540ustar00rootroot00000000000000.DEFAULT_GOAL := help SHELL := bash DUTY = $(shell [ -n "${VIRTUAL_ENV}" ] || echo pdm run) duty args = $(foreach a,$($(subst -,_,$1)_args),$(if $(value $a),$a="$($a)")) check_quality_args = files docs_serve_args = host port release_args = version test_args = match BASIC_DUTIES = \ changelog \ check-dependencies \ clean \ coverage \ docs \ docs-deploy \ docs-regen \ docs-serve \ format \ release QUALITY_DUTIES = \ check-quality \ check-docs \ check-types \ test .PHONY: help help: @$(DUTY) --list .PHONY: lock lock: @pdm lock .PHONY: setup setup: @bash scripts/setup.sh .PHONY: check check: @bash scripts/multirun.sh duty check-quality check-types check-docs @$(DUTY) check-dependencies .PHONY: $(BASIC_DUTIES) $(BASIC_DUTIES): @$(DUTY) $@ $(call args,$@) .PHONY: $(QUALITY_DUTIES) $(QUALITY_DUTIES): @bash scripts/multirun.sh duty $@ $(call args,$@) python-legacy-0.2.3/README.md000066400000000000000000000067751424444364000156020ustar00rootroot00000000000000

mkdocstrings-python-legacy

The legacy Python handler for mkdocstrings.

ci documentation pypi version gitpod gitter

---

WARNING: We suggest using the new handler instead: [mkdocstrings-python](https://mkdocstrings.github.io/python/). ## Installation You can install this handler as a *mkdocstrings* extra: ```toml title="pyproject.toml" # PEP 621 dependencies declaration # adapt to your dependencies manager [project] dependencies = [ "mkdocstrings[python-legacy]>=0.18", ] ``` You can also explicitely depend on the handler: ```toml title="pyproject.toml" # PEP 621 dependencies declaration # adapt to your dependencies manager [project] dependencies = [ "mkdocstrings-python-legacy", ] ``` ## Preview ![mkdocstrings_python_gif](https://user-images.githubusercontent.com/3999221/77157838-7184db80-6aa2-11ea-9f9a-fe77405202de.gif) ## Features - **Data collection from source code**: collection of the object-tree and the docstrings is done thanks to [pytkdocs](https://github.com/mkdocstrings/pytkdocs). - **Support for type annotations:** pytkdocs collects your type annotations and *mkdocstrings* uses them to display parameters types or return types. - **Recursive documentation of Python objects:** just use the module dotted-path as identifier, and you get the full module docs. You don't need to inject documentation for each class, function, etc. - **Support for documented attributes:** attributes (variables) followed by a docstring (triple-quoted string) will be recognized by Griffe in modules, classes and even in `__init__` methods. - **Multiple docstring-styles support:** common support for Google-style, Numpydoc-style, and Sphinx-style docstrings. - **Admonition support in Google docstrings:** blocks like `Note:` or `Warning:` will be transformed to their [admonition](https://squidfunk.github.io/mkdocs-material/reference/admonitions/) equivalent. *We do not support nested admonitions in docstrings!* - **Every object has a TOC entry:** we render a heading for each object, meaning *MkDocs* picks them into the Table of Contents, which is nicely display by the Material theme. Thanks to *mkdocstrings* cross-reference ability, you can reference other objects within your docstrings, with the classic Markdown syntax: `[this object][package.module.object]` or directly with `[package.module.object][]` - **Source code display:** *mkdocstrings* can add a collapsible div containing the highlighted source code of the Python object. python-legacy-0.2.3/config/000077500000000000000000000000001424444364000155515ustar00rootroot00000000000000python-legacy-0.2.3/config/coverage.ini000066400000000000000000000004221424444364000200430ustar00rootroot00000000000000[coverage:run] branch = true parallel = true source = src/ tests/ [coverage:paths] equivalent = src/ __pypackages__/ [coverage:report] precision = 2 omit = src/*/__init__.py src/*/__main__.py tests/__init__.py [coverage:json] output = htmlcov/coverage.json python-legacy-0.2.3/config/flake8.ini000066400000000000000000000051421424444364000174260ustar00rootroot00000000000000[flake8] exclude = fixtures,site,snippets max-line-length = 132 docstring-convention = google ban-relative-imports = true ignore = # redundant with W0622 (builtin override), which is more precise about line number A001 # missing docstring in magic method D105 # multi-line docstring summary should start at the first line D212 # does not support Parameters sections D417 # whitespace before ':' (incompatible with Black) E203 # redundant with E0602 (undefined variable) F821 # black already deals with quoting Q000 # use of assert S101 # we are not parsing XML S405 # line break before binary operator (incompatible with Black) W503 # two-lowercase-letters variable DO conform to snake_case naming style C0103 # redundant with D102 (missing docstring) C0116 # line too long C0301 # too many instance attributes R0902 # too few public methods R0903 # too many public methods R0904 # too many branches R0912 # too many methods R0913 # too many local variables R0914 # too many statements R0915 # redundant with F401 (unused import) W0611 # lazy formatting for logging calls W1203 # short name VNE001 # f-strings WPS305 # common variable names (too annoying) WPS110 # redundant with W0622 (builtin override), which is more precise about line number WPS125 # too many imports WPS201 # too many module members WPS202 # overused expression WPS204 # too many local variables WPS210 # too many arguments WPS211 # too many expressions WPS213 # too many methods WPS214 # too deep nesting WPS220 # high Jones complexity WPS221 # too many elif branches WPS223 # string over-use: can't disable it per file? WPS226 # too many public instance attributes WPS230 # too complex f-string WPS237 # too cumbersome, asks to write class A(object) WPS306 # multi-line parameters (incompatible with Black) WPS317 # multi-line strings (incompatible with attributes docstrings) WPS322 # implicit string concatenation WPS326 # explicit string concatenation WPS336 # noqa overuse WPS402 # __init__ modules with logic WPS412 # print statements WPS421 # statement with no effect (not compatible with attribute docstrings) WPS428 # redundant with C0415 (not top-level import) WPS433 # multiline attribute docstring WPS462 # implicit dict.get usage (generally false-positive) WPS529 python-legacy-0.2.3/config/mypy.ini000066400000000000000000000001621424444364000172470ustar00rootroot00000000000000[mypy] ignore_missing_imports = true exclude = tests/fixtures/ warn_unused_ignores = true show_error_codes = true python-legacy-0.2.3/config/pytest.ini000066400000000000000000000002701424444364000176010ustar00rootroot00000000000000[pytest] norecursedirs = .git .tox .env dist build python_files = test_*.py *_test.py tests.py addopts = --cov --cov-config config/coverage.ini testpaths = tests python-legacy-0.2.3/docs/000077500000000000000000000000001424444364000152345ustar00rootroot00000000000000python-legacy-0.2.3/docs/changelog.md000066400000000000000000000000261424444364000175030ustar00rootroot00000000000000--8<-- "CHANGELOG.md" python-legacy-0.2.3/docs/code_of_conduct.md000066400000000000000000000000341424444364000206700ustar00rootroot00000000000000--8<-- "CODE_OF_CONDUCT.md" python-legacy-0.2.3/docs/contributing.md000066400000000000000000000000311424444364000202570ustar00rootroot00000000000000--8<-- "CONTRIBUTING.md" python-legacy-0.2.3/docs/credits.md000066400000000000000000000000711424444364000172110ustar00rootroot00000000000000```python exec="yes" --8<-- "scripts/gen_credits.py" ``` python-legacy-0.2.3/docs/css/000077500000000000000000000000001424444364000160245ustar00rootroot00000000000000python-legacy-0.2.3/docs/css/material.css000066400000000000000000000001311424444364000203270ustar00rootroot00000000000000/* More space at the bottom of the page. */ .md-main__inner { margin-bottom: 1.5rem; } python-legacy-0.2.3/docs/css/mkdocstrings.css000066400000000000000000000002051424444364000212420ustar00rootroot00000000000000/* Indentation. */ div.doc-contents:not(.first) { padding-left: 25px; border-left: .05rem solid var(--md-typeset-table-color); } python-legacy-0.2.3/docs/gen_ref_nav.py000077500000000000000000000016631424444364000200700ustar00rootroot00000000000000"""Generate the code reference pages and navigation.""" from pathlib import Path import mkdocs_gen_files nav = mkdocs_gen_files.Nav() for path in sorted(Path("src").rglob("*.py")): module_path = path.relative_to("src").with_suffix("") doc_path = path.relative_to("src").with_suffix(".md") full_doc_path = Path("reference", doc_path) parts = tuple(module_path.parts) if parts[-1] == "__init__": parts = parts[:-1] doc_path = doc_path.with_name("index.md") full_doc_path = full_doc_path.with_name("index.md") elif parts[-1] == "__main__": continue nav[parts] = doc_path.as_posix() with mkdocs_gen_files.open(full_doc_path, "w") as fd: ident = ".".join(parts) fd.write(f"::: {ident}") mkdocs_gen_files.set_edit_path(full_doc_path, path) with mkdocs_gen_files.open("reference/SUMMARY.md", "w") as nav_file: nav_file.writelines(nav.build_literate_nav()) python-legacy-0.2.3/docs/index.md000066400000000000000000000000231424444364000166600ustar00rootroot00000000000000--8<-- "README.md" python-legacy-0.2.3/docs/license.md000066400000000000000000000000311424444364000171720ustar00rootroot00000000000000``` --8<-- "LICENSE" ``` python-legacy-0.2.3/docs/logo.png000066400000000000000000001627141424444364000167150ustar00rootroot00000000000000PNG  IHDRZrMzTXtRaw profile type exifxڭgvcvcrZo^+DN;JzzG|Ssg_^(c1}k%,~=o/|?[~.=oV߳k _|(uJa,pz a%WzN\XxGhq2.L&$2kH%Tz,q {L9)$cNuoB'3yH&%HHӑ`SCK)(k*l-JF=Ksđ2h1䦓'\0EKXf݆EʪnXsǝ6ȵn R:SO;3/vͷzwG־?k;keJlkCIQX́7e@BQStEL(9;(cd0 ?#s?ys9?9=oڞ zاztB)0qd1^W/)ɫӈ=o[imjhDv6mr\KbhZXٷgwNnE|:=w+z~9 b%t_Zo[@F-,uPn)Cx`brIq),&AN(gܬ_r6^~)$}wV&~'/Oi Xk [Vuk4"F-U K E9BWH{4&Tp䁼b6`;w:/iwg(LnΘ03u10g!GtI<2b"# Z_FJu8.%{(4Ivt?P.aiTŸ DAG9ܦ6nVxJ:"R}/p3WLݔ>x)UBJ+bTׁMCZH&< ow N.D҂p^LnDW)qq~'7kӨ ˤ T~`X7`R.Y=A 2ƚ$H8~}]7Zu6gJEiiDS|f XHiDf4#'a>(3#e)Rޕ"a_h_s -¯e3sZeR}HvA-Dʍ`zLH藬)zH !."B4/x2XD]۔LgF 6dS-Q62A;K/ o ~/WA&jI iԫʵRQS3.K z(Lb/͆r6Y#C)UYn~T]2NBn;(.8C"D.NŞfFS'<%  %*9? MWWe f2@|.ky|DP`{M4}3!֓i)ՠ 6 B(~V:РC+ `9n1U+7qæ8.v?w]Yb:)k/x.5wlA. gM _{ OP|=M{GAL=@ׇwHT"P}{'$v3꫟ԄDzmɬ?@er^Um?t,ory JFMT)jqlHVhuɘd#H%U#% =XKWXhoИQ44\)V.AM!:n#"Vxr)!T?, Y)0E[HapR|}L<<+Kp4n]#[UwY1߼8J=.BsGʢ mI/Fđd%6ϓ'h xww5.ɐrgPbDm,8K$G#项͋`3y1Uy%Ĭ lYhm/CiZ$ikBX6 z @7% ny2uljxQOLB֑CMpB-H"01Ѻ46U'p:4r"X[$Hѓ$(Ƙ-hπR ;tL`1)IX[2GLsBH?!|.}@*|D SRߏPp0ִR,1;|½ED hCB7(j_g) &aV14TV;3I::ޚ EqU36-)r_n1PxRm0cYa=d'B=PnaTp\~^{P7΅rm4aG {paϻ2G;b 9ںh{hZŰ4(pIBke|"0. c]~;6MR碟@x@5CD$c_JBH+ps0~GQ聅:D;3#~CNhcw@nxщvJ&G rZ"1"̟:AGPcӋAdyo7?ʚL#6R)V=EKZnXhj sb IRʅ %q:)_.bVZy6]vtT@x@TAQk |boS{-`p^—+cMκy(!w3"jWQ \L~cC2c=! t@ЫWo_f[+:hC;6~6Bn4 >5 H2ϑ + y_ .[`I^LLBJ n y84ryC 2mx#o#Oac4(EgI e>+'j"6JHtj*y$nK[PnAk1d4W3䑘$Cѥ8P-U<nt!F"U1(OJw) =umIM_[B::ԫG$ yo9G/O[a-Z?-I:(6#twthE-֗M'fB`FI$C_g0%(S . `@WgڏCǡi`xhjvaȊxEG 2®159-d(-QQΘ&@aX;LѩΗ1Tm=E1pnUhtdZ#ޚRی?3JrdYAgW(6b#, ! pi.ܠ|2p yB^rSDbSA܉|B3E$ q@+q7TǡKe[~@Q') xk(b. jrh&p8H$p)%>2o3 xh$.G!fxǑ-EK4jY :oK,2Cp޽] Z⻮N!p⨉-C[9ν#8C8SK3AbG$~u@b [ĆIEoD6 o9a+;YG8 Ov X ~ ? za`mgjI?;F/,Bچ~9.q|b#]{&#-0&M&N Qk0 bZoڬ"ĈpY$yԣM-$zzVabCUt.TRc2_.t@G%UXcBSjv97 /hJ?rOP `"hUJR|POe:O>F* |(_YN-n_ps-I<RUڇzΎ-7 3&K:m_уEr?.I_0/K ,Pbfze @'FQG>z/ & 54C$;x?4{uba@r +T}xD:LB^/#lt$xOv4^售>t^י6r zձ܆ @zZ|i7@Aw2 rIQ].d:t r* &mlOH2^[o$_i/ސH r݈ى6{Al@NwDn}(n Bl(lwHaUqP^;&D0\3$gfԮp#yK];Ot4>Y!jPAԴ2/,.P>4!~T;:mӺaRLvdVpsԉUߏ'Ϗ:0J Q*0nEEm?(+.OBKVztLw,c"-\3:XHy1K҆翨}W&|, xxz9GYIRω #e8̨IGbJJ 9bKGD pHYs  tIME  4S IDATxy|Օ=zSK[1"86l^`2$eB20I3I>y~' U,$!c H0cm1xhݒ%[K/խt>[UV=s  A(hnƆzM =Kn1ͺLL9Y13.Hpʔi%N/4^cIMCSrPe(.Wb411i?2ɣc h%BbF Nͪmvht@qZ6$GL-6v:@Fvy>~@2!"ՌH*AAaX o'ԳXZ;v5?',O0TlzǬ&Ü@c {"Dh0& W0k9Yzӏ^rJ{t b|@D R鷨k@ 8h 8!vH:6ɖ|V_?jQI^GlD3"H   zT-oЬoёmӅsMS1|Wt~˘1M5)8ciX$; рvaSgbySӥ2D|7l;wCԿSÒ AA)H)2``za'pq'pTA oE>2 dƑ]?38m++uDAAfΪD/'Lڛ|ݎ^TkW h935|*. HsZZo4^AϾEめkmǹ.T5D Z'qX )<+9KK>gR#݃&@C)e ev@;-amϯOюHd]$]A{olT#EٟьS&] s2)qh05k(*!gn!=8?%)2DJJ)ӂ:?ƬL:_f[WBfS8,0"  ҩӳ3>䘠a_b*,& 0v@K(t (g!bbS7h5D,GOmj=Gzdf]$]AR@m-# r]6Aà=L& +n<#%w}12,*F2-K6f0R =~hv'h'rx[b F-q"  ZFvoZdXКV̌Eh!.AW]Ao ):ߛ?O|{GjhDzDAA("+BW:D~d Xwx|e vlG;6+";<ARxb|K dZiOi"ôرöA7~`-[bˬH  E6 ,Zp{|[Mw)tv<d1Bt3ѩD2-S>8xnz<^wXJ)#ouSn3RAD.5k;7hiql FOs!!tAA uf:X۽ wuvt<=VNK.0=ZݪNM;hcѵ'w 5zW'% H  nSh LϪ'Lmc}`K;IPȂ 4~PAϢ- `0A٤ KY^8bOV?H  ΅]w|ezevY&Q,-JnYҕD]t5k(h|"[hj{*T  ?BHy%mkLraz(C!dXHa'6=[^ϋܲHFC>Y̤ °i:M^n2<;ayi/l I z6ŽdZ&D"|7o7O4tAAF5f*z3@C/JvfѝS%Dx.,;7u# DH  HӒ[֘o5Y_}$0vw DZ#,33S6r_.YYwhh8.mw,Ӛ㫨z3ߥr<)EbAXi<~!_gJQ_8K!}@AGqʱUl[bswd}*d&]AJF^e kDe-gYX7Sp9Cp;-<1Pڦ9r/ιڦ0+BdF}tAA(e>R&N/X~mORΈv;"Dݤ\nˁ^/~rAN"i˦PqŞ &Q/22.  aճ~~̉vlNѶc3;I~m[3L,p6c46pbѸlLįlj\ǡPHL  ,ЬϹi>M${QWv 2L_@)_aX~ a*bVZ; &:H>7"\"J)emvѦl -bcĉ ,\@AJf&"`}[19mIޗo "`Ўxp4 :;ҿ}+ VRTRc6,J;V֙MBEd6d\;:qngqqKr_vlXkVՒr(X&`jq6jN{O 8H~ؗ~N~TtxZ{-Nwn *L\2]܆qlxI\n [̦5_=TJ"uEKłW Q &Hk=+B;FYT$&9!~Gh=LO?# Xq4-H{HQ : Ƅ}wb1s]v04fw:}XL<]v?N BY!c`Aj`$,Lbcюg`+JMsk"55+YI42sq$auּy3j"k,ak[oHTP`1G*E@f0 `[o" dƔtKZ ?N}6Y^Nf HB <"(:NlNdg;Uc&êaCSFP1|\8!3;PY9lGEs A9+ϱ\x>T[iy= %"><5Շe Y|T6?m๫G} ;r#;ͧQQpD|f{v[FjN9pjLq55dw= Awcl ffy(vl2$. "yI|X` J+=xk^36 3?p>RwpIZ҅1~NtmWjaP[)Cg"'xfE8>-NϡXwN)tGY}\fz6Ȩnf*ӳ`Hd}K42-l"5֤ =o2_* :WFhonqU[>| @*-=C@2[%mh/ߡj|P1`f"]]6/D ;.HKf40;8Tx6sPBB*~RyWЧl{,2/x^- d}:=嚥؝f(E}i6keU LBpIHiotCN͜aJIH0I !"5s}]Z'xUO"uc ӗNQI礊F3Cu"`994(X5e++m¡m,k5U;IM`{8t!⊠Y9  8_E u)Db57!s"Bp'6Rʬt]TA Юgi0$P>I@{ +5DY<>AX3ւR5dUXJ$$HHjR7 BX~ H=0}wR7 B1KI?Td4ͅNOF>as'%xَ33ѕ,ݶa.n[OW]n8FjO%@ǐFi !-ϋRmB p9Rb6DĠwp0dMwԪ@ĵ`@)ǸzIۦ^ޑ$+irZ"qnԣH!5k("uS 3| Е5|T, J7'U2!t"֧?LD)ef9Dm}B"MӸ5IJdh{f[MY.} QL.r J_ 0Y\&RY6> axPԽ!#v4 c ٰQ敗W?e-峸հmDl˿hsD&RFy/sNz[J 6Ϡ(_Lر"͕8JK9$s8 WEAJWT04 ; m&|J F8LLn(F0i_XO2Id.p;wpo,}R}t9q!͙ZhJU5ox@L!b|9RJh|/ғkڊ!¡in&62uuihp"ďk|&|]!Req)4\e:fE* KRn-QII"e l?=ƎǞT[+'F6|D=h*edlR"eR9FBz.-iGO4JFAaɃ6.U1="zEd9vұ1V )Tv8e; "L:pAwC` <˼,)_B* 0< R]R}D1܈ 2-5ر>O D e9S -9mFJE] `R} Þ:K5H.vY$ @bo!|z6ȲnMw hG>&יCR-DEE*++v=***PVV`0!@hсVɓ8yd'NmX©ѼR~QhooGgggV8\8rK50bWV ΄JzGsL4 Ǐرc1n8;'Nĉ1fTTTt?Ʋ??5ں%?~ǎñcpߏ9Cرc`pRYYI&uٞwرw{+}a5)'NÇq^ѣ8x N<9X IDATqbW%n|+rCCP%t$^’>oWLEEjjjPSS3gb̙={6f͚ɓ's9k-x{͛chnn믿Vǃ磶gg;gFU  Q]]{;::ocΝx7o^Css3><һ"OP a xo7g]O.m$=x`]cFgJ0T41m4̜9sܹs1{lL6 ӦMÄ  v2Rz3g̙s&Ɖ'w^ݻwƮ]k׮n1:~\&2>gƜ9s0k,L:SNŴiP]]]𰓑HYYPWWwkmmmxww^ر:~mڵ ;wDggH9 JMmFFTq.>KW-`.to[fHzX|9.,_K,x<,_˗/ǃ>;ws=oQ_]]ݫ4MiQ¢Eh"{x׿>,֭[K 3!]۸ַ]&*BEȹHz."}ݸ80k,̚5 7p`֭OGydnDUJ >K.isŹ瞋[oZk `|Ǟ={#`ʕCv, .<#G'EЅ~r+Vڵkqa<#rF#R'؀BEyz0g=p0\٧[~ZyY^̫jIkcqgKk  q7bݺux?ؼy3\p*xx'cy7zGo9Zq3z(,渿|gA~ >%~;̛7OZHțy׿5>epe\veRBTWW?!֬Y#1 !6|gɢY, )ΰH(>%=.'ү$] p+!:bg[(:>HZ AA(I "=:Iv=SAtY /eϞ9 RgDisAgЖф(H  ֎;.um[te >{2?.9H$DdulX qs". Bd;^[Q |)>c0x}3%'Hlo.tWC{J]$]A۶1aS{E_9ՙk;8s߿kvG2kbpִ^f =`~,vtAA_^sZUEh)'ɉ(km;$[Qcg,,'h(Rlܽȳnh %@ w zV\J̠ft.tAAM0#v@MX +H+^p96swb .  G"p0V1~4IMLf<@(AAF:IRoAwsW 1C̤ 0(`XrK,JHkbG<G<ض 5ְ9s$ ÀR J)^/^/|>_eYR ( rA.fAA%p^;]wH{޽{҂#Gȑ#8zh]6D5i" bر?~|ɓ1i$L2ӧOQVV& * |A/\y :AϪ2+&ܞj%AFd"SCIϒd2#G`ؿ?ZZZ҂wqQ;v 'O,m'N'sA7nƏSLQAi>3]ɡ 8-رcz-8qBÇ~n̘1={6fϞsb޼yży$F‰83zu+իpXaFCצᴜ #_DyRoKi /猌7 5Y 7"J,Λ2r7Z)'qx|WM WI/"o6?駟3e S *nj |LڧAZnWqe|tq;lB^cc`MĄ2Af "&\KЋv,`#pl/IQ{Щ 3nʾ ?`Rjjjrc$L~դo>3W!i 0DxI?r^~eKذa6mڄmoD  l2\uU81~x(A@`"h,?,lâSNs'✨^f8u*Y3/G1pd}DJԩS5BZw{ ]Uv!>ZsɗX Vzt2 'E2ɤDng?`%ȌwVzϠ;06_un7r9:e p8j 5ַОڥi?l$ cu+. ]70"̸G}މYeOz9,";#I)JGRFẠ#n :XЋ&E!u zOXllBшC#hc|0? g030 VR$]A,ekK3G?l*"Hh;n" #U>,]~ץMAwS8s;,-spC Xe2rulJ]e\B@tZ^9CC " $R+R5&q//xiYʀH:1)R$3}#͆n2*ŞwQͿyvQ>΁]jׂzd@3dVGU 4yw^嗗XX.DH P̦ի&"_ULjô Nq;aZD`GCŐsI`E9sh-sAϣ_U{jcX L$mTxTMn^Z⯙C&Ϋ  *=EoUk09hBkm*2" uHĐQT)]t1tovDI 6dg9/,Q:Jjt IAJ Nl"Ϲ+_NvC"O*?2-Y OM`wSl+.}z{اULun~UD NcL7  B_d&]A(B!Z7~zLV ʎGLj"2I 'h>,y 'Cu3=_&Ef1Τܮ>ڒslǬfya&2~ܐbJ6HA]!DCQƕ}|WRNe|IAFaM+W>=?1=D]3Jaq#2HHE_!,^It1J٭̟Vdֺ!#F 9mu wA[АVӱcϙ?ىwj۱5)c 4^]A!~o!ƓO8uUU//l# *G]$|>TTTt?*++QQQr~B)0R j:q8dZk858(b8bXhmmEkk+N<Ӷmi,ACc'W <(+{#1I45 i *<$"p%diEQZ{+28]ܖZa ;`ŋ} j8"%@YYjjj0c L6 'O1}tuY6mZ\2Zk>|w޽{o>ڵ ݻoĉ M}}ihpjn _2њd$\$Z0PZB\AhsR-ٖż2!fnvE՘4i1ydTWW0aJ)L4 &M\6mmmؿ?8{[كfq8 O(jkoo/ ]n xf𔺠 :\lLPoS\.z. 1G#`N`tSwܹsq/ҥKQWW#üy|qxaū*'B"s9e?'mqRv1"j -ŞuͲ.ؒ-n͠gfѭL4ʃQ>ùe]Nۦ RrvG?3gb-)zQ[[wXl,X磬Ly`jjjPSSn с^{ ۶m֭[el޼ Fh5Ez⻾>mfFJzAA=e /ner΅_s<=Ӆif#sx /?u+LDcܸq}˗/ f(++ҥKtSݙ:z)7?T `Sq }eeٱM`dfnfq-}!.f`͔g]!A!io}%̒hy nLQJaΜ9 qE/Fmm\%K"q{qa hjj477q(A!s/F_ub]ܡNXeݎAw\ qqc@ t.!ąNU\+KւMQ}Y@9EU?ͺn<RDf#G_|hhhu]ӧ˕q0a\{kx'OT g7o_[ }[FNtjf i ΍,B|*#%"㳔qŹ+Mb6նᳮK'?`O>ÔAjDJ1f &Mn v}a.Ǧ- $m"ew%+fmIr&Lr3=zpy&b*29uA3z=cBz? ڲ d?]a">2va ni ;s>_Na}.!AGJǠ]g.s,&YCЎPlY0uk"fP "DR0 (;L&]+YgJY_ױuVW2M?QUU% _LBYf11&"#_bs:C$%>y3u-]Ϊ-iBĠg\:K&%@ڎ'hW91zK0.D$]F9w֮]Zy]wk]SVVEtVu?1`}7͎v$rD4Awc^t.htu@y~Fr=hYǸ%.\3`!Jsu!}VdD ~Vބ Cz- 7Zy?ϱi&i"Q_H9c14=8K߄8!q 7gteqE32MF0X,gC38Wm.eu$}[r4u7rǞM[a~kVg9X 3>g@0]@c}!.BX|aWzA04+ B,r<í2A7l(TK&U72 gķ0sI)!mmmhmmE,C,CGGGX xxdJ)"eYPJ4SMzz|`aHoߎ_W^{mAp5+WWƯ7O:D!V+_lRFH7=c1p❵]Y"/#K!b)"S[r{ehO@?@IE]q}1c&d=wy6UM컉\ t以DKK y;ؿ?ߏ#Gz#^18~8vP)TUUa2eJO4[Lٳg|H$_ҵ>K/-ʱ_tE];_׾#EB&όfz+'رW.C4\B IDATsVv |((^l u s;_jbAP@mg(NT)dx饗 /`hnnFGGǨ5=GbnWVVZ,Z .矏ŋ,| vZ޽ە*++)塇o~ R+QP$n!3Ơg[f[6X̻-]bL٠*XL]Lر>,.2  pYcI&zO=ձ1n{5˺p-͢[a9|*͠QMyD4d#f\諅A%o(=BL\/YV5č91*$/"6n܈xpA [n֭[}˖-_e˖~7***\ѵ>L:uHΣwk鍍"n\G, J. 'R\ ([s6^ΠJF;LPZL@rl;+͹P PH2gL0.jh?#2O/~ \qW\O=0!Hg׾5\y3f .)<2ˊ@vTF"zWʺ<$ot646Mά[`q1C`qEW.nƠsa75z*P2D~ fEaeD:6]}uRWu#ĥ5}$'"C4%]3y]+TtM~W:Io51)ӚvAw}{IXt-̃ :|n z?J:H:dv.gs.mAd fk೭1KzDa~z,֯_/%B!fgEhHYbu|\Ac썯Śs<^ǐMFלq1q5=z`oA?#gόtz+i<&݅\=sv(lZd{<9+@Da?ɕr,—:/ˮ\Iȃ|;5MiCe.p"&6!RuV&pA-ˮ~$k"&.TV0Ȃ)bENy 2:ݍц-5 r2dtoV&a`u/ևM46~BXӞMy[.#$Svf=hm,S;|7H Ѩ+-5\SxWxGd+٦770:#Ai9~v9 g݊A'sV0 D* W/AD̜8y-v^̞=*8gmַ̠jJv*)n2\,㐺P~ո{^xe bLD[tm8;mC `as `Hu3B|>g``}}}Coo8z(?>Ӂp'%KLqxG#??0hu-,y7̿w* MеE$e-W2e˨ׄx ".50K؂ Aq p5?Lя7ÇkG_p!M6ڿtR-v6md8SJ8\gr(s*,X:cЫ4hF2Y"#P$:*z.%D#Vzhl^KiR(XX x)R-&㨁A _kHY|뭷NK/d8p=9o,p:"ۖjM`Z|xy{]"3ΨBjq .)i_av jvbg…gE]T5~U4ԉܢ\WѩU>adU֌1#󞥷b`82`;ڞ_Z6ȶEDRx A/;$$L@ I70AٳGTMy9r̀dEVf<" qQdti!>!.~3hÕXy,[*7ղ#2ӶRaMHH@)8_|X~PcL$LP&\oo?5(gub$T3\B},3}s|7|7)K(mx5n`Pc8x #۹'n+ ]]]fPkސPL)â::`a[tMDq{ed[8vP6Wjf"?Z2Dz1D3F0.eDXDoo/ׇ^\|~  ,I')O'ضV?5Ιo:P+G3gά*X4('Fc =~/A-XF@=FT"GH\yVGD]ߘpW o/i8!CmJDN׿7`9IBY -YL{lk?f18g}8bh3}v5TFU"k؍ kQC-q?9b1j_`LPV"ee1{:{{oL2d[%Q[Xd"pBMU̢oB\83g] j'O4$ hs 3F"L-(s$`hY,=Ybx,$BH[;\sz0SkՑY N U7LUKIY zF#3$+,VHzss3l>~%4@aTX zyR2D2fI du.#U`E $ ˆ[zܾ\tj[l6:K)iQFJg7mw)AXz2Z\46$&+mSSSIСC%|FbpUfN'\:e_F[ :@Ă@B-BapUE/"(LFDTַ-h?^ؠ@osyn``H9HR5㓦$B3f@-XC̢DKw])~Xf1U\j&AD HQz=  <?tT~|Jg"khg!;a3LP, E1Asg2d!ZҨV@_k $=u>,V"xYb2E>kqg,'#sSW}M)A^9ӿfw?t@?S(Ooo/q~;f.&|<ى˯55%h8ܥ!.oT[J`o71?_{mowg+WJhQ0,pa-AٶvF[КÞzXF;Z8G͜WO|B>CŠ!b1 -.5~SC#NW_ oŋ1oDGzk!)'N޽{sNر;wΝ;m6?~ ! ZJZS NL|n HAeOHbÊ"i'Ҧ|n 9v~C=EK1kQ)McTƌr!S9_)d[?"l&qhL`@B5.x+(8-sڊ[o˖-^ҋSL)ShѢs>sxzj^iD'f'}4a2Dy/ S_(z_+cvdȐʚQ{siZݾZdJ0^:(ζ;e$= xƜ(H;Agkx:oIz*u]n7x#nf\f2mcٲeXl>C)]vaÆ شi:;;vZ9r8+"t֒.ࠖ1lp6 9dY/YɔTbcO۫CE4Bu h%%d3"ܩ2DUiuu1qdS :D !ɠB麌Ll"T o{w wq^!`,X|;KRظq#x <2 ]o~jp___cBDuO~vЫ9]YI`*Ds̶ $בdbg+ûv.C,<#`G?R߮YGgq{JED ~g«`a-!~lJ [)1 $o<~|lAq@Iq-`ٲex_%K*&7pn|ӟ+gyկ/bI>: IcWZf 0ᠨR+-Ao ~dvWY]Gydž+d[+u&l۶,dZ1‡d%/ q òoFXd'($ypI%)0 Pa=Ag/Z$|;G6i;wʕ+c&_!"Ղk-9 $AQNAQV+)?m| dy DZ m>zӇNAx[9L&sU> ˧=+QP$v,۲mD@&fhqbdo.\q1_blNz v11!lY#PNΈmIN Zc+`ԩZ;v&188'OV_k %X`,B(U玙fEXyL$-b7~ϾٚN[Xeܞޯ36e= uy[h_/KyaO"pӌDr!gjĂNm=LH؇Mp6pO,),!9aK- (X<)ݚXbͥSvUTrGz-qA[ b`PC2e;:vڡ˯5"7Xp0g)(X<ѧ[lZf0V g1U"{nn+so}= u.Ih:P[`@1$;47tzr6.lo0#3@1Caqn @9c@<5E7 4H8X2%xC6%M+ -Jvo͝R =%Fȁ\V0!CPPu Pv2YZАпA H!u:ԧ!)Q. }eHA Ap]0$}4N}w*'N<dutlKxr~Ԛ^eu,Ű^b>p|b;W3ef`4B%<5D\b *QƸ4IQGqᡈ-_ tcPjuR0aF,vi:7G]\yLAfσ~YLFP0$0mڴR爙َ=jH !58d%*bD9GLtVQXr& rYfOY,O߱[ (è|Zhp@$o } # A [?c⥫.(gc*Я$f͚Ç3g4kWZ6ՕkHD>RQApDΝGC=?V txD/ΜF폒KECBA'Bi+wq9j#Az[i/AǚH9PZ>͛:t&|2zpHf#_㢀jLミ_ (-%QÛ&]sZQ= Tb)2:9@ X°BƠk܋Py@YgJ!Tc`P[?~d _j!5{>Ġ%Xy`>֖PCCLyV}KGu\Ő$!|򁸉ddn3Tgķ+§RT:tԏ4I701\qm*WQ8+DB8)qegHc%d}SZAvmn`PcꫵٺuŁ"ۘ7oɤX#@i=8􄓴_Ua>$!Y;i}O=њ^eut|9, -tNu/578Y,1,몈' 1 B|_9긝l$őJ&+b;$>}3$62$Q/Oz_7lk1j4/#)MZa'd :dR eq@\a È\fDsߣ{ya[:ѕ L "wco¶q% ȞSVZ.0d2@dzXVjU7f'؈YfE9kqךA5 > "_̆UfQ-+s}_u^ 8Ey`%& sT_ \c+p mL&0yipu5$q饗FqFI_|Qo Qzw]V^ Ř7w<= +?"w~~zr,Iz";zв󸞠!m۶M5kD3w\ضm( |LH V'h LD4Ē"=è y{zo!#sZ%QF+"5eW)Vӧ$H/y=Vu20C.4o& I70A,ZHɪe c-b.Ib8 :$A}O1D$)WN/xշ˺uD.[!%H!QkhkŭZɷ`2Qr$A I70A,YD_򗓲/BU&qtKxČ\ 1:i{>:By?Wx; QL%K._Qš˰DyCʑ(bX8HRUBc*fgHA .C]]]d;6mRjҵƍZҜIt>Z@ZgmCRF4-h<^> 4誯"=NMڎTbr.د_yc g=:a.|>f)QWx"-f*2A_Ivn`PH$Xtid;Ǐ͛']ׯ_oHz`"q-ABXE߾8 WOxi+eSNY(d|oKM+.>y]`8h>B]hGO*cu9"c!ao%bI un`P;Ilذ!\yf qA&^ę_ ]ӳ01{v^Qp]ǘC]$eܚ7_f77LDft <$ZQ'r #ĥ A zdYƠ5HVjHA-oyyIҟ}Yv7"L4rWBE*Fa x?nb L_ Q+ca"'ZR:{)=rQ3 C})|eܚݑbYi e_h @y͐tō7ވv֯_CMv?Uȩe }\HϘ!4LQS2Q'ÿ/^*׷. ,L/AD!⟵t1Azv>nZDz3ᛠ3 \hH4$Fa6/^}ÀYZJp?[wuD`jr_:NVD\d( iw_&uaa,mҭoC$U/ INWGÎxe&;zą]9 l*.A;+Hy"׋ㆤ0nf-vtd,֮]v.B\s5fM ~X& :d#'&P&OPLRẈXt^Ze}i"zz֫L]>DЪmvq,Af1Aג%W\R^AQC j7t;}o5 f9 xqЯ2)=Ph@)H uT~ |hg6էނ:R<$V ^,>{_=5}btY6 z8< V [zo!5 ];ǎ~VU~i2 y%ΜqbA UBNŠ.k qv@!AD|p͉HJ[>D_:0KBŠ+*#IZ za7^_A{b0| "G읔2$`̝;7^xAKIжl23x&@["@7#h$ R LbD9B6Ji2MfO72(2H"ZH&Sڈ,[HY/8B\ˇ<"ce;y(pd>g`HA~wdb77P,#۩7;> HէN N\, o $Pmt3qJHzl\OAajAT\4>LIA zs% HK cuD(fFJK wn``Ho| _v~_bo}+9E #6L[FY@0D1 :vNqq:-(QW)q+ cz ҉Ad9vLKHjLaC!ũ̢e=HK[Z I708CmۆΪlcgg'mVUG&L;*7 Hsq "ԉ!eh*5M^*Z~ABFr\>'DE3ru,m*T7x+ c[$Una~siaHy)ShSOUetkʔ)̀9,o_-%6y|[bHDd|'ǀ\^u6<υm=_I2\AiI: @]A/a( 'E]dHy7MZJo u`P]Ҳ9^b 2:^My>ƟDu~,eU`I7-E;[.+t zPA0nr5SW}Dd+n`px;7oc=VUm{ǰi&-~~ >V5r>VSS3X8"$ 总q֡q#/'0 :~,ob˚bqaED "?qW^L._#t(:`ay8ivn`p>`ʔ)zW&6«}݇f3X Q |A^"B]"@$¯;Bټ8D'rsX1h+ TV'x+J#t(ț:} U IDATb60z 2$G>m֏>hU_;RJ_$Y$f&:yaDE-b.P<[}g믅iJ?"CK؀sB| - CY8afpC\t$ṫ:]$<&"0Vw(Ĥ7+tR-~`֭m֭[3hd,X hP."1y2=@9@Y%7*fBL >H"&h6@33O} n`pARfƇ?axWvx`5X bV;'ZH[!!< bP chNI+a-z3ӘI[(i\PE #!,qDiIdHy6m{9Z"Xz5{9mVXaGp$X(%HH 4.!{YPqITe76=LP3̸ C&97a >M4sXuI&@p{K% 4$ʆ"Ac.z89`_A=wD+d=߱5^jYC W|3f駟/~^Ъ.O -!$/ A^uf-wzÌD_ibe%D1U2y9b.[ J=Zʳ^gIKc!IqugGp!!-Z-)|DYߏ|Moŋ͠0.FPW s 4C^ 6^dJ *lйָ#c;LPuV/=!!i+k_ZY;vf} Еₙcv}D'.ЕCgƺ$$|i~(3dJY A{h23AגH1T!IC,2ʐto1{lm>ϡ/zfk]3!ZW˞/t;!_QZL=nm=)! /VWn9K$=* qa՞g-6cC34+hM?g^٩l"73]9fb108܌fo޽ԧ>kߏ={h|dՌVh;̪>(yaDEsP39_;AceE"p/W@l9~MqKx+8Ը{Z 觫NP em!)kf+_ ֬YK]jw5`F_})^vY)5eSk$]iJy1.cP 2$Rwt gy􅺁y ˲X=9>xٻaYAĭeggη!13*PxЊOyu >=Hc¦O 9aB11l( >R 2~C\bQ:f *|m;Qw I708sf逸OSut]/ޜ9sGGcP 3ŁvsԴQwu`r{j mPrZcg*AZjSW>:ڠX)|͌y,ܐtӧOǃ>͞yx{ރm6?cÆ }K_BKKɨ*kףDOBpL)cJTTi=U[aRÊ)fJ,>fɥ(yOm/1}ywj(O|'LGM" hR YyR% QPrhpՐ0L=P,>GB"鱓X1;z)iv})[B&H+_$,8]ׄ?A>9ASk&k zPI@Hpx*6- zLb+3#)/M`.!+_qb~^T:=z9vѦqm+VrBQǟ>vʱ=ڿNxoB(vQ'PwM̐tf7& ߐ\=iZI(cNu\!Ȯnġ0A2V{r/>K! y?zǾ8 t@4hN1_&=o!%Qpx vH%ȩU=x؀N #Hx$CVʔIt>co([E_U;>dy:{9V F;}C{hGE I70000b\);%!,Ja/7N IIx1LU4vr+$!Лm[nHAّ,d7.NXJjD?gidҡyx>dK](9#h- &#n~A5h]>=+(F!U_t4sa !eE6;iJK#"v%ulTőr36u*K ]Ŷ< h,(m;1OuWM[gnt50000"d2L;/LLl̬xxdwNMA9K t.V"IMRt94 F&V9.,9R‹s 5"C@R=sI-CݐtI %?dw~_M7V"D} s灈,@ht61ܾL=n哉CLЇxJك BBB"W\G}'q~e tuyAaHA5;·3>G:T]㖝xHs R !eժXIxAC˪= >'$~)0 apW-A3j\L‡@ C [DJJTw6Z=l)S]7n;1"nXݡx[ I70000f8a{1-T$ۅ+\!sy!nD!.Q u"lhGzFS_!b, RgTMÐyaWP7Ā8? n7 ^?o!*}V||`ꐄ"3hةt{[>C & "'߽_?;ws}CldS J2M X)E`-uPTw5젏gE>RE_[|Y;tO?( XD1KrcI' u+x i40x~llYr|n````0zIf V7f_zEk7z{m"/\JLbu'*Þ&,NxR[P!Q-Y,T_y 8jaQ xR4$༚g3D%;ฮs.$0)=hCezДDIq: 8IL2yMSA[ ]ٶʂ>8BU lhQC?[oD>$0 ø[;Ύ_=s2lޯ.UUxU},0.qcPVѵ7r*^m $ HXJе^VH:AjQgt\3*:囤a |@{{Ҽr7wG;:,ȥinrg=Fe $Wq讳ana@gg|$-nsYi{Leu]Ir [+ب&NIt0I7 0wN7QEYk-ɼqk 0 c zɂ t$0 0Jf]$ZuA/7nna1m=2?IU\"Z݈ 9Ir 0 czM"YZ3/{!!`upS mGEIaat*,QtIJ=:(V6 t0 0&Q 0Ar~8Iݽ1gG<< ;C.(^{menaFfc@г^d&^e_$@e$EF -k^Sp*}*ȣAҙx ΢La w,=MG+IqDB#eqQr_=rO|I\}ooOe<( r:&aar36@zVYu*]2D˽~*q?V['ID"xonnaluvZ9z719D**ڎrjt9 7$mAqV$0 0foע$LkUk_Z$FLxq9<:Sߨ"aa*nAMgYPZ&aadu LeAp6}ZZr&.&&a1C)v42],UJ}ZNP&mSʕtI7 0Th"Whon%JmkR~/uh).7Ǣ&P*P(P*(xu4\.GCCMMMr9@cʈ!(.k74RBب6A߼i͗.2ԁ7LҧBS8y$gϞΝ;顧/rҥBaʯ9ٳ={6mmm̝;?>c,\n f7```ӧOsΜ9Coo/ϟ9zzz8{,ϟjFQ4pdܶ1{l̙C[[ͻnq,]fg#X$Zy%S6T{`t"c=Jww7o&o&>@uzfey7Z[[{?̊+?իYr%ЇlCCC8p`d:tÇ3mWE#,̛7e˖|r^/_Κ5kXbfͲcBFONY.畔Z*FͽxO.]=zǏs 9‘#G8~8|u)&3>Ǿ}{nѢE,];3%Kd-[wͲe˘={u`ѣ#c;v{cǎqرi;bk׮ϟ]t)w}]`u1l~5ī~inA_MW𶙑Izb޽޽={/gUԩS:uW_}u-ZڵkY~==ׯg…qeNv52vw"d*ΝܹscYx17nfݺu_V}]z-9bQ)m6m6ؒ%KXb+V`\+Wr]wQeA/ǿeo`~W jOl ɿegե޽{ٹs' ۷o>%yb>6}}}Ͻc=Ϛ5kXz5vuQ%T&%A7թCN&A!Y8,'$=T*/ݻw[ epp]v]o<3 k׮\ո{\|L'Amu=AP"J*"H ~8+ADp5W[4TQOuaV:prʼn ~0߸d' lJ~|AЫHtZYOգ#@p\ &m# BxCyJ0/`þXW+;`aӖ[H+ zֶK>vMq]v1o`|=D ̈́6/n%-uMATPu8sI1rnnaUay=!ArtL*ws/FvhB5D VxKBg7/ϚK|h "Oؙ/UcI&aaT*sZomr2,fi;eO9B ?sXm}%`[?n{?'zЖK^_"^sldaӊ,).ՙ MZ,4@/Dž¿W~ѽ߾m>UnItUG򸣳]~Kf'8ZL}>)X$0 0R͊*i[($YO >: [7TqʦP:vF"tOnr?sφuZGA<ꇋk5eI7 0[3l _T&:4Η|suC*;3o#xyjgڃ{{~Y=!+ͺ@'0 t0 ø5<] Xu,|o0KTZ|jkЌZ֩'0n'-a(;c:7;M;~W A`ۣ z,&a1S^ɖ3]9A-^tMSƷ2ֈ }|_vBymYǏbPtF\T"&&a1cqJrus4e!z(z}Z'7xRǴ;8%Rd"]Cľth|@AA״OGOXut0 Ø/S:'rJwazK%).UܤTA%&/AE~> [u;.?עݰ{I]lS#t0 0,^o7 ט g_<5D7/NUG M 0 cF7e=%j7R͊ }&i@fy狨"A>6łq2;k*.Ju]jna3$7ƹ4ZV'T+ dʼnP QO9PEP=PoKd0+hna,HKԕ/^",yY}Be˔Y_ot~I)"$([e%ǥӫ"N^ߣA/oc5vPHRkJc:ȑd@hHkHQGKz F[Lc4yǮKwxܶ_[0n=Φc"B(Xf[!)"^U}.}fk]JEz Q[Mp8'ӯgס)F ۀ{%gsQp8M5]GveQ.3|6NۏGН?u".UEc, 8ab]+}aEƹ^d$䓓:Mb$A^?J:#3bM`Dg{q3Zǀ|7jc:~ߟ}QʧY7c.xX|?ް@:s?v__9y5 'C5fi[k-N@˹:b^DC_\eAuzֶzO&B1֞uOtklr=x7p%C1`7F? %=B"0[I~7$q[Z?D=I|Tu$QIRffJ5';oI.uEx5=>8tJӣ^zc@Fk 2MKkOA;HgM[ m+JsUuy@6 +#X~nnc7YꦂtiɅʓLBX8<zIa`I7cq$Qio!im'ظE/] )SE٭O4 «fZhh6*&6$ǁMN TEر||XCT="_L&gE.XTnLg9>hCu~ݗƨi<ĕDgOu#ƨ'L;k4o#.(ˤ&z7+,:Q2/|^]Iů0ι_RB+TQ4At[k]u]Q7gLd3I"BEO\+.JeFIȿ1s)q%M/F=~?C$Qϑl3D7H>"*k$~pGRanL!)Y+?e^nq"4,G0n%HsD(4OO!vM]#"tH;kʵ5$Q#,_&(ݵL^O_㰑*C}]]ds H?)/}iZj8_x(?tPiױks:$QWI]F-`dqv,Ә*I돎:nAMH"_Eҷ3.ᳮ\,8ܨ='QQ iNp',k1-A@Пs婣>sXIN*աw)apQjxf9_?)׿_ Ԃ%$mv,F=̜gdd?ZuTG}#=,5%}xխq "{/*7כW%pyc𕋧wE1i *I*G7Kk|B8e@K#{]Ra1aQe+$ I4֒^o^'1tĪ84n{lT3A7 E>LaǺe~to_pſM.skc(²*g9!.Fg=t-aL$uf_lH=xSE"ء՗-&F^*|P ߽Ot7tNx%.ni44(QWO*.Qnþ_jna3Wy~ףk7S-/%,+:^Dg ő)2J)%i$7Jqtw.Q>n6*PLaQh5TU _|ٟ҆!`)I}FNF-T~ Z}ZI{zIaٷyX$0 0";#ݵ.^:{b34b{cIꆖ*+ݰDfڨH˔mZ:̶7m]oԯUӉk}#)|oׂIaa7]vC ^4WDjG l{LրHJ,).*kѵPz҅_iنa1MYs7r ~_9}\d֚kvZ k6T#AkDKb]rOdܺ0 0|>ΝDŽ\*ߦz]O8U+ײ?Ũ2'%|tfBϵ~om\4X$0 0)J7^ODcT}դf3 zi/A*#f(( lN}SOϷaa@3صΆ]sg(P.m5=kzmV4y^ SX=@sz)us?~L 0 Øo#ĺu[7Wqn>QW@L K'Cm7I+X#A/xUDcЇ>r9}oNaQmQ-͏^{[!|!/:W:ezQi.Oez<Z{/ҁ/I^ժ na">q|ï~~Ο=M[#'JɗPCu3HгWv<^>UTcD hr_ meU}6=7I7 0 cٶ=ho?#)0k݇h'p-_Ȭ\1 E dVAJ7Tŷc¬С/>/aWŁ?n R< wznnaF[plE%MhS~Ӯ5B!NRMvNBDQ=O {j=t@cbR7~ǜ|l&N_}7L 0 èGYO뻌« Y kJ'և 7r "Y7}ME&:uGUr$ /F~];BCxUYj t0 0okhoGds _g|t柌%|\)=^xG njOFEYVA+ G"!H@  JI?P~}/ |ǎ 瘫`)-&aa:xX6A|i}ƅaGL EQPN:J{m'Uh+^# 'eE7OB'#{F[ۅ* $0 0[O5p&ǓOM6?ZK?q N_LkZr}C{T#$k\I5rŻ*_뛓M'#rM4\dg h9AwrtR˥m7eCR>ݙ\A;97I7 0 c ``w8)8#!BKp^-%M"ɑo^QT\8Lkgy%:.c4\a{dD y#RQtZcCb6OŇf-'e#rl\&茇&aada;5%Gmk358PA˽b@B=1U$ URgN ]zE诉GZI1H$EGMߒF=$ UPG@!G('b8 \pKT|[S\?|NVB/sO;  䒪^%DzK/Л5ZGsŸL [Y?(+g$qݺnz&aaw-ucB}BǸ`j5-m&iqa⥁YM.n yF6щx|a#8U "s} 21"H!"R4Az Q<w~su 5Wܫ3[ sc ?yEgIENDB`python-legacy-0.2.3/docs/snippets/000077500000000000000000000000001424444364000171015ustar00rootroot00000000000000python-legacy-0.2.3/docs/snippets/function_annotations_google.py000066400000000000000000000007501424444364000252530ustar00rootroot00000000000000from typing import Optional def my_function(param1: int, param2: Optional[str] = None) -> str: """A short description of this function. Arguments: param1: An integer? param2: A string? If you have a long description, you can split it on multiple lines. Just remember to indent those lines consistently. Complex markup is supported in sections items. I'm a code block! """ return f"{param2}{param1}" python-legacy-0.2.3/docs/snippets/function_annotations_rst.py000066400000000000000000000006331424444364000246070ustar00rootroot00000000000000from typing import Optional def my_function(param1: int, param2: Optional[str] = None) -> str: """A short description of this function. Complex markup is supported in the main description section. I'm a code block! :param param1: An integer? :param param2: A string? If you have a long description, you can split it on multiple lines. """ return f"{param2}{param1}" python-legacy-0.2.3/docs/usage.md000066400000000000000000000326261424444364000166730ustar00rootroot00000000000000# Usage WARNING: **This is the documentation for the LEGACY Python handler.** To read the documentation for the NEW handler, go to the [new handler documentation](https://mkdocstrings.github.io/python). The tool used by the legacy Python handler to collect documentation from Python source code is [`pytkdocs`](https://mkdocstrings.github.io/pytkdocs). It stands for *(Python) Take Docs*, and is supposed to be a pun on MkDocs (*Make Docs*?). Like every handler, the legacy Python handler accepts both **global** and **local** options. ## Global-only options Some options are **global only**, and go directly under the handler's name. - `import`: this option is used to import Sphinx-compatible objects inventories from other documentation sites. For example, you can import the standard library objects inventory like this: ```yaml title="mkdocs.yml" plugins: - mkdocstrings: handlers: python: import: - https://docs.python-requests.org/en/master/objects.inv ``` When importing an inventory, you enable automatic cross-references to other documentation sites like the standard library docs or any third-party package docs. Typically, you want to import the inventories of your project's dependencies, at least those that are used in the public API. NOTE: This global option is common to *all* handlers, however they might implement it differently (or not even implement it). - `paths`: this option is used to provide filesystem paths in which to search for Python modules. Non-absolute paths are computed as relative to MkDocs configuration file. Example: ```yaml title="mkdocs.yml" plugins: - mkdocstrings: handlers: python: paths: [src] # search packages in the src folder ``` More details at [Finding modules](#finding-modules). - `setup_commands`: this option is used to instruct `pytkdocs`, the tool responsible for collecting data from sources, to run Python statements before starting to collect data. It is declared as a list of strings: ```yaml title="mkdocs.yml" plugins: - mkdocstrings: handlers: python: setup_commands: - import os - import django - os.environ.setdefault("DJANGO_SETTINGS_MODULE", "my_django_app.settings") - django.setup() ``` The setup commands are executed only once, when the `pytkdocs` background process is started. ## Global/local options The other options can be used both globally *and* locally, under the `options` key. For example, globally: ```yaml title="mkdocs.yml" plugins: - mkdocstrings: handlers: python: options: do_something: true ``` ...and locally, overriding the global configuration: ```md title="docs/some_page.md" ::: package.module.class options: do_something: false ``` These options affect how the documentation is collected from sources and renderered: headings, members, docstrings, etc. ::: mkdocstrings_handlers.python.handler.PythonHandler.default_config options: show_root_toc_entry: false ## Supported docstrings styles Right now, `pytkdocs` supports the Google-style, Numpy-style and reStructuredText-style docstring formats. The style used by default is the Google-style. You can configure what style you want to use with the `docstring_style` and `docstring_options` options, both globally or per autodoc instruction. ### Google-style You can see examples of Google-style docstrings in [Napoleon's documentation](https://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_google.html). #### Sections Docstrings sections are parsed by `pytkdocs` and rendered by *mkdocstrings*. Supported sections are: - `Arguments` (or `Args`, `Parameters`, `Params`) - `Attributes` - `Examples` (or `Example`) - `Raises` (or `Raise`, `Except`, `Exceptions`) - `Returns` (or `Return`) #### Admonitions Additionally, any section that is not recognized will be transformed into its admonition equivalent. For example: === "Original" ```python """ Note: You can disable this behavior with the `replace_admonitions` option. To prevent `pytkdocs` from converting sections to admonitions, use the `replace_admonitions`: ```md ::: my_package.my_module selection: docstring_style: google # this is the default docstring_options: replace_admonitions: no ``` So meta! """ ``` === "Modified" ```python """ !!! note "You can disable this behavior with the `replace_admonitions` option." To prevent `pytkdocs` from converting sections to admonitions, use the `replace_admonitions`: ```md ::: my_package.my_module selection: docstring_style: google # this is the default docstring_options: replace_admonitions: no ``` So meta! """ ``` === "Result" > NOTE: **You can disable this behavior with the `replace_admonitions` parser option.** > To prevent `pytkdocs` from converting sections to admonitions, > use the `replace_admonitions` parser option: > > ```md > ::: my_package.my_module > selection: > docstring_style: google # this is the default > docstring_options: > replace_admonitions: no > ``` > > So meta! As shown in the above example, this can be disabled with the `replace_admonitions` option of the Google-style parser: ```yaml ::: my_package.my_module selection: docstring_style: google # this is the default docstring_options: replace_admonitions: no ``` #### Annotations Type annotations are read both in the code and in the docstrings. > EXAMPLE: **Example with a function** > **Expand the source at the end to see the original code!** > > ::: snippets.function_annotations_google:my_function > rendering: > show_root_heading: no > show_root_toc_entry: no ### Numpy-style IMPORTANT: **Extra dependency required** You'll need an extra dependency to parse Numpy-style docstrings: ``` pdm add -d --group docs 'pytkdocs[numpy-style]' poetry add -D 'pytkdocs[numpy-style]' pip install 'pytkdocs[numpy-style]' # etc. ``` NOTE: As Numpy-style is partially supported by the underlying parser, you may experience problems in the building process if your docstring has a `Methods` section in the class docstring (see [#366](https://github.com/mkdocstrings/mkdocstrings/issues/366)). You can see examples of Numpy-style docstrings in [numpydoc's documentation](https://numpydoc.readthedocs.io/en/latest/format.html). ### reStructuredText-style WARNING: **Partial support** Only RST-**style** is supported, not the whole RST markup specification. You can see examples of reStructuredText-style docstrings in [Sphinx's documentation](https://sphinx-rtd-tutorial.readthedocs.io/en/latest/docstrings.html). #### Sections Docstrings directives are parsed by `pytkdocs` and rendered by *mkdocstrings*. Supported directives are: - `param` (or `parameter`, `arg`, `argument`, `key`, `keyword`) - `type` - `raises` (or `raise`, `except`, `exception`) - `var` (or `ivar`, `cvar`) - `vartype` - `returns` (or `return1`) - `rtype` Details about how to use each directive can be found in the [Sphinx domain documentation](https://www.sphinx-doc.org/en/master/usage/restructuredtext/domains.html?highlight=python%20domain#info-field-lists) #### Annotations Type annotations are read both in the code and in the docstrings. > EXAMPLE: **Example with a function** > **Expand the source at the end to see the original code!** > > ::: snippets.function_annotations_rst:my_function > options: > docstring_style: restructured-text > show_root_heading: no > show_root_toc_entry: no ## Finding modules There are multiple ways to tell the handler where to find your packages/modules. **The recommended method is to use the `paths` option, as it's the only one that works with the `-f` option of MkDocs, allowing to build the documentation from any location on the file system.** Indeed, the paths provided with the `paths` option are computed as relative to the configuration file (mkdocs.yml), so that the current working directory has no impact on the build process: *you can build the docs from any location on your filesystem*. ### Using the `paths` option TIP: **This is the recommended method.** 1. mkdocs.yml in root, package in root ```tree root/ mkdocs.yml package/ ``` ```yaml title="mkdocs.yml" plugins: - mkdocstrings: handlers: python: paths: [.] # actually not needed, default ``` 1. mkdocs.yml in root, package in subfolder ```tree root/ mkdocs.yml src/ package/ ``` ```yaml title="mkdocs.yml" plugins: - mkdocstrings: handlers: python: paths: [src] ``` 1. mkdocs.yml in subfolder, package in root ```tree root/ docs/ mkdocs.yml package/ ``` ```yaml title="mkdocs.yml" plugins: - mkdocstrings: handlers: python: paths: [..] ``` 1. mkdocs.yml in subfolder, package in subfolder ```tree root/ docs/ mkdocs.yml src/ package/ ``` ```yaml title="mkdocs.yml" plugins: - mkdocstrings: handlers: python: paths: [../src] ``` Except for case 1, which is supported by default, **we strongly recommend to set the path to your packages using this option, even if it works without it** (for example because your project manager automatically adds `src` to PYTHONPATH), to make sure anyone can build your docs from any location on their filesystem. Behind the scenes, the handler will actually insert the specified paths in front of `sys.path`. ### Using the PYTHONPATH environment variable WARNING: **This method has limitations.** This method might work for you, with your current setup, but not for others trying your build your docs with their own setup/environment. We recommend to use the [`paths` method](#using-the-paths-option) instead. You can take advantage of the usual Python loading mechanisms. In Bash and other shells, you can run your command like this (note the prepended `PYTHONPATH=...`): 1. mkdocs.yml in root, package in root ```tree root/ mkdocs.yml package/ ``` ```bash PYTHONPATH=. mkdocs build # actually not needed, default ``` 1. mkdocs.yml in root, package in subfolder ```tree root/ mkdocs.yml src/ package/ ``` ```bash PYTHONPATH=src mkdocs build ``` 1. mkdocs.yml in subfolder, package in root ```tree root/ docs/ mkdocs.yml package/ ``` ```bash PYTHONPATH=. mkdocs build -f docs/mkdocs.yml ``` 1. mkdocs.yml in subfolder, package in subfolder ```tree root/ docs/ mkdocs.yml src/ package/ ``` ```bash PYTHONPATH=src mkdocs build -f docs/mkdocs.yml ``` ### Installing your package in the current Python environment WARNING: **This method has limitations.** This method might work for you, with your current setup, but not for others trying your build your docs with their own setup/environment. We recommend to use the [`paths` method](#using-the-paths-option) instead. Install your package in the current environment, and run MkDocs: === "pip" ```bash . venv/bin/activate pip install -e . mkdocs build ``` === "PDM" ```bash pdm install pdm run mkdocs build ``` === "Poetry" ```bash poetry install poetry run mkdocs build ``` ### Using the setup commands WARNING: **This method has limitations.** This method might work for you, with your current setup, but not for others trying your build your docs with their own setup/environment. We recommend to use the [`paths` method](#using-the-paths-option) instead. You can use the setup commands to modify `sys.path`: ```yaml title="mkdocs.yml" plugins: - mkdocstrings: handlers: python: setup_commands: - import sys - sys.path.append("src") # or sys.path.insert(0, "src") ``` ## Mocking libraries You may want to generate documentation for a package while its dependencies are not available. The Python handler provides itself no builtin way to mock libraries, but you can use the `setup_commands` to mock them manually: ```yaml title="mkdocs.yml" plugins: - mkdocstrings: handlers: python: setup_commands: - import sys - from unittest.mock import MagicMock as mock - sys.modules["lib1"] = mock() - sys.modules["lib2"] = mock() - sys.modules["lib2.module1"] = mock() - sys.modules["lib2.module1.moduleB"] = mock() # etc ``` ## Recommended style (Material) Here are some CSS rules for the [*Material for MkDocs*](https://squidfunk.github.io/mkdocs-material/) theme: ```css /* Indentation. */ div.doc-contents:not(.first) { padding-left: 25px; border-left: .05rem solid var(--md-typeset-table-color); } ``` ## Recommended style (ReadTheDocs) Here are some CSS rules for the built-in *ReadTheDocs* theme: ```css /* Indentation. */ div.doc-contents:not(.first) { padding-left: 25px; border-left: 4px solid rgba(230, 230, 230); } ``` python-legacy-0.2.3/duties.py000066400000000000000000000257601424444364000161650ustar00rootroot00000000000000"""Development tasks.""" import importlib import os import re import sys import tempfile from contextlib import suppress from io import StringIO from pathlib import Path from typing import List, Optional, Pattern from urllib.request import urlopen from duty import duty PY_SRC_PATHS = (Path(_) for _ in ("src", "tests", "duties.py", "docs")) PY_SRC_LIST = tuple(str(_) for _ in PY_SRC_PATHS) PY_SRC = " ".join(PY_SRC_LIST) TESTING = os.environ.get("TESTING", "0") in {"1", "true"} CI = os.environ.get("CI", "0") in {"1", "true", "yes", ""} WINDOWS = os.name == "nt" PTY = not WINDOWS and not CI def _latest(lines: List[str], regex: Pattern) -> Optional[str]: for line in lines: match = regex.search(line) if match: return match.groupdict()["version"] return None def _unreleased(versions, last_release): for index, version in enumerate(versions): if version.tag == last_release: return versions[:index] return versions def update_changelog( inplace_file: str, marker: str, version_regex: str, template_url: str, ) -> None: """ Update the given changelog file in place. Arguments: inplace_file: The file to update in-place. marker: The line after which to insert new contents. version_regex: A regular expression to find currently documented versions in the file. template_url: The URL to the Jinja template used to render contents. """ from git_changelog.build import Changelog from git_changelog.commit import AngularStyle from jinja2.sandbox import SandboxedEnvironment AngularStyle.DEFAULT_RENDER.insert(0, AngularStyle.TYPES["build"]) env = SandboxedEnvironment(autoescape=False) template_text = urlopen(template_url).read().decode("utf8") # noqa: S310 template = env.from_string(template_text) changelog = Changelog(".", style="angular") if len(changelog.versions_list) == 1: last_version = changelog.versions_list[0] if last_version.planned_tag is None: planned_tag = "0.1.0" last_version.tag = planned_tag last_version.url += planned_tag last_version.compare_url = last_version.compare_url.replace("HEAD", planned_tag) with open(inplace_file, "r") as changelog_file: lines = changelog_file.read().splitlines() last_released = _latest(lines, re.compile(version_regex)) if last_released: changelog.versions_list = _unreleased(changelog.versions_list, last_released) rendered = template.render(changelog=changelog, inplace=True) lines[lines.index(marker)] = rendered with open(inplace_file, "w") as changelog_file: # noqa: WPS440 changelog_file.write("\n".join(lines).rstrip("\n") + "\n") @duty def changelog(ctx): """ Update the changelog in-place with latest commits. Arguments: ctx: The context instance (passed automatically). """ commit = "166758a98d5e544aaa94fda698128e00733497f4" template_url = f"https://raw.githubusercontent.com/pawamoy/jinja-templates/{commit}/keepachangelog.md" ctx.run( update_changelog, kwargs={ "inplace_file": "CHANGELOG.md", "marker": "", "version_regex": r"^## \[v?(?P[^\]]+)", "template_url": template_url, }, title="Updating changelog", pty=PTY, ) @duty(pre=["check_quality", "check_types", "check_docs", "check_dependencies"]) def check(ctx): """ Check it all! Arguments: ctx: The context instance (passed automatically). """ @duty def check_quality(ctx, files=PY_SRC): """ Check the code quality. Arguments: ctx: The context instance (passed automatically). files: The files to check. """ ctx.run(f"flake8 --config=config/flake8.ini {files}", title="Checking code quality", pty=PTY) @duty def check_dependencies(ctx): """ Check for vulnerabilities in dependencies. Arguments: ctx: The context instance (passed automatically). """ # undo possible patching # see https://github.com/pyupio/safety/issues/348 for module in sys.modules: # noqa: WPS528 if module.startswith("safety.") or module == "safety": del sys.modules[module] # noqa: WPS420 importlib.invalidate_caches() # reload original, unpatched safety from safety.formatter import report from safety.safety import check as safety_check from safety.util import read_requirements # retrieve the list of dependencies requirements = ctx.run( ["pdm", "export", "-f", "requirements", "--without-hashes"], title="Exporting dependencies as requirements", allow_overrides=False, ) # check using safety as a library def safety(): # noqa: WPS430 packages = list(read_requirements(StringIO(requirements))) vulns = safety_check(packages=packages, ignore_ids="", key="", db_mirror="", cached=False, proxy={}) output_report = report(vulns=vulns, full=True, checked_packages=len(packages)) if vulns: print(output_report) ctx.run(safety, title="Checking dependencies") @duty def check_docs(ctx): """ Check if the documentation builds correctly. Arguments: ctx: The context instance (passed automatically). """ Path("htmlcov").mkdir(parents=True, exist_ok=True) Path("htmlcov/index.html").touch(exist_ok=True) ctx.run("mkdocs build -s", title="Building documentation", pty=PTY) @duty # noqa: WPS231 def check_types(ctx): # noqa: WPS231 """ Check that the code is correctly typed. Arguments: ctx: The context instance (passed automatically). """ # NOTE: the following code works around this issue: # https://github.com/python/mypy/issues/10633 # compute packages directory path py = f"{sys.version_info.major}.{sys.version_info.minor}" pkgs_dir = Path("__pypackages__", py, "lib").resolve() # build the list of available packages packages = {} for package in pkgs_dir.glob("*"): if package.suffix not in {".dist-info", ".pth"} and package.name != "__pycache__": packages[package.name] = package # handle .pth files for pth in pkgs_dir.glob("*.pth"): with suppress(OSError): for package in Path(pth.read_text().splitlines()[0]).glob("*"): # noqa: WPS440 if package.suffix != ".dist-info": packages[package.name] = package # create a temporary directory to assign to MYPYPATH with tempfile.TemporaryDirectory() as tmpdir: # symlink the stubs ignore = set() for stubs in (path for name, path in packages.items() if name.endswith("-stubs")): # noqa: WPS335 Path(tmpdir, stubs.name).symlink_to(stubs, target_is_directory=True) # try to symlink the corresponding package # see https://www.python.org/dev/peps/pep-0561/#stub-only-packages pkg_name = stubs.name.replace("-stubs", "") if pkg_name in packages: ignore.add(pkg_name) Path(tmpdir, pkg_name).symlink_to(packages[pkg_name], target_is_directory=True) # create temporary mypy config to ignore stubbed packages newconfig = Path("config", "mypy.ini").read_text() newconfig += "\n" + "\n\n".join(f"[mypy-{pkg}.*]\nignore_errors=true" for pkg in ignore) tmpconfig = Path(tmpdir, "mypy.ini") tmpconfig.write_text(newconfig) # set MYPYPATH and run mypy os.environ["MYPYPATH"] = tmpdir ctx.run(f"mypy --config-file {tmpconfig} {PY_SRC}", title="Type-checking", pty=PTY) @duty(silent=True) def clean(ctx): """ Delete temporary files. Arguments: ctx: The context instance (passed automatically). """ ctx.run("rm -rf .coverage*") ctx.run("rm -rf .mypy_cache") ctx.run("rm -rf .pytest_cache") ctx.run("rm -rf tests/.pytest_cache") ctx.run("rm -rf build") ctx.run("rm -rf dist") ctx.run("rm -rf htmlcov") ctx.run("rm -rf pip-wheel-metadata") ctx.run("rm -rf site") ctx.run("find . -type d -name __pycache__ | xargs rm -rf") ctx.run("find . -name '*.rej' -delete") @duty def docs(ctx): """ Build the documentation locally. Arguments: ctx: The context instance (passed automatically). """ ctx.run("mkdocs build", title="Building documentation") @duty def docs_serve(ctx, host="127.0.0.1", port=8000): """ Serve the documentation (localhost:8000). Arguments: ctx: The context instance (passed automatically). host: The host to serve the docs from. port: The port to serve the docs on. """ ctx.run(f"mkdocs serve -a {host}:{port}", title="Serving documentation", capture=False) @duty def docs_deploy(ctx): """ Deploy the documentation on GitHub pages. Arguments: ctx: The context instance (passed automatically). """ ctx.run("mkdocs gh-deploy", title="Deploying documentation") @duty def format(ctx): """ Run formatting tools on the code. Arguments: ctx: The context instance (passed automatically). """ ctx.run( f"autoflake -ir --exclude tests/fixtures --remove-all-unused-imports {PY_SRC}", title="Removing unused imports", pty=PTY, ) ctx.run(f"isort {PY_SRC}", title="Ordering imports", pty=PTY) ctx.run(f"black {PY_SRC}", title="Formatting code", pty=PTY) @duty def release(ctx, version): """ Release a new Python package. Arguments: ctx: The context instance (passed automatically). version: The new version number to use. """ ctx.run("git add pyproject.toml CHANGELOG.md", title="Staging files", pty=PTY) ctx.run(["git", "commit", "-m", f"chore: Prepare release {version}"], title="Committing changes", pty=PTY) ctx.run(f"git tag {version}", title="Tagging commit", pty=PTY) if not TESTING: ctx.run("git push", title="Pushing commits", pty=False) ctx.run("git push --tags", title="Pushing tags", pty=False) ctx.run("pdm build", title="Building dist/wheel", pty=PTY) ctx.run("twine upload --skip-existing dist/*", title="Publishing version", pty=PTY) docs_deploy.run() @duty(silent=True) def coverage(ctx): """ Report coverage as text and HTML. Arguments: ctx: The context instance (passed automatically). """ ctx.run("coverage combine", nofail=True) ctx.run("coverage report --rcfile=config/coverage.ini", capture=False) ctx.run("coverage html --rcfile=config/coverage.ini") @duty def test(ctx, match: str = ""): """ Run the test suite. Arguments: ctx: The context instance (passed automatically). match: A pytest expression to filter selected tests. """ py_version = f"{sys.version_info.major}{sys.version_info.minor}" os.environ["COVERAGE_FILE"] = f".coverage.{py_version}" ctx.run( ["pytest", "-c", "config/pytest.ini", "-n", "auto", "-k", match, "tests"], title="Running tests", pty=PTY, ) python-legacy-0.2.3/logo.png000077700000000000000000000000001424444364000203432docs/logo.pngustar00rootroot00000000000000python-legacy-0.2.3/mkdocs.yml000066400000000000000000000037541424444364000163200ustar00rootroot00000000000000site_name: "mkdocstrings-python (legacy)" site_description: "A legacy Python handler for mkdocstrings." site_url: "https://mkdocstrings.github.io/python-legacy" repo_url: "https://github.com/mkdocstrings/python-legacy" repo_name: "mkdocstrings/python-legacy" site_dir: "site" watch: [README.md, CONTRIBUTING.md, CHANGELOG.md, src] nav: - Home: - Overview: index.md - Usage: usage.md - Changelog: changelog.md - Credits: credits.md - License: license.md # defer to gen-files + literate-nav - Code Reference: reference/ - Development: - Contributing: contributing.md - Code of Conduct: code_of_conduct.md - Coverage report: coverage.md - mkdocstrings: https://mkdocstrings.github.io/ theme: name: material icon: logo: material/currency-sign features: - navigation.tabs - navigation.tabs.sticky - navigation.top palette: - media: "(prefers-color-scheme: light)" scheme: default primary: teal accent: purple toggle: icon: material/weather-sunny name: Switch to dark mode - media: "(prefers-color-scheme: dark)" scheme: slate primary: black accent: lime toggle: icon: material/weather-night name: Switch to light mode extra_css: - css/material.css - css/mkdocstrings.css markdown_extensions: - admonition - callouts - pymdownx.emoji - pymdownx.magiclink - pymdownx.snippets: check_paths: true - pymdownx.superfences - pymdownx.tabbed: alternate_style: true - pymdownx.tasklist - toc: permalink: "¤" plugins: - search - markdown-exec - gen-files: scripts: - docs/gen_ref_nav.py - literate-nav: nav_file: SUMMARY.md - coverage - section-index - mkdocstrings: handlers: python: paths: [src, docs] import: - https://mkdocstrings.github.io/objects.inv - https://mkdocstrings.github.io/pytkdocs/objects.inv extra: social: - icon: fontawesome/brands/github link: https://github.com/pawamoy - icon: fontawesome/brands/twitter link: https://twitter.com/pawamoy python-legacy-0.2.3/pyproject.toml000066400000000000000000000056421424444364000172270ustar00rootroot00000000000000[build-system] requires = ["pdm-pep517"] build-backend = "pdm.pep517.api" [project] name = "mkdocstrings-python-legacy" description = "A legacy Python handler for mkdocstrings." authors = [{name = "Timothée Mazzucotelli", email = "pawamoy@pm.me"}] license-expression = "ISC" readme = "README.md" requires-python = ">=3.7" keywords = [] dynamic = ["version"] classifiers = [ "Development Status :: 4 - Beta", "Intended Audience :: Developers", "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Topic :: Documentation", "Topic :: Software Development", "Topic :: Software Development :: Documentation", "Topic :: Utilities", "Typing :: Typed", ] dependencies = [ "mkdocstrings>=0.19", "pytkdocs>=0.14", ] [project.urls] Homepage = "https://mkdocstrings.github.io/python-legacy" Documentation = "https://mkdocstrings.github.io/python-legacy" Changelog = "https://mkdocstrings.github.io/python-legacy/changelog" Repository = "https://github.com/mkdocstrings/python-legacy" Issues = "https://github.com/mkdocstrings/python-legacy/issues" Discussions = "https://github.com/mkdocstrings/python-legacy/discussions" Gitter = "https://gitter.im/mkdocstrings/community" Funding = "https://github.com/sponsors/pawamoy" [tool.pdm] version = {use_scm = true} includes = ["src/mkdocstrings_handlers"] editable-backend = "editables" [tool.pdm.dev-dependencies] duty = ["duty>=0.7"] docs = [ "mkdocs>=1.3", "mkdocs-coverage>=0.2", "mkdocs-gen-files>=0.3", "mkdocs-literate-nav>=0.4", "mkdocs-material>=7.3", "mkdocs-section-index>=0.3", "markdown-callouts>=0.2", "markdown-exec>=0.5", "toml>=0.10", ] format = [ "autoflake>=1.4", "black>=21.10b0", "isort>=5.10", ] maintain = [ "git-changelog>=0.4", ] quality = [ "darglint>=1.8", "flake8-bandit>=2.1", "flake8-black>=0.2", "flake8-bugbear>=21.9", "flake8-builtins>=1.5", "flake8-comprehensions>=3.7", "flake8-docstrings>=1.6", "flake8-pytest-style>=1.5", "flake8-string-format>=0.3", "flake8-tidy-imports>=4.5", "flake8-variables-names>=0.0", "pep8-naming>=0.12", "wps-light>=0.15", ] tests = [ "pytest>=6.2", "pytest-cov>=3.0", "pytest-randomly>=3.10", "pytest-xdist>=2.4", ] typing = [ "mypy>=0.910", "types-markdown>=3.3", "types-toml>=0.10", ] security = ["safety>=1.10"] [tool.black] line-length = 120 exclude = "tests/fixtures" [tool.isort] line_length = 120 not_skip = "__init__.py" multi_line_output = 3 force_single_line = false balanced_wrapping = true default_section = "THIRDPARTY" known_first_party = "mkdocstrings" include_trailing_comma = true python-legacy-0.2.3/scripts/000077500000000000000000000000001424444364000157735ustar00rootroot00000000000000python-legacy-0.2.3/scripts/gen_credits.py000066400000000000000000000076341424444364000206450ustar00rootroot00000000000000import re from itertools import chain from pathlib import Path from textwrap import dedent import toml from jinja2 import StrictUndefined from jinja2.sandbox import SandboxedEnvironment try: from importlib.metadata import metadata, PackageNotFoundError except ImportError: from importlib_metadata import metadata, PackageNotFoundError project_dir = Path(".") pyproject = toml.load(project_dir / "pyproject.toml") project = pyproject["project"] pdm = pyproject["tool"]["pdm"] lock_data = toml.load(project_dir / "pdm.lock") lock_pkgs = {pkg["name"].lower(): pkg for pkg in lock_data["package"]} project_name = project["name"] regex = re.compile(r"(?P[\w.-]+)(?P.*)$") def get_license(pkg_name): try: data = metadata(pkg_name) except PackageNotFoundError: return "?" license = data.get("License", "").strip() multiple_lines = bool(license.count("\n")) # TODO: remove author logic once all my packages licenses are fixed author = "" if multiple_lines or not license or license == "UNKNOWN": for header, value in data.items(): if header == "Classifier" and value.startswith("License ::"): license = value.rsplit("::", 1)[1].strip() elif header == "Author-email": author = value if license == "Other/Proprietary License" and "pawamoy" in author: license = "ISC" return license or "?" def get_deps(base_deps): deps = {} for dep in base_deps: parsed = regex.match(dep).groupdict() dep_name = parsed["dist"].lower() deps[dep_name] = {"license": get_license(dep_name), **parsed, **lock_pkgs[dep_name]} again = True while again: again = False for pkg_name in lock_pkgs: if pkg_name in deps: for pkg_dependency in lock_pkgs[pkg_name].get("dependencies", []): parsed = regex.match(pkg_dependency).groupdict() dep_name = parsed["dist"].lower() if dep_name not in deps: deps[dep_name] = {"license": get_license(dep_name), **parsed, **lock_pkgs[dep_name]} again = True return deps dev_dependencies = get_deps(chain(*pdm.get("dev-dependencies", {}).values())) prod_dependencies = get_deps( chain( project.get("dependencies", []), chain(*project.get("optional-dependencies", {}).values()), ) ) template_data = { "project_name": project_name, "prod_dependencies": sorted(prod_dependencies.values(), key=lambda dep: dep["name"]), "dev_dependencies": sorted(dev_dependencies.values(), key=lambda dep: dep["name"]), "more_credits": "http://pawamoy.github.io/credits/", } template_text = dedent( """ These projects were used to build `{{ project_name }}`. **Thank you!** [`python`](https://www.python.org/) | [`pdm`](https://pdm.fming.dev/) | [`copier-pdm`](https://github.com/pawamoy/copier-pdm) {% macro dep_line(dep) -%} [`{{ dep.name }}`](https://pypi.org/project/{{ dep.name }}/) | {{ dep.summary }} | {{ ("`" ~ dep.spec ~ "`") if dep.spec else "" }} | `{{ dep.version }}` | {{ dep.license }} {%- endmacro %} ### Runtime dependencies Project | Summary | Version (accepted) | Version (last resolved) | License ------- | ------- | ------------------ | ----------------------- | ------- {% for dep in prod_dependencies -%} {{ dep_line(dep) }} {% endfor %} ### Development dependencies Project | Summary | Version (accepted) | Version (last resolved) | License ------- | ------- | ------------------ | ----------------------- | ------- {% for dep in dev_dependencies -%} {{ dep_line(dep) }} {% endfor %} {% if more_credits %}**[More credits from the author]({{ more_credits }})**{% endif %} """ ) jinja_env = SandboxedEnvironment(undefined=StrictUndefined) print(jinja_env.from_string(template_text).render(**template_data)) python-legacy-0.2.3/scripts/multirun.sh000077500000000000000000000014561424444364000202170ustar00rootroot00000000000000#!/usr/bin/env bash set -e PYTHON_VERSIONS="${PYTHON_VERSIONS-3.7 3.8 3.9 3.10 3.11}" restore_previous_python_version() { if pdm use -f "$1" &>/dev/null; then echo "> Restored previous Python version: ${1##*/}" fi } if [ -n "${PYTHON_VERSIONS}" ]; then old_python_version="$(pdm config python.path)" echo "> Currently selected Python version: ${old_python_version##*/}" trap "restore_previous_python_version ${old_python_version}" EXIT for python_version in ${PYTHON_VERSIONS}; do if pdm use -f "python${python_version}" &>/dev/null; then echo "> pdm run $@ (python${python_version})" pdm run "$@" else echo "> pdm use -f python${python_version}: Python interpreter not available?" >&2 fi done else pdm run "$@" fi python-legacy-0.2.3/scripts/setup.sh000077500000000000000000000020771424444364000175000ustar00rootroot00000000000000#!/usr/bin/env bash set -e PYTHON_VERSIONS="${PYTHON_VERSIONS-3.7 3.8 3.9 3.10 3.11}" install_with_pipx() { if ! command -v "$1" &>/dev/null; then if ! command -v pipx &>/dev/null; then python3 -m pip install --user pipx fi pipx install "$1" fi } install_with_pipx pdm restore_previous_python_version() { if pdm use -f "$1" &>/dev/null; then echo "> Restored previous Python version: ${1##*/}" fi } if [ -n "${PYTHON_VERSIONS}" ]; then if old_python_version="$(pdm config python.path 2>/dev/null)"; then echo "> Currently selected Python version: ${old_python_version##*/}" trap "restore_previous_python_version ${old_python_version}" EXIT fi for python_version in ${PYTHON_VERSIONS}; do if pdm use -f "python${python_version}" &>/dev/null; then echo "> Using Python ${python_version} interpreter" pdm install else echo "> pdm use -f python${python_version}: Python interpreter not available?" >&2 fi done else pdm install fi python-legacy-0.2.3/src/000077500000000000000000000000001424444364000150735ustar00rootroot00000000000000python-legacy-0.2.3/src/mkdocstrings_handlers/000077500000000000000000000000001424444364000214625ustar00rootroot00000000000000python-legacy-0.2.3/src/mkdocstrings_handlers/py.typed000066400000000000000000000000001424444364000231470ustar00rootroot00000000000000python-legacy-0.2.3/src/mkdocstrings_handlers/python/000077500000000000000000000000001424444364000230035ustar00rootroot00000000000000python-legacy-0.2.3/src/mkdocstrings_handlers/python/__init__.py000066400000000000000000000002521424444364000251130ustar00rootroot00000000000000"""This package implements a handler for the Python language.""" from mkdocstrings_handlers.python.handler import get_handler __all__ = ["get_handler"] # noqa: WPS410 python-legacy-0.2.3/src/mkdocstrings_handlers/python/handler.py000066400000000000000000000362201424444364000247750ustar00rootroot00000000000000"""This module implements a handler for the Python language. It collects data with [`pytkdocs`](https://github.com/pawamoy/pytkdocs). """ from __future__ import annotations import json import os import posixpath import sys import traceback from collections import ChainMap from subprocess import PIPE, Popen # noqa: S404 from typing import Any, BinaryIO, Iterator, List, Optional, Sequence, Tuple from markdown import Markdown from mkdocstrings.extension import PluginError from mkdocstrings.handlers.base import BaseHandler, CollectionError, CollectorItem from mkdocstrings.inventory import Inventory from mkdocstrings.loggers import get_logger from mkdocstrings_handlers.python.rendering import ( do_brief_xref, rebuild_category_lists, sort_key_alphabetical, sort_key_source, sort_object, ) # TODO: add a deprecation warning once the new handler handles 95% of use-cases logger = get_logger(__name__) class PythonHandler(BaseHandler): """The Python handler class. Attributes: domain: The cross-documentation domain/language for this handler. enable_inventory: Whether this handler is interested in enabling the creation of the `objects.inv` Sphinx inventory file. """ domain: str = "py" # to match Sphinx's default domain enable_inventory: bool = True fallback_theme = "material" fallback_config = {"docstring_style": "markdown", "filters": ["!.*"]} """The configuration used when falling back to re-collecting an object to get its anchor. This configuration is used in [`Handlers.get_anchors`][mkdocstrings.handlers.base.Handlers.get_anchors]. When trying to fix (optional) cross-references, the autorefs plugin will try to collect an object with every configured handler until one succeeds. It will then try to get an anchor for it. It's because objects can have multiple identifiers (aliases), for example their definition path and multiple import paths in Python. When re-collecting the object, we have no use for its members, or for its docstring being parsed. This is why the fallback configuration filters every member out, and uses the Markdown style, which we know will not generate any warnings. """ default_config: dict = { "filters": ["!^_[^_]"], "show_root_heading": False, "show_root_toc_entry": True, "show_root_full_path": True, "show_root_members_full_path": False, "show_object_full_path": False, "show_category_heading": False, "show_if_no_docstring": False, "show_signature": True, "show_signature_annotations": False, "show_source": True, "show_bases": True, "group_by_category": True, "heading_level": 2, "members_order": "alphabetical", } """ **Headings options:** - `heading_level` (`int`): The initial heading level to use. Default: `2`. - `show_root_heading` (`bool`): Show the heading of the object at the root of the documentation tree (i.e. the object referenced by the identifier after `:::`). Default: `False`. - `show_root_toc_entry` (`bool`): If the root heading is not shown, at least add a ToC entry for it. Default: `True`. - `show_root_full_path` (`bool`): Show the full Python path for the root object heading. Default: `True`. - `show_root_members_full_path` (`bool`): Show the full Python path of the root members. Default: `False`. - `show_object_full_path` (`bool`): Show the full Python path of every object. Default: `False`. - `show_category_heading` (`bool`): When grouped by categories, show a heading for each category. Default: `False`. **Members options:** - `members` (`list[str] | False | None`): An explicit list of members to render. Default: `None`. - `members_order` (`str`): The members ordering to use. Options: `alphabetical` - order by the members names, `source` - order members as they appear in the source file. Default: `"alphabetical"`. - `filters` (`list[str] | None`): A list of filters applied to filter objects based on their name. A filter starting with `!` will exclude matching objects instead of including them. The `members` option takes precedence over `filters` (filters will still be applied recursively to lower members in the hierarchy). Default: `["!^_[^_]"]`. - `group_by_category` (`bool`): Group the object's children by categories: attributes, classes, functions, and modules. Default: `True`. **Docstrings options:** - `docstring_style` (`str`): The docstring style to use: `google`, `numpy`, `sphinx`, or `None`. Default: `"google"`. - `docstring_options` (`dict`): The options for the docstring parser. See parsers under [`pytkdocs.parsers.docstrings`][]. - `show_if_no_docstring` (`bool`): Show the object heading even if it has no docstring or children with docstrings. Default: `False`. **Signatures/annotations options:** - `show_signature` (`bool`): Show methods and functions signatures. Default: `True`. - `show_signature_annotations` (`bool`): Show the type annotations in methods and functions signatures. Default: `False`. **Additional options:** - `show_bases` (`bool`): Show the base classes of a class. Default: `True`. - `show_source` (`bool`): Show the source code of this object. Default: `True`. """ # noqa: E501 def __init__( # noqa: WPS231 self, *args, setup_commands: Optional[List[str]] = None, config_file_path: str | None = None, paths: list[str] | None = None, **kwargs, ) -> None: """Initialize the handler. When instantiating a Python handler, we open a `pytkdocs` subprocess in the background with `subprocess.Popen`. It will allow us to feed input to and read output from this subprocess, keeping it alive during the whole documentation generation. Spawning a new Python subprocess for each "autodoc" instruction would be too resource intensive, and would slow down `mkdocstrings` a lot. Parameters: *args: Handler name, theme and custom templates. setup_commands: A list of python commands as strings to be executed in the subprocess before `pytkdocs`. config_file_path: The MkDocs configuration file path. paths: A list of paths to use as search paths. **kwargs: Same thing, but with keyword arguments. """ logger.debug("Opening 'pytkdocs' subprocess") env = os.environ.copy() env["PYTHONUNBUFFERED"] = "1" self._config_file_path = config_file_path paths = paths or [] if not paths and config_file_path: paths.append(os.path.dirname(config_file_path)) search_paths = [] for path in paths: if not os.path.isabs(path): if config_file_path: path = os.path.abspath(os.path.join(os.path.dirname(config_file_path), path)) if path not in search_paths: search_paths.append(path) self._paths = search_paths commands = [] if search_paths: commands.extend([f"sys.path.insert(0, {path!r})" for path in reversed(search_paths)]) # noqa: WPS441 if setup_commands: # prevent the Python interpreter or the setup commands # from writing to stdout as it would break pytkdocs output commands.extend( [ "from io import StringIO", "sys.stdout = StringIO()", # redirect stdout to memory buffer *setup_commands, "sys.stdout.flush()", "sys.stdout = sys.__stdout__", # restore stdout ] ) if commands: final_commands = [ "import sys", *commands, "from pytkdocs.cli import main as pytkdocs", "pytkdocs(['--line-by-line'])", ] cmd = [sys.executable, "-c", "; ".join(final_commands)] else: cmd = [sys.executable, "-m", "pytkdocs", "--line-by-line"] self.process = Popen( # noqa: S603,S607 (we trust the input, and we don't want to use the absolute path) cmd, universal_newlines=True, stdout=PIPE, stdin=PIPE, bufsize=-1, env=env, ) super().__init__(*args, **kwargs) @classmethod def load_inventory( cls, in_file: BinaryIO, url: str, base_url: Optional[str] = None, **kwargs ) -> Iterator[Tuple[str, str]]: """Yield items and their URLs from an inventory file streamed from `in_file`. This implements mkdocstrings' `load_inventory` "protocol" (see plugin.py). Arguments: in_file: The binary file-like object to read the inventory from. url: The URL that this file is being streamed from (used to guess `base_url`). base_url: The URL that this inventory's sub-paths are relative to. **kwargs: Ignore additional arguments passed from the config. Yields: Tuples of (item identifier, item URL). """ if base_url is None: base_url = posixpath.dirname(url) for item in Inventory.parse_sphinx(in_file, domain_filter=("py",)).values(): # noqa: WPS526 yield item.name, posixpath.join(base_url, item.uri) def collect(self, identifier: str, config: dict) -> CollectorItem: # noqa: WPS231 """Collect the documentation tree given an identifier and selection options. In this method, we feed one line of JSON to the standard input of the subprocess that was opened during instantiation of the collector. Then we read one line of JSON on its standard output. We load back the JSON text into a Python dictionary. If there is a decoding error, we log it as error and raise a CollectionError. If the dictionary contains an `error` key, we log it as error (with the optional `traceback` value), and raise a CollectionError. If the dictionary values for keys `loading_errors` and `parsing_errors` are not empty, we log them as warnings. Then we pick up the only object within the `objects` list (there's always only one, because we collect them one by one), rebuild it's categories lists (see [`rebuild_category_lists()`][mkdocstrings_handlers.python.rendering.rebuild_category_lists]), and return it. Arguments: identifier: The dotted-path of a Python object available in the Python path. config: Selection options, used to alter the data collection done by `pytkdocs`. Raises: CollectionError: When there was a problem collecting the object documentation. Returns: The collected object-tree. """ final_config = {} for option in ("filters", "members"): if option in config: final_config[option] = config[option] elif option in self.default_config: final_config[option] = self.default_config[option] logger.debug("Preparing input") json_input = json.dumps({"objects": [{"path": identifier, **final_config}]}) logger.debug("Writing to process' stdin") self.process.stdin.write(json_input + "\n") # type: ignore self.process.stdin.flush() # type: ignore logger.debug("Reading process' stdout") stdout = self.process.stdout.readline() # type: ignore logger.debug("Loading JSON output as Python object") try: result = json.loads(stdout) except json.decoder.JSONDecodeError as exception: error = "\n".join(("Error while loading JSON:", stdout, traceback.format_exc())) raise CollectionError(error) from exception if "error" in result: error = result["error"] if "traceback" in result: error += f"\n{result['traceback']}" raise CollectionError(error) for loading_error in result["loading_errors"]: logger.warning(loading_error) for errors in result["parsing_errors"].values(): for parsing_error in errors: logger.warning(parsing_error) # We always collect only one object at a time result = result["objects"][0] logger.debug("Rebuilding categories and children lists") rebuild_category_lists(result) return result def teardown(self) -> None: """Terminate the opened subprocess, set it to `None`.""" logger.debug("Tearing process down") self.process.terminate() def render(self, data: CollectorItem, config: dict) -> str: # noqa: D102 (ignore missing docstring) final_config = ChainMap(config, self.default_config) template = self.env.get_template(f"{data['category']}.html") # Heading level is a "state" variable, that will change at each step # of the rendering recursion. Therefore, it's easier to use it as a plain value # than as an item in a dictionary. heading_level = final_config["heading_level"] members_order = final_config["members_order"] if members_order == "alphabetical": sort_function = sort_key_alphabetical elif members_order == "source": sort_function = sort_key_source else: raise PluginError(f"Unknown members_order '{members_order}', choose between 'alphabetical' and 'source'.") sort_object(data, sort_function=sort_function) return template.render( **{"config": final_config, data["category"]: data, "heading_level": heading_level, "root": True}, ) def get_anchors(self, data: CollectorItem) -> Sequence[str]: # noqa: D102 (ignore missing docstring) try: return (data["path"],) except KeyError: return () def update_env(self, md: Markdown, config: dict) -> None: # noqa: D102 (ignore missing docstring) super().update_env(md, config) self.env.trim_blocks = True self.env.lstrip_blocks = True self.env.keep_trailing_newline = False self.env.filters["brief_xref"] = do_brief_xref def get_handler( theme: str, # noqa: W0613 (unused argument config) custom_templates: Optional[str] = None, setup_commands: Optional[List[str]] = None, config_file_path: str | None = None, paths: list[str] | None = None, **config: Any, ) -> PythonHandler: """Simply return an instance of `PythonHandler`. Arguments: theme: The theme to use when rendering contents. custom_templates: Directory containing custom templates. setup_commands: A list of commands as strings to be executed in the subprocess before `pytkdocs`. config_file_path: The MkDocs configuration file path. paths: A list of paths to use as search paths. config: Configuration passed to the handler. Returns: An instance of `PythonHandler`. """ return PythonHandler( handler="python", theme=theme, custom_templates=custom_templates, setup_commands=setup_commands, config_file_path=config_file_path, paths=paths, ) python-legacy-0.2.3/src/mkdocstrings_handlers/python/rendering.py000066400000000000000000000064511424444364000253400ustar00rootroot00000000000000"""This module implements rendering utilities.""" from __future__ import annotations import sys from typing import Any, Callable from markupsafe import Markup from mkdocstrings.handlers.base import CollectorItem from mkdocstrings.loggers import get_logger log = get_logger(__name__) def do_brief_xref(path: str) -> Markup: """Filter to create cross-reference with brief text and full identifier as hover text. Arguments: path: The path to shorten and render. Returns: A span containing the brief cross-reference and the full one on hover. """ brief = path.split(".")[-1] return Markup("{brief}").format(path=path, brief=brief) def sort_object(obj: CollectorItem, sort_function: Callable[[CollectorItem], Any]) -> None: """Sort the collected object's children. Sorts the object's children list, then each category separately, and then recurses into each. Arguments: obj: The collected object, as a dict. Note that this argument is mutated. sort_function: The sort key function used to determine the order of elements. """ obj["children"].sort(key=sort_function) for category in ("attributes", "classes", "functions", "methods", "modules"): obj[category].sort(key=sort_function) for child in obj["children"]: sort_object(child, sort_function=sort_function) def sort_key_alphabetical(item: CollectorItem) -> Any: """Return an item's name or the final unicode character. Arguments: item: A collected item. Returns: Name or final unicode character. """ # chr(sys.maxunicode) is a string that contains the final unicode # character, so if 'name' isn't found on the object, the item will go to # the end of the list. return item.get("name", chr(sys.maxunicode)) def sort_key_source(item: CollectorItem) -> Any: """Return an item's starting line number or -1. Arguments: item: A collected item. Returns: Starting line number or -1. """ # if 'line_start' isn't found on the object, the item will go to # the start of the list. return item.get("source", {}).get("line_start", -1) def rebuild_category_lists(obj: dict) -> None: """Recursively rebuild the category lists of a collected object. Since `pytkdocs` dumps JSON on standard output, it must serialize the object-tree and flatten it to reduce data duplication and avoid cycle-references. Indeed, each node of the object-tree has a `children` list, containing all children, and another list for each category of children: `attributes`, `classes`, `functions`, `methods` and `modules`. It replaces the values in category lists with only the paths of the objects. Here, we reconstruct these category lists by picking objects in the `children` list using their path. For each object, we recurse on every one of its children. Arguments: obj: The collected object, loaded back from JSON into a Python dictionary. """ for category in ("attributes", "classes", "functions", "methods", "modules"): obj[category] = [obj["children"][path] for path in obj[category]] obj["children"] = [child for _, child in obj["children"].items()] for child in obj["children"]: rebuild_category_lists(child) python-legacy-0.2.3/src/mkdocstrings_handlers/python/templates/000077500000000000000000000000001424444364000250015ustar00rootroot00000000000000python-legacy-0.2.3/src/mkdocstrings_handlers/python/templates/material/000077500000000000000000000000001424444364000265775ustar00rootroot00000000000000python-legacy-0.2.3/src/mkdocstrings_handlers/python/templates/material/attribute.html000066400000000000000000000034151424444364000314730ustar00rootroot00000000000000{{ log.debug() }} {% if config.show_if_no_docstring or attribute.has_contents %}
{% with html_id = attribute.path %} {% if not root or config.show_root_heading %} {% if root %} {% set show_full_path = config.show_root_full_path %} {% set root_members = True %} {% elif root_members %} {% set show_full_path = config.show_root_members_full_path or config.show_object_full_path %} {% set root_members = False %} {% else %} {% set show_full_path = config.show_object_full_path %} {% endif %} {% filter heading(heading_level, role="data" if obj == module else "attr", id=html_id, class="doc doc-heading", toc_label=attribute.name) %} {% filter highlight(language="python", inline=True) %} {% if show_full_path %}{{ attribute.path }}{% else %}{{ attribute.name }}{% endif %} {% if attribute.type %}: {{ attribute.type }}{% endif %} {% endfilter %} {% with properties = attribute.properties %} {% include "properties.html" with context %} {% endwith %} {% endfilter %} {% else %} {% if config.show_root_toc_entry %} {% filter heading(heading_level, role="data" if obj == module else "attr", id=html_id, toc_label=attribute.path, hidden=True) %} {% endfilter %} {% endif %} {% set heading_level = heading_level - 1 %} {% endif %}
{% with docstring_sections = attribute.docstring_sections %} {% include "docstring.html" with context %} {% endwith %}
{% endwith %}
{% endif %} python-legacy-0.2.3/src/mkdocstrings_handlers/python/templates/material/attributes.html000066400000000000000000000007771424444364000316660ustar00rootroot00000000000000{{ log.debug() }}

Attributes:

{% for attribute in attributes %} {% endfor %}
Name Type Description
{{ attribute.name }} {% if attribute.annotation %}{{ attribute.annotation }}{% endif %} {{ attribute.description|convert_markdown(heading_level, html_id) }}
python-legacy-0.2.3/src/mkdocstrings_handlers/python/templates/material/children.html000066400000000000000000000063161424444364000312630ustar00rootroot00000000000000{{ log.debug() }} {% if obj.children %}
{% if config.group_by_category %} {% with %} {% if config.show_category_heading %} {% set extra_level = 1 %} {% else %} {% set extra_level = 0 %} {% endif %} {% if config.show_category_heading and obj.attributes|any("has_contents") %} {% filter heading(heading_level, id=html_id ~ "-attributes") %}Attributes{% endfilter %} {% endif %} {% with heading_level = heading_level + extra_level %} {% for attribute in obj.attributes %} {% include "attribute.html" with context %} {% endfor %} {% endwith %} {% if config.show_category_heading and obj.classes|any("has_contents") %} {% filter heading(heading_level, id=html_id ~ "-classes") %}Classes{% endfilter %} {% endif %} {% with heading_level = heading_level + extra_level %} {% for class in obj.classes %} {% include "class.html" with context %} {% endfor %} {% endwith %} {% if config.show_category_heading and obj.functions|any("has_contents") %} {% filter heading(heading_level, id=html_id ~ "-functions") %}Functions{% endfilter %} {% endif %} {% with heading_level = heading_level + extra_level %} {% for function in obj.functions %} {% include "function.html" with context %} {% endfor %} {% endwith %} {% if config.show_category_heading and obj.methods|any("has_contents") %} {% filter heading(heading_level, id=html_id ~ "-methods") %}Methods{% endfilter %} {% endif %} {% with heading_level = heading_level + extra_level %} {% for method in obj.methods %} {% include "method.html" with context %} {% endfor %} {% endwith %} {% if config.show_category_heading and obj.modules|any("has_contents") %} {% filter heading(heading_level, id=html_id ~ "-modules") %}Modules{% endfilter %} {% endif %} {% with heading_level = heading_level + extra_level %} {% for module in obj.modules %} {% include "module.html" with context %} {% endfor %} {% endwith %} {% endwith %} {% else %} {% for child in obj.children %} {% if child.category == "attribute" %} {% with attribute = child %} {% include "attribute.html" with context %} {% endwith %} {% elif child.category == "class" %} {% with class = child %} {% include "class.html" with context %} {% endwith %} {% elif child.category == "function" %} {% with function = child %} {% include "function.html" with context %} {% endwith %} {% elif child.category == "method" %} {% with method = child %} {% include "method.html" with context %} {% endwith %} {% elif child.category == "module" %} {% with module = child %} {% include "module.html" with context %} {% endwith %} {% endif %} {% endfor %} {% endif %}
{% endif %} python-legacy-0.2.3/src/mkdocstrings_handlers/python/templates/material/class.html000066400000000000000000000044521424444364000305770ustar00rootroot00000000000000{{ log.debug() }} {% if config.show_if_no_docstring or class.has_contents %}
{% with html_id = class.path %} {% if not root or config.show_root_heading %} {% if root %} {% set show_full_path = config.show_root_full_path %} {% set root_members = True %} {% elif root_members %} {% set show_full_path = config.show_root_members_full_path or config.show_object_full_path %} {% set root_members = False %} {% else %} {% set show_full_path = config.show_object_full_path %} {% endif %} {% filter heading(heading_level, role="class", id=html_id, class="doc doc-heading", toc_label=class.name) %} {% if show_full_path %}{{ class.path }}{% else %}{{ class.name }}{% endif %} {% if config.show_bases and class.bases and class.bases != ['object'] %} ({% for base in class.bases -%} {{ base|brief_xref() }}{% if not loop.last %}, {% endif %} {% endfor %}) {% endif %} {% with properties = class.properties %} {% include "properties.html" with context %} {% endwith %} {% endfilter %} {% else %} {% if config.show_root_toc_entry %} {% filter heading(heading_level, role="class", id=html_id, toc_label=class.path, hidden=True) %} {% endfilter %} {% endif %} {% set heading_level = heading_level - 1 %} {% endif %}
{% with docstring_sections = class.docstring_sections %} {% include "docstring.html" with context %} {% endwith %} {% if config.show_source and class.source %}
Source code in {{ class.relative_file_path }} {{ class.source.code|highlight(language="python", linestart=class.source.line_start, linenums=False) }}
{% endif %} {% with obj = class %} {% set root = False %} {% set heading_level = heading_level + 1 %} {% include "children.html" with context %} {% endwith %}
{% endwith %}
{% endif %} python-legacy-0.2.3/src/mkdocstrings_handlers/python/templates/material/docstring.html000066400000000000000000000024641424444364000314670ustar00rootroot00000000000000{{ log.debug() }} {% if docstring_sections %} {% for section in docstring_sections %} {% if section.type == "markdown" %} {{ section.value|convert_markdown(heading_level, html_id) }} {% elif section.type == "attributes" %} {% with attributes = section.value %} {% include "attributes.html" with context %} {% endwith %} {% elif section.type == "parameters" %} {% with parameters = section.value %} {% include "parameters.html" with context %} {% endwith %} {% elif section.type == "keyword_args" %} {% with kwargs = section.value %} {% include "keyword_args.html" with context %} {% endwith %} {% elif section.type == "exceptions" %} {% with exceptions = section.value %} {% include "exceptions.html" with context %} {% endwith %} {% elif section.type == "yield" %} {% with yield = section.value %} {% include "yield.html" with context %} {% endwith %} {% elif section.type == "return" %} {% with return = section.value %} {% include "return.html" with context %} {% endwith %} {% elif section.type == "examples" %} {% with examples = section.value %} {% include "examples.html" with context %} {% endwith %} {% endif %} {% endfor %} {% endif %} python-legacy-0.2.3/src/mkdocstrings_handlers/python/templates/material/examples.html000066400000000000000000000005171424444364000313060ustar00rootroot00000000000000{{ log.debug() }}

Examples:

{% for section_type, sub_section in examples %} {% if section_type == "markdown" %} {{ sub_section|convert_markdown(heading_level, html_id) }} {% elif section_type == "examples" %} {{ sub_section|highlight(language="python", linenums=False) }} {% endif %} {% endfor %} python-legacy-0.2.3/src/mkdocstrings_handlers/python/templates/material/exceptions.html000066400000000000000000000006201424444364000316440ustar00rootroot00000000000000{{ log.debug() }}

Exceptions:

{% for exception in exceptions %} {% endfor %}
Type Description
{{ exception.annotation }} {{ exception.description|convert_markdown(heading_level, html_id) }}
python-legacy-0.2.3/src/mkdocstrings_handlers/python/templates/material/function.html000066400000000000000000000041211424444364000313100ustar00rootroot00000000000000{{ log.debug() }} {% if config.show_if_no_docstring or function.has_contents %}
{% with html_id = function.path %} {% if not root or config.show_root_heading %} {% if root %} {% set show_full_path = config.show_root_full_path %} {% set root_members = True %} {% elif root_members %} {% set show_full_path = config.show_root_members_full_path or config.show_object_full_path %} {% set root_members = False %} {% else %} {% set show_full_path = config.show_object_full_path %} {% endif %} {% filter heading(heading_level, role="function", id=html_id, class="doc doc-heading", toc_label=function.name ~ "()") %} {% filter highlight(language="python", inline=True) %} {% if show_full_path %}{{ function.path }}{% else %}{{ function.name }}{% endif %} {% with signature = function.signature %}{% include "signature.html" with context %}{% endwith %} {% endfilter %} {% with properties = function.properties %} {% include "properties.html" with context %} {% endwith %} {% endfilter %} {% else %} {% if config.show_root_toc_entry %} {% filter heading(heading_level, role="function", id=html_id, toc_label=function.path, hidden=True) %} {% endfilter %} {% endif %} {% set heading_level = heading_level - 1 %} {% endif %}
{% with docstring_sections = function.docstring_sections %} {% include "docstring.html" with context %} {% endwith %} {% if config.show_source and function.source %}
Source code in {{ function.relative_file_path }} {{ function.source.code|highlight(language="python", linestart=function.source.line_start, linenums=False) }}
{% endif %}
{% endwith %}
{% endif %} python-legacy-0.2.3/src/mkdocstrings_handlers/python/templates/material/keyword_args.html000066400000000000000000000007561424444364000321750ustar00rootroot00000000000000{{ log.debug() }}

Keyword arguments:

{% for kwarg in kwargs %} {% endfor %}
Name Type Description
{{ kwarg.name }} {% if kwarg.annotation %}{{ kwarg.annotation }}{% endif %} {{ kwarg.description|convert_markdown(heading_level, html_id) }}
python-legacy-0.2.3/src/mkdocstrings_handlers/python/templates/material/method.html000066400000000000000000000040611424444364000307460ustar00rootroot00000000000000{{ log.debug() }} {% if config.show_if_no_docstring or method.has_contents %}
{% with html_id = method.path %} {% if not root or config.show_root_heading %} {% if root %} {% set show_full_path = config.show_root_full_path %} {% set root_members = True %} {% elif root_members %} {% set show_full_path = config.show_root_members_full_path or config.show_object_full_path %} {% set root_members = False %} {% else %} {% set show_full_path = config.show_object_full_path %} {% endif %} {% filter heading(heading_level, role="method", id=html_id, class="doc doc-heading", toc_label=method.name ~ "()") %} {% filter highlight(language="python", inline=True) %} {% if show_full_path %}{{ method.path }}{% else %}{{ method.name }}{% endif %} {% with signature = method.signature %}{% include "signature.html" with context %}{% endwith %} {% endfilter %} {% with properties = method.properties %} {% include "properties.html" with context %} {% endwith %} {% endfilter %} {% else %} {% if config.show_root_toc_entry %} {% filter heading(heading_level, role="method", id=html_id, toc_label=method.path, hidden=True) %} {% endfilter %} {% endif %} {% set heading_level = heading_level - 1 %} {% endif %}
{% with docstring_sections = method.docstring_sections %} {% include "docstring.html" with context %} {% endwith %} {% if config.show_source and method.source %}
Source code in {{ method.relative_file_path }} {{ method.source.code|highlight(language="python", linestart=method.source.line_start, linenums=False) }}
{% endif %}
{% endwith %}
{% endif %} python-legacy-0.2.3/src/mkdocstrings_handlers/python/templates/material/module.html000066400000000000000000000033461424444364000307600ustar00rootroot00000000000000{{ log.debug() }} {% if config.show_if_no_docstring or module.has_contents %}
{% with html_id = module.path %} {% if not root or config.show_root_heading %} {% if root %} {% set show_full_path = config.show_root_full_path %} {% set root_members = True %} {% elif root_members %} {% set show_full_path = config.show_root_members_full_path or config.show_object_full_path %} {% set root_members = False %} {% else %} {% set show_full_path = config.show_object_full_path %} {% endif %} {% filter heading(heading_level, role="module", id=html_id, class="doc doc-heading", toc_label=module.name) %} {% if show_full_path %}{{ module.path }}{% else %}{{ module.name }}{% endif %} {% with properties = module.properties %} {% include "properties.html" with context %} {% endwith %} {% endfilter %} {% else %} {% if config.show_root_toc_entry %} {% filter heading(heading_level, role="module", id=html_id, toc_label=module.path, hidden=True) %} {% endfilter %} {% endif %} {% set heading_level = heading_level - 1 %} {% endif %}
{% with docstring_sections = module.docstring_sections %} {% include "docstring.html" with context %} {% endwith %} {% with obj = module %} {% set root = False %} {% set heading_level = heading_level + 1 %} {% include "children.html" with context %} {% endwith %}
{% endwith %}
{% endif %} python-legacy-0.2.3/src/mkdocstrings_handlers/python/templates/material/parameters.html000066400000000000000000000012141424444364000316260ustar00rootroot00000000000000{{ log.debug() }}

Parameters:

{% for parameter in parameters %} {% endfor %}
Name Type Description Default
{{ parameter.name }} {% if parameter.annotation %}{{ parameter.annotation }}{% endif %} {{ parameter.description|convert_markdown(heading_level, html_id) }} {% if parameter.default %}{{ parameter.default }}{% else %}required{% endif %}
python-legacy-0.2.3/src/mkdocstrings_handlers/python/templates/material/properties.html000066400000000000000000000003741424444364000316650ustar00rootroot00000000000000{{ log.debug() }} {% if properties %} {% for property in properties %} {{ property }} {% endfor %} {% endif %} python-legacy-0.2.3/src/mkdocstrings_handlers/python/templates/material/return.html000066400000000000000000000005551424444364000310110ustar00rootroot00000000000000{{ log.debug() }}

Returns:

Type Description
{% if return.annotation %}{{ return.annotation }}{% endif %} {{ return.description|convert_markdown(heading_level, html_id) }}
python-legacy-0.2.3/src/mkdocstrings_handlers/python/templates/material/signature.html000066400000000000000000000026261424444364000314740ustar00rootroot00000000000000{{ log.debug() }} {%- if signature and config.show_signature -%} {%- with -%} {%- set ns = namespace(render_pos_only_separator=True, render_kw_only_separator=True, equal="=") -%} {%- if config.show_signature_annotations -%} {%- set ns.equal = " = " -%} {%- endif -%} ({%- for parameter in signature.parameters %}{% if parameter.kind == "POSITIONAL_ONLY" -%} {%- if ns.render_pos_only_separator -%} {%- set ns.render_pos_only_separator = False %}/, {% endif -%} {%- elif parameter.kind == "KEYWORD_ONLY" -%} {%- if ns.render_kw_only_separator -%} {%- set ns.render_kw_only_separator = False %}*, {% endif -%} {%- endif -%} {%- if config.show_signature_annotations and "annotation" in parameter -%} {%- set annotation = ": " + parameter.annotation|safe -%} {%- endif -%} {%- if "default" in parameter -%} {%- set default = ns.equal + parameter.default|safe -%} {%- endif -%} {%- if parameter.kind == "VAR_POSITIONAL" %}* {%- set render_kw_only_separator = False -%} {%- elif parameter.kind == "VAR_KEYWORD" %}** {%- endif %}{{ parameter.name }}{{ annotation }}{{ default }}{% if not loop.last %}, {% endif -%} {%- endfor %}){% if config.show_signature_annotations and "return_annotation" in signature %} -> {{ signature.return_annotation }} {%- endif -%} {%- endwith -%} {%- endif -%} python-legacy-0.2.3/src/mkdocstrings_handlers/python/templates/material/style.css000066400000000000000000000005241424444364000304520ustar00rootroot00000000000000/* Don't capitalize names. */ h5.doc-heading { text-transform: none !important; } /* Avoid breaking parameters name, etc. in table cells. */ .doc-contents td code { word-break: normal !important; } /* For pieces of Markdown rendered in table cells. */ .doc-contents td p { margin-top: 0 !important; margin-bottom: 0 !important; } python-legacy-0.2.3/src/mkdocstrings_handlers/python/templates/material/yield.html000066400000000000000000000005511424444364000305740ustar00rootroot00000000000000{{ log.debug() }}

Yields:

Type Description
{% if yield.annotation %}{{ yield.annotation }}{% endif %} {{ yield.description|convert_markdown(heading_level, html_id) }}
python-legacy-0.2.3/src/mkdocstrings_handlers/python/templates/mkdocs/000077500000000000000000000000001424444364000262615ustar00rootroot00000000000000python-legacy-0.2.3/src/mkdocstrings_handlers/python/templates/mkdocs/exceptions.html000066400000000000000000000003401424444364000313250ustar00rootroot00000000000000{{ log.debug() }}
Exceptions:
{% for exception in exceptions %}
{{ ("`" + exception.annotation + "`: " + exception.description)|convert_markdown(heading_level, html_id) }}
{% endfor %}
python-legacy-0.2.3/src/mkdocstrings_handlers/python/templates/mkdocs/keyword_args.html000066400000000000000000000004251424444364000316500ustar00rootroot00000000000000{{ log.debug() }}
Keyword arguments:
{% for kwarg in kwargs %}
{{ ("**" + kwarg.name + ":** " + ("`" + kwarg.annotation + "` – " if kwarg.annotation else "") + kwarg.description)|convert_markdown(heading_level, html_id) }}
{% endfor %}
python-legacy-0.2.3/src/mkdocstrings_handlers/python/templates/mkdocs/parameters.html000066400000000000000000000004461424444364000313160ustar00rootroot00000000000000{{ log.debug() }}
Parameters:
{% for parameter in parameters %}
{{ ("**" + parameter.name + ":** " + ("`" + parameter.annotation + "` – " if parameter.annotation else "") + parameter.description)|convert_markdown(heading_level, html_id) }}
{% endfor %}
python-legacy-0.2.3/src/mkdocstrings_handlers/python/templates/mkdocs/return.html000066400000000000000000000003101424444364000304600ustar00rootroot00000000000000{{ log.debug() }}
Returns:
{{ (("`" + return.annotation + "` – " if return.annotation else "") + return.description)|convert_markdown(heading_level, html_id) }}
python-legacy-0.2.3/src/mkdocstrings_handlers/python/templates/mkdocs/style.css000066400000000000000000000002111424444364000301250ustar00rootroot00000000000000.doc-contents { padding-left: 20px; } .doc-contents dd>p { margin-bottom: 0.5rem; } .doc-contents dl+dl { margin-top: -0.5rem; } python-legacy-0.2.3/src/mkdocstrings_handlers/python/templates/mkdocs/yield.html000066400000000000000000000003041424444364000302520ustar00rootroot00000000000000{{ log.debug() }}
Yields:
{{ (("`" + yield.annotation + "` – " if yield.annotation else "") + yield.description)|convert_markdown(heading_level, html_id) }}
python-legacy-0.2.3/src/mkdocstrings_handlers/python/templates/readthedocs/000077500000000000000000000000001424444364000272665ustar00rootroot00000000000000python-legacy-0.2.3/src/mkdocstrings_handlers/python/templates/readthedocs/exceptions.html000066400000000000000000000010411424444364000323310ustar00rootroot00000000000000{{ log.debug() }}
Exceptions:
    {% for exception in exceptions %}
  • {{ ("`" + exception.annotation + "` – " + exception.description)|convert_markdown(heading_level, html_id) }}
  • {% endfor %}
python-legacy-0.2.3/src/mkdocstrings_handlers/python/templates/readthedocs/keyword_args.html000066400000000000000000000011311424444364000326500ustar00rootroot00000000000000{{ log.debug() }}
Keyword arguments:
    {% for kwarg in kwargs %}
  • {{ ("**" + kwarg.name + "**" + (" (`" + kwarg.annotation + "`)" if kwarg.annotation else "") + " – " + kwarg.description)|convert_markdown(heading_level, html_id) }}
  • {% endfor %}
python-legacy-0.2.3/src/mkdocstrings_handlers/python/templates/readthedocs/parameters.html000066400000000000000000000011521424444364000323160ustar00rootroot00000000000000{{ log.debug() }}
Parameters:
    {% for parameter in parameters %}
  • {{ ("**" + parameter.name + "**" + (" (`" + parameter.annotation + "`)" if parameter.annotation else "") + " – " + parameter.description)|convert_markdown(heading_level, html_id) }}
  • {% endfor %}
python-legacy-0.2.3/src/mkdocstrings_handlers/python/templates/readthedocs/return.html000066400000000000000000000007561424444364000315030ustar00rootroot00000000000000{{ log.debug() }}
Returns:
  • {{ ((("`" + return.annotation + "` – ") if return.annotation else "") + return.description)|convert_markdown(heading_level, html_id) }}
python-legacy-0.2.3/src/mkdocstrings_handlers/python/templates/readthedocs/style.css000066400000000000000000000011301424444364000311330ustar00rootroot00000000000000/* Avoid breaking parameters name, etc. in table cells. */ .doc-contents td code { word-break: normal !important; } /* For pieces of Markdown rendered in table cells. */ .doc-contents td p { margin-top: 0 !important; margin-bottom: 0 !important; } /* Avoid breaking code headings. */ .doc-heading code { white-space: normal; } /* Improve rendering of parameters, returns and exceptions. */ .doc-contents .field-name { min-width: 100px; } .doc-contents .field-name, .field-body { border: none !important; padding: 0 !important; } .doc-contents .field-list { margin: 0 !important; } python-legacy-0.2.3/src/mkdocstrings_handlers/python/templates/readthedocs/yield.html000066400000000000000000000007521424444364000312660ustar00rootroot00000000000000{{ log.debug() }}
Yields:
  • {{ ((("`" + yield.annotation + "` – ") if yield.annotation else "") + yield.description)|convert_markdown(heading_level, html_id) }}
python-legacy-0.2.3/tests/000077500000000000000000000000001424444364000154465ustar00rootroot00000000000000python-legacy-0.2.3/tests/__init__.py000066400000000000000000000002451424444364000175600ustar00rootroot00000000000000"""Tests suite for `mkdocstrings`.""" from pathlib import Path TESTS_DIR = Path(__file__).parent TMP_DIR = TESTS_DIR / "tmp" FIXTURES_DIR = TESTS_DIR / "fixtures" python-legacy-0.2.3/tests/conftest.py000066400000000000000000000045371424444364000176560ustar00rootroot00000000000000"""Configuration for the pytest test suite.""" from collections import ChainMap import pytest from markdown.core import Markdown from mkdocs import config try: from mkdocs.config.defaults import get_schema except ImportError: def get_schema(): # noqa: WPS440 """Fallback for old versions of MkDocs.""" # noqa: DAR201 return config.DEFAULT_SCHEMA @pytest.fixture(name="mkdocs_conf") def fixture_mkdocs_conf(request, tmp_path): """Yield a MkDocs configuration object. Parameters: request: Pytest request fixture. tmp_path: Pytest temporary path fixture. Yields: MkDocs configuration object. """ conf = config.Config(schema=get_schema()) while hasattr(request, "_parent_request") and hasattr(request._parent_request, "_parent_request"): # noqa: WPS437 request = request._parent_request # noqa: WPS437 conf_dict = { "site_name": "foo", "site_url": "https://example.org/", "site_dir": str(tmp_path), "plugins": [{"mkdocstrings": {"default_handler": "python"}}], **getattr(request, "param", {}), } # Re-create it manually as a workaround for https://github.com/mkdocs/mkdocs/issues/2289 mdx_configs = dict(ChainMap(*conf_dict.get("markdown_extensions", []))) conf.load_dict(conf_dict) assert conf.validate() == ([], []) conf["mdx_configs"] = mdx_configs conf["markdown_extensions"].insert(0, "toc") # Guaranteed to be added by MkDocs. conf = conf["plugins"]["mkdocstrings"].on_config(conf) conf = conf["plugins"]["autorefs"].on_config(conf) yield conf conf["plugins"]["mkdocstrings"].on_post_build(conf) @pytest.fixture(name="plugin") def fixture_plugin(mkdocs_conf): """Return a plugin instance. Parameters: mkdocs_conf: MkDocs configuration object (fixture). Returns: Configurated plugin instance. """ plugin = mkdocs_conf["plugins"]["mkdocstrings"] plugin.md = Markdown(extensions=mkdocs_conf["markdown_extensions"], extension_configs=mkdocs_conf["mdx_configs"]) return plugin @pytest.fixture(name="ext_markdown") def fixture_ext_markdown(plugin): """Return a Markdown instance with MkdocstringsExtension. Parameters: plugin: A configurated plugin instance. (fixture). Returns: The plugin Markdown instance. """ return plugin.md python-legacy-0.2.3/tests/test_collector.py000066400000000000000000000017521424444364000210520ustar00rootroot00000000000000# -*- coding: utf-8 -*- """Tests for the `collector` module.""" from unittest import mock import pytest from mkdocstrings.handlers.base import CollectionError from mkdocstrings_handlers.python import get_handler @pytest.mark.parametrize( ("retval", "exp_res"), [ ({"error": "error1", "traceback": "hello"}, "error1\nhello"), ({"error": "error1"}, "error1"), ({"error": "", "traceback": "hello"}, "\nhello"), ], ) def test_collect_result_error(retval, exp_res): """Test handling of errors when collecting an object. Args: retval: Return value to mock `json.loads` with. exp_res: Expected result. """ with mock.patch("mkdocstrings_handlers.python.handler.json.loads") as m_loads: with pytest.raises(CollectionError) as excinfo: # noqa: PT012 m_loads.return_value = retval handler = get_handler("material") assert handler.collect("", {}) assert str(excinfo.value) == exp_res python-legacy-0.2.3/tests/test_renderer.py000066400000000000000000000060161424444364000206700ustar00rootroot00000000000000"""Tests for the handlers.python module.""" from copy import deepcopy from mkdocstrings_handlers.python.rendering import ( # noqa: WPS450 rebuild_category_lists, sort_key_alphabetical, sort_key_source, sort_object, ) def test_members_order(): """Assert that members sorting functions work correctly.""" subcategories = {key: [] for key in ("attributes", "classes", "functions", "methods", "modules")} categories = {"children": {}, **subcategories} collected = { "name": "root", "children": { "b": {"name": "b", "source": {"line_start": 0}, **categories}, "a": {"name": "a", **categories}, "z": {"name": "z", "source": {"line_start": 100}, **categories}, "no_name": {"source": {"line_start": 10}, **categories}, "c": { "name": "c", "source": {"line_start": 30}, "children": { "z": {"name": "z", "source": {"line_start": 200}, **categories}, "a": {"name": "a", "source": {"line_start": 20}, **categories}, }, **subcategories, }, }, "attributes": ["b", "c", "no_name", "z", "a"], "classes": [], "functions": [], "methods": [], "modules": [], } rebuild_category_lists(collected) alphebetical = deepcopy(collected) sort_object(alphebetical, sort_key_alphabetical) rebuilt_categories = {"children": [], **subcategories} assert ( alphebetical["children"] == alphebetical["attributes"] == [ {"name": "a", **rebuilt_categories}, {"name": "b", "source": {"line_start": 0}, **rebuilt_categories}, { "name": "c", "source": {"line_start": 30}, "children": [ {"name": "a", "source": {"line_start": 20}, **rebuilt_categories}, {"name": "z", "source": {"line_start": 200}, **rebuilt_categories}, ], **subcategories, }, {"name": "z", "source": {"line_start": 100}, **rebuilt_categories}, {"source": {"line_start": 10}, **rebuilt_categories}, ] ) source = deepcopy(collected) sort_object(source, sort_key_source) assert ( source["children"] == source["attributes"] == [ {"name": "a", **rebuilt_categories}, {"name": "b", "source": {"line_start": 0}, **rebuilt_categories}, {"source": {"line_start": 10}, **rebuilt_categories}, { "name": "c", "source": {"line_start": 30}, "children": [ {"name": "a", "source": {"line_start": 20}, **rebuilt_categories}, {"name": "z", "source": {"line_start": 200}, **rebuilt_categories}, ], **subcategories, }, {"name": "z", "source": {"line_start": 100}, **rebuilt_categories}, ] ) python-legacy-0.2.3/tests/test_themes.py000066400000000000000000000022321424444364000203430ustar00rootroot00000000000000"""Tests for the different themes we claim to support.""" import sys import pytest @pytest.mark.parametrize( "plugin", [ {"theme": "mkdocs"}, {"theme": "readthedocs"}, {"theme": {"name": "material"}}, ], indirect=["plugin"], ) @pytest.mark.parametrize( "module", [ "mkdocstrings.extension", "mkdocstrings.inventory", "mkdocstrings.loggers", "mkdocstrings.plugin", "mkdocstrings.handlers.base", "mkdocstrings.handlers.rendering", "mkdocstrings_handlers.python.handler", "mkdocstrings_handlers.python.rendering", ], ) @pytest.mark.skipif(sys.version_info < (3, 7), reason="material is not installed on Python 3.6") def test_render_themes_templates(module, plugin): """Test rendering of a given theme's templates. Parameters: module: The module to load and render (parametrized). plugin: The plugin instance (parametrized fixture). """ handler = plugin.handlers.get_handler("python") handler._update_env(plugin.md, plugin.handlers._config) # noqa: WPS437 data = handler.collect(module, {}) handler.render(data, {})