pax_global_header00006660000000000000000000000064136540363710014522gustar00rootroot0000000000000052 comment=aff5f7f9ade410ac37077a384c66cbacf2a64b12 sphinxcontrib-trio-1.1.2/000077500000000000000000000000001365403637100153705ustar00rootroot00000000000000sphinxcontrib-trio-1.1.2/.coveragerc000066400000000000000000000001701365403637100175070ustar00rootroot00000000000000[run] branch=True omit= */setup.py */autodoc_examples.py [report] precision = 1 exclude_lines = pragma: no cover sphinxcontrib-trio-1.1.2/.gitignore000066400000000000000000000012411365403637100173560ustar00rootroot00000000000000# Project-specific generated files docs/build/ bench/results/ bench/env/ bench/trio/ # Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] *~ \#* .#* # C extensions *.so # Distribution / packaging .Python /build/ /develop-eggs/ /dist/ /eggs/ /lib/ /lib64/ /parts/ /sdist/ /var/ *.egg-info/ .installed.cfg *.egg # Installer logs pip-log.txt # Unit test / coverage reports htmlcov/ .tox/ .coverage .coverage.* .cache nosetests.xml coverage.xml # Translations *.mo # Mr Developer .mr.developer.cfg .project .pydevproject # Rope .ropeproject # Django stuff: *.log *.pot # VSCode stuff: .vscode # MyPy stuff: .mypy_cache # Sphinx documentation doc/_build/ sphinxcontrib-trio-1.1.2/.travis.yml000066400000000000000000000006651365403637100175100ustar00rootroot00000000000000language: python dist: xenial matrix: include: - python: 3.5 - python: 3.6 - python: 3.7 - python: 3.7 env: OLD_SPHINX=1.7 - python: 3.8 env: OLD_SPHINX=1.8 - python: 3.8 env: OLD_SPHINX=2.0 - python: 3.8 env: OLD_SPHINX=2.1 - python: 3.8 env: OLD_SPHINX=2.2 - python: 3.8 env: OLD_SPHINX=2.3 - python: 3.8 env: OLD_SPHINX=2.4 script: - ci/travis.sh sphinxcontrib-trio-1.1.2/CODE_OF_CONDUCT.md000066400000000000000000000001661365403637100201720ustar00rootroot00000000000000The Trio code of conduct applies to this project. See: https://trio.readthedocs.io/en/latest/code-of-conduct.html sphinxcontrib-trio-1.1.2/CONTRIBUTING.md000066400000000000000000000002041365403637100176150ustar00rootroot00000000000000This is an official Trio project. For the Trio contributing guide, see: https://trio.readthedocs.io/en/latest/contributing.html sphinxcontrib-trio-1.1.2/LICENSE000066400000000000000000000002761365403637100164020ustar00rootroot00000000000000This software is made available under the terms of *either* of the licenses found in LICENSE.APACHE2 or LICENSE.MIT. Contributions to trio are made under the terms of *both* these licenses. sphinxcontrib-trio-1.1.2/LICENSE.APACHE2000066400000000000000000000261361365403637100174070ustar00rootroot00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. sphinxcontrib-trio-1.1.2/LICENSE.MIT000066400000000000000000000020261365403637100170250ustar00rootroot00000000000000The MIT License (MIT) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. sphinxcontrib-trio-1.1.2/MANIFEST.in000066400000000000000000000003111365403637100171210ustar00rootroot00000000000000include LICENSE LICENSE.MIT LICENSE.APACHE2 include README.rst CODE_OF_CONDUCT.md include test-requirements.in test-requirements.txt recursive-include docs * recursive-include tests * prune docs/build sphinxcontrib-trio-1.1.2/README.rst000066400000000000000000000032551365403637100170640ustar00rootroot00000000000000.. note that this README gets 'include'ed into the main documentation sphinxcontrib-trio ================== This sphinx extension helps you document Python code that uses async/await, or abstract methods, or context managers, or generators, or ... you get the idea. It works by making sphinx's regular directives for documenting Python functions and methods smarter and more powerful. The name is because it was originally written for the `Trio `__ project, and I'm not very creative. But don't be put off – there's nothing Trio- or async-specific about this extension; any Python project can benefit. (Though projects using async/await probably benefit the most, since sphinx's built-in tools are especially inadequate in this case.) Vital statistics ---------------- **Requirements:** This extension currently assumes you're using Python 3.5+ to build your docs. This could be relaxed if anyone wants to send a patch. **Documentation:** https://sphinxcontrib-trio.readthedocs.io **Bug tracker and source code:** https://github.com/python-trio/sphinxcontrib-trio **License:** MIT or Apache 2, your choice. **Usage:** ``pip install -U sphinxcontrib-trio`` in the same environment where you installed sphinx, and then add ``"sphinxcontrib_trio"`` to the list of ``extensions`` in your project's ``conf.py``. (Notice that ``"sphinxcontrib_trio"`` has an underscore in it, NOT a dot. This is because I don't understand namespace packages, and I fear things that I don't understand.) **Code of conduct:** Contributors are requested to follow our `code of conduct `__ in all project spaces. sphinxcontrib-trio-1.1.2/ci/000077500000000000000000000000001365403637100157635ustar00rootroot00000000000000sphinxcontrib-trio-1.1.2/ci/rtd-requirements.in000066400000000000000000000000071365403637100216220ustar00rootroot00000000000000sphinx sphinxcontrib-trio-1.1.2/ci/rtd-requirements.txt000066400000000000000000000021251365403637100220360ustar00rootroot00000000000000# # This file is autogenerated by pip-compile # To update, run: # # pip-compile ci/rtd-requirements.in # alabaster==0.7.12 # via sphinx babel==2.8.0 # via sphinx certifi==2020.4.5.1 # via requests chardet==3.0.4 # via requests docutils==0.16 # via sphinx idna==2.9 # via requests imagesize==1.2.0 # via sphinx jinja2==2.11.2 # via sphinx markupsafe==1.1.1 # via jinja2 packaging==20.3 # via sphinx pygments==2.6.1 # via sphinx pyparsing==2.4.7 # via packaging pytz==2020.1 # via babel requests==2.23.0 # via sphinx six==1.14.0 # via packaging snowballstemmer==2.0.0 # via sphinx sphinx==3.0.3 # via -r ci/rtd-requirements.in sphinxcontrib-applehelp==1.0.2 # via sphinx sphinxcontrib-devhelp==1.0.2 # via sphinx sphinxcontrib-htmlhelp==1.0.3 # via sphinx sphinxcontrib-jsmath==1.0.1 # via sphinx sphinxcontrib-qthelp==1.0.3 # via sphinx sphinxcontrib-serializinghtml==1.1.4 # via sphinx urllib3==1.25.9 # via requests sphinxcontrib-trio-1.1.2/ci/travis.sh000077500000000000000000000020731365403637100176340ustar00rootroot00000000000000#!/bin/bash set -exu -o pipefail pip install -U pip setuptools wheel python setup.py sdist --formats=zip pip install dist/*.zip # Make sure that the docs build without warnings. And this also acts as a # basic smoke test on the code, since the docs use the code. pushd docs # -n (nit-picky): warn on missing references # -W: turn warnings into errors sphinx-build -nW -b html source build popd pip install -Ur test-requirements.txt # https://stackoverflow.com/questions/3601515/how-to-check-if-a-variable-is-set-in-bash if [ -n "${OLD_SPHINX+x}" ]; then pip install "sphinx == ${OLD_SPHINX}.*" fi mkdir empty pushd empty INSTALLDIR=$(python -c "import os, sphinxcontrib_trio; print(os.path.dirname(sphinxcontrib_trio.__file__))") pytest ../tests --cov="$INSTALLDIR" --cov=../tests --cov-config="../.coveragerc" mv .coverage firstrun # Run tests again with minimal dependencies installed pip uninstall -y async_generator contextlib2 pytest ../tests --cov="$INSTALLDIR" --cov=../tests --cov-config="../.coveragerc" coverage combine -a firstrun pip install codecov codecov sphinxcontrib-trio-1.1.2/docs/000077500000000000000000000000001365403637100163205ustar00rootroot00000000000000sphinxcontrib-trio-1.1.2/docs/Makefile000066400000000000000000000011531365403637100177600ustar00rootroot00000000000000# Minimal makefile for Sphinx documentation # # You can set these variables from the command line. SPHINXOPTS = SPHINXBUILD = sphinx-build SPHINXPROJ = sphinxcontrib-trio SOURCEDIR = source BUILDDIR = build # Put it first so that "make" without argument is like "make help". help: @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) .PHONY: help Makefile # Catch-all target: route all unknown targets to Sphinx using the new # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). %: Makefile @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)sphinxcontrib-trio-1.1.2/docs/make.bat000066400000000000000000000014721365403637100177310ustar00rootroot00000000000000@ECHO OFF pushd %~dp0 REM Command file for Sphinx documentation if "%SPHINXBUILD%" == "" ( set SPHINXBUILD=sphinx-build ) set SOURCEDIR=source set BUILDDIR=build set SPHINXPROJ=sphinxcontrib-trio if "%1" == "" goto help %SPHINXBUILD% >NUL 2>NUL if errorlevel 9009 ( echo. echo.The 'sphinx-build' command was not found. Make sure you have Sphinx echo.installed, then set the SPHINXBUILD environment variable to point echo.to the full path of the 'sphinx-build' executable. Alternatively you echo.may add the Sphinx directory to PATH. echo. echo.If you don't have Sphinx installed, grab it from echo.http://sphinx-doc.org/ exit /b 1 ) %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% goto end :help %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% :end popd sphinxcontrib-trio-1.1.2/docs/source/000077500000000000000000000000001365403637100176205ustar00rootroot00000000000000sphinxcontrib-trio-1.1.2/docs/source/_static/000077500000000000000000000000001365403637100212465ustar00rootroot00000000000000sphinxcontrib-trio-1.1.2/docs/source/_static/hack.css000066400000000000000000000034721365403637100226740ustar00rootroot00000000000000/* docutils has a very stupid heuristic where it forces browsers to render the columns in HTML tables with the same relative widths as the monospaced ReST source text for those columns. Our tables have lots of markup in them that take up source text but don't even appear in the HTML (and never mind that the whole thing makes no sense because browsers know the *actual* width of the text), which causes them to be ugly and have unnecessary linebreaks in some columns and random whitespace in others. According to the docutils documentation, this can be overridden by using a table:: directive with :widths: auto, or setting the docutils configuration table_style to "colwidths-auto". However, after much pain and hassle, I've convinced myself that this doesn't actually work -- the code in _html_base.py in docutils that tries to decide whether to emit the tag based on these settings isn't even called, and the code in html4css1/__init__.py that actually emits the tags doesn't check the configuration. (Also, sphinx makes it absurdly difficult to modify the docutils settings -- I ended up monkeypatching sphinx.environment.default_settings. But it doesn't matter because the settings don't work anyway.) This attempts to tell the browser to ignore docutils's helpful table width settings. I'm not sure it works on all browsers, because docutils actually generates HTML like: but in HTML5 the HTML width= attribute on tags is deprecated in favor CSS width: attribute, so hopefully most browsers map them to the same internal setting. It works on Firefox 52, anyway. Idea from: http://stackoverflow.com/a/25553413 */ table.docutils col { width: auto !important; } sphinxcontrib-trio-1.1.2/docs/source/_templates/000077500000000000000000000000001365403637100217555ustar00rootroot00000000000000sphinxcontrib-trio-1.1.2/docs/source/_templates/.gitkeep000066400000000000000000000000001365403637100233740ustar00rootroot00000000000000sphinxcontrib-trio-1.1.2/docs/source/_templates/need-help.html000066400000000000000000000003241365403637100245030ustar00rootroot00000000000000

Need help?

Try chat or StackOverflow.
sphinxcontrib-trio-1.1.2/docs/source/conf.py000066400000000000000000000123101365403637100211140ustar00rootroot00000000000000#!/usr/bin/env python3 # -*- coding: utf-8 -*- # # sphinxcontrib-trio documentation build configuration file, created by # sphinx-quickstart on Wed May 10 23:26:44 2017. # # This file is execfile()d with the current directory set to its # containing dir. # # Note that not all possible configuration values are present in this # autogenerated file. # # All configuration values have a default; values that are commented out # serve to show the default. # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. # import os import sys sys.path.insert(0, os.path.abspath('../..')) # -- General configuration ------------------------------------------------ # If your documentation needs a minimal Sphinx version, state it here. # # needs_sphinx = '1.0' # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ 'sphinx.ext.autodoc', 'sphinx.ext.intersphinx', 'sphinxcontrib_trio', ] def setup(app): app.add_stylesheet("hack.css") intersphinx_mapping = { "sphinx": ("http://www.sphinx-doc.org/en/stable/", None), "python": ('https://docs.python.org/3', None), } html_sidebars = { "**": [ "localtoc.html", "relations.html", "searchbox.html", "need-help.html", ], } autodoc_member_order = "bysource" # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] # The suffix(es) of source filenames. # You can specify multiple suffix as a list of string: # # source_suffix = ['.rst', '.md'] source_suffix = '.rst' # The master toctree document. master_doc = 'index' # General information about the project. project = 'sphinxcontrib-trio' copyright = '2017, Nathaniel J. Smith' author = 'Nathaniel J. Smith' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # import sphinxcontrib_trio # The short X.Y version. version = sphinxcontrib_trio.__version__ # The full version, including alpha/beta/rc tags. release = version # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. # # This is also used if you do content translation via gettext catalogs. # Usually you set "language" from the command line for these cases. language = None # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. # This patterns also effect to html_static_path and html_extra_path exclude_patterns = [] # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' highlight_language = 'python3' # If true, `todo` and `todoList` produce output, else they produce nothing. todo_include_todos = False # -- Options for HTML output ---------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # html_theme = 'alabaster' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. # # html_theme_options = {} # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] # -- Options for HTMLHelp output ------------------------------------------ # Output file base name for HTML help builder. htmlhelp_basename = 'sphinxcontrib-triodoc' # -- Options for LaTeX output --------------------------------------------- latex_elements = { # The paper size ('letterpaper' or 'a4paper'). # # 'papersize': 'letterpaper', # The font size ('10pt', '11pt' or '12pt'). # # 'pointsize': '10pt', # Additional stuff for the LaTeX preamble. # # 'preamble': '', # Latex figure (float) alignment # # 'figure_align': 'htbp', } # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ (master_doc, 'sphinxcontrib-trio.tex', 'sphinxcontrib-trio Documentation', 'Nathaniel J. Smith', 'manual'), ] # -- Options for manual page output --------------------------------------- # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ (master_doc, 'sphinxcontrib-trio', 'sphinxcontrib-trio Documentation', [author], 1) ] # -- Options for Texinfo output ------------------------------------------- # Grouping the document tree into Texinfo files. List of tuples # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ (master_doc, 'sphinxcontrib-trio', 'sphinxcontrib-trio Documentation', author, 'sphinxcontrib-trio', 'One line description of project.', 'Miscellaneous'), ] sphinxcontrib-trio-1.1.2/docs/source/index.rst000066400000000000000000000312571365403637100214710ustar00rootroot00000000000000.. include:: ../../README.rst The big idea ------------ Sphinx provides some convenient directives for `documenting Python code `__: you can use the ``method::`` directive to document an ordinary method, the ``classmethod::`` directive to document a classmethod, the ``decoratormethod::`` directive to document a decorator method, and so on. But what if you have a classmethod that's also a decorator? And what if you want to document a project that uses some of Python's many interesting function types that Sphinx *doesn't* support, like async functions, abstract methods, generators, ...? It would be possible to keep adding directive after directive for every possible type: ``asyncmethod::``, ``abstractmethod::``, ``classmethoddecorator::``, ``abstractasyncstaticmethod::`` – you get the idea. But this quickly becomes silly. sphinxcontrib-trio takes a different approach: it enhances the basic ``function::`` and ``method::`` directives to accept options describing the attributes of each function/method, so you can write ReST code like: .. code-block:: rst .. method:: overachiever(arg1, ...) :abstractmethod: :async: :classmethod: This method is perhaps more complicated than it needs to be. and you'll get rendered output like: .. method:: overachiever(arg1, ...) :abstractmethod: :async: :classmethod: This method is perhaps more complicated than it needs to be. While I was at it, I also enhanced the ``sphinx.ext.autodoc`` directives ``autofunction::`` and ``automethod::`` with new versions that know how to automatically detect many of these attributes, so you could just as easily have written the above as: .. code-block:: rst .. automethod:: overachiever and it would automatically figure out that this was an abstract async classmethod by looking at your code. And finally, I made the legacy ``classmethod::`` directive into an alias for: .. code-block:: rst .. method:: :classmethod: and similarly ``staticmethod``, ``decorator``, and ``decoratormethod``, so dropping this extension into an existing sphinx project should be 100% backwards-compatible while giving sphinx new superpowers. Basically, this is how sphinx ought to work in the first place. `Perhaps in the future it will. `__ But until then, this extension is pretty handy. The details ----------- The following options are supported by the enhanced ``function::`` and ``method::`` directives, and some of them can be automatically detected if you use ``autofunction::`` / ``automethod::``. ==================== =============================== ========================== Option Renders like Autodetectable? ==================== =============================== ========================== ``:async:`` *await* **fn**\() yes! ``:decorator:`` @\ **fn** no ``:with:`` *with* **fn**\() yes! (see below) ``:with: foo`` *with* **fn**\() *as foo* no ``:async-with:`` *async with* **fn**\() yes! (see below) ``:async-with: foo`` *async with* **fn**\() *as foo* no ``:for:`` *for ... in* **fn**\() yes! (see below) ``:for: foo`` *for foo in* **fn**\() no ``:async-for:`` *async for ... in* **fn**\() yes! (see below) ``:async-for: foo`` *async for foo in* **fn**\() no ==================== =============================== ========================== There are also a few options that are specific to ``method::``. They are: ==================== ========================== ===================== Option Renders like Autodetectable? ==================== ========================== ===================== ``:abstractmethod:`` *abstractmethod* **fn**\() yes! ``:staticmethod:`` *staticmethod* **fn**\() yes! ``:classmethod:`` *classmethod* **fn**\() yes! ==================== ========================== ===================== Autodetection heuristics ++++++++++++++++++++++++ * ``:with:`` is autodetected for: * functions decorated with `contextlib.contextmanager `__ or `contextlib2.contextmanager `__, * functions that have an attribute ``__returns_contextmanager__`` with a truthy value. * ``:async-with:`` is autodetected for: * functions decorated with `contextlib.asynccontextmanager `__, * functions that have an attribute ``__returns_acontextmanager__`` (note the ``a``) with a truthy value. * ``:for:`` is autodetected for generators. * ``:async-for:`` is autodetected for async generators. The code supports both `native async generators `__ (in Python 3.6+) and those created by the `async_generator `__ library (in Python 3.5+). As you can see, autodetection is necessarily a somewhat heuristic process. To reduce the rate of false positives, the autodetection code assumes that any given function will have at most one out of the following options: ``:async:``, ``:with:``, ``:async-with:``, ``:for:``, ``:async-for:``. For example, this avoids the situation where a generator is decorated with ``contextlib.contextmanager``, and sphinxcontrib-trio ends up applying both ``:for:`` and ``:with:``. But, despite our best attempts, it's possible that the heuristics will go wrong. Please do `report any cases where this happens `__, but in the mean time you can work around the issue by using the ``:no-auto-options:`` option to disable option sniffing, and then add the correct options manually. For example, this code will pull out ``some_function``\'s signature and docstring from the source code, and then treat it as returning an async generator, regardless of its actual attributes. .. code-block:: rst .. autofunction:: some_function :no-auto-options: :async-for: Another situation where this might be useful is if you have a function with `a complicated calling convention that can't be summarized in one line `__. I can't really recommend writing such APIs, but if you need to document one, then ``:no-auto-options:`` can be used to tell sphinxcontrib-trio to stop being helpful, and then you can describe the full calling convention in the text. Examples -------- A regular async function: .. code-block:: rst .. function:: example_async_fn(...) :async: This is an example. Renders as: .. function:: example_async_fn(...) :async: This is an example. A context manager with a hint as to what's returned: .. code-block:: rst .. function:: open(file_name) :with: file_handle It's good practice to use :func:`open` as a context manager. Renders as: .. function:: open(file_name) :with: file_handle It's good practice to use :func:`open` as a context manager. The auto versions of the directives also accept explicit options, which are appended to the automatically detected options. So if ``some_method`` is defined as a ``abstractmethod`` in the source, and you want to document that it should be used as a decorator, you can write: .. code-block:: rst .. automethod:: some_method :decorator: and it will render like: .. method:: some_method :abstractmethod: :decorator: Here's some text automatically extracted from the method's docstring. Bugs and limitations -------------------- * Python supports defining abstract properties like:: @abstractmethod @property def some_property(...): ... But currently this extension doesn't help you document them. The difficulty is that for Sphinx, properties are "attributes", not "methods", and we don't currently hook the code for handling ``attribute::`` and ``autoattribute::``. Maybe we should? * When multiple options are combined, then we try to render them in a sensible way, but this does assume that you're giving us a sensible combination to start with. If you give sphinxcontrib-trio nonsense, then it will happily render nonsense. For example, this ReST: .. code-block:: rst .. function:: all_things_to_all_people(a, b) :with: x :async-with: y :for: z :decorator: Something has gone terribly wrong. renders as: .. function:: all_things_to_all_people(a, b) :with: x :async-with: y :for: z :decorator: Something has gone terribly wrong. * There's currently no particular support for asyncio's old-style "generator-based coroutines", though they might work if you remember to use `asyncio.coroutine `__. Acknowledgements ---------------- Inspiration and hints on sphinx hackery were drawn from: * `sphinxcontrib-asyncio `__ * `Curio's local customization `__ * `CPython's local customization `__ sphinxcontrib-asyncio was especially helpful. Compared to sphinxcontrib-asyncio, this package takes the idea of directive options to its logical conclusion, steals Dave Beazley's idea of documenting special methods like coroutines by showing how they're used ("await f()" instead of "coroutine f()"), and avoids the `forbidden word `__ `coroutine `__. Revision history ---------------- .. towncrier release notes start Sphinxcontrib_Trio 1.1.2 (2020-05-04) +++++++++++++++++++++++++++++++++++++ Bugfixes ~~~~~~~~ - Recent version of Sphinx deprecated its ``PyClassmember`` class. We've adjusted sphinxcontrib-trio's internals to stop using it and silence the warning. (`#154 `__) Sphinxcontrib_Trio 1.1.1 (2020-03-26) +++++++++++++++++++++++++++++++++++++ Bugfixes ~~~~~~~~ - When using autodoc to document a class that has inherited members, we now correctly auto-detect the async-ness and other properties of those inherited methods. (`#19 `__) - Recent versions of Sphinx deprecated its ``PyModulelevel`` class. We've adjusted sphinxcontrib-trio's internals to stop using it. (`#138 `__) Sphinxcontrib_Trio 1.1.0 (2019-06-03) +++++++++++++++++++++++++++++++++++++ Features ~~~~~~~~ - Added support for Sphinx 2.1. (`#23 `__) Deprecations and Removals ~~~~~~~~~~~~~~~~~~~~~~~~~ - Drop support for Sphinx 1.6 and earlier. (`#87 `__) Sphinxcontrib_Trio 1.0.2 (2019-01-27) +++++++++++++++++++++++++++++++++++++ Bugfixes ~~~~~~~~ - Previously, on Sphinx 1.7, ``autodoc_member_order="bysource"`` didn't work correctly for async methods. Now, it does. (`#13 `__) Deprecations and Removals ~~~~~~~~~~~~~~~~~~~~~~~~~ - Remove support for sphinx<1.6. (`#14 `__) sphinxcontrib-trio 1.0.1 (2018-02-06) +++++++++++++++++++++++++++++++++++++ Bugfixes ~~~~~~~~ - Fix an obscure incompatibility with the :mod:`sphinx.ext.autosummary` module's ``autosummary_generate = True`` setting. (`#8 `__) - Previously, sphinxcontrib-trio had to be listed after sphinx.ext.autodoc in your extensions configuration, or else sphinx would error out. Now sphinxcontrib-trio automatically loads sphinx.ext.autodoc as needed. (`#9 `__) sphinxcontrib-trio v1.0.0 (2017-05-12) ++++++++++++++++++++++++++++++++++++++ Added autodetection heuristics for context managers. Added rule to prevent functions using ``@contextlib.contextmanager`` or similar from being detected as generators (see `bpo-30359 `__). Added ``:no-sniff-options:`` option for when the heuristics go wrong anyway. Added a test suite, and fixed many bugs... but I repeat myself. sphinxcontrib-trio v0.9.0 (2017-05-11) ++++++++++++++++++++++++++++++++++++++ Initial release. sphinxcontrib-trio-1.1.2/newsfragments/000077500000000000000000000000001365403637100202535ustar00rootroot00000000000000sphinxcontrib-trio-1.1.2/newsfragments/README.rst000066400000000000000000000020511365403637100217400ustar00rootroot00000000000000This directory collects "newsfragments": short files that each contain a snippet of ReST-formatted text that will be added to the next release notes. This should be a description of aspects of the change (if any) that are relevant to users. (This contrasts with your commit message and PR description, which are a description of the change as relevant to people working on the code itself.) Each file should be named like ``..rst``, where ```` is an issue numbers, and ```` is one of: * ``feature`` * ``bugfix`` * ``doc`` * ``removal`` * ``misc`` So for example: ``123.feature.rst``, ``456.bugfix.rst`` If your PR fixes an issue, use that number here. If there is no issue, then after you submit the PR and get the PR number you can add a newsfragment using that instead. Note that the ``towncrier`` tool will automatically reflow your text, so don't try to do any fancy formatting. You can install ``towncrier`` and then run ``towncrier --draft`` if you want to get a preview of how your change will look in the final release notes. sphinxcontrib-trio-1.1.2/pyproject.toml000066400000000000000000000007641365403637100203130ustar00rootroot00000000000000[tool.towncrier] # Usage: # - PRs should drop a file like "issuenumber.feature" in newsfragments # (or "bugfix", "doc", "removal", "misc"; misc gets no text, we can # customize this) # - At release time after bumping version number, run: towncrier # (or towncrier --draft) package = "sphinxcontrib_trio" filename = "docs/source/index.rst" directory = "newsfragments" underlines = ["+", "~", "^"] issue_format = "`#{issue} `__" sphinxcontrib-trio-1.1.2/setup.py000066400000000000000000000025101365403637100171000ustar00rootroot00000000000000from pathlib import Path from setuptools import setup, find_packages # defines __version__ exec(open("sphinxcontrib_trio/_version.py").read()) setup( name="sphinxcontrib-trio", version=__version__, description= "Make Sphinx better at documenting Python functions and methods", # Just in case the cwd is not the root of the source tree, or python is # not set to use utf-8 by default: long_description=Path(__file__).with_name("README.rst").read_text('utf-8'), author="Nathaniel J. Smith", author_email="njs@pobox.com", license="MIT -or- Apache License 2.0", packages=find_packages(), url="https://github.com/python-trio/sphinxcontrib-trio", install_requires=["sphinx >= 1.7"], classifiers=[ 'Development Status :: 5 - Production/Stable', "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "License :: OSI Approved :: Apache Software License", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Framework :: Sphinx :: Extension", "Framework :: Trio", "Framework :: AsyncIO", "Framework :: Twisted", "Topic :: Documentation :: Sphinx", "Topic :: Software Development :: Documentation", ]) sphinxcontrib-trio-1.1.2/sphinxcontrib_trio/000077500000000000000000000000001365403637100213175ustar00rootroot00000000000000sphinxcontrib-trio-1.1.2/sphinxcontrib_trio/__init__.py000066400000000000000000000360341365403637100234360ustar00rootroot00000000000000"""A sphinx extension to help documenting Python code that uses async/await (or context managers, or abstract methods, or generators, or ...). This extension takes a somewhat non-traditional approach, though, based on the observation that function properties like "classmethod", "async", "abstractmethod" can be mixed and matched, so the the classic sphinx approach of defining different directives for all of these quickly becomes cumbersome. Instead, we override the ordinary function & method directives to add options corresponding to these different properties, and override the autofunction and automethod directives to sniff for these properties. Examples: A function that returns a context manager: .. function:: foo(x, y) :with: bar renders in the docs like: with foo(x, y) as bar The 'bar' part is optional. Use :async-with: for an async context manager. These are also accepted on method, autofunction, and automethod. An abstract async classmethod: .. method:: foo :abstractmethod: :classmethod: :async: renders like: abstractmethod classmethod await foo() Or since all of these attributes are introspectable, we can get the same result with: .. automethod:: foo An abstract static decorator: .. method:: foo :abstractmethod: :staticmethod: :decorator: The :decorator: attribute isn't introspectable, but the others are, so this also works: .. automethod:: foo :decorator: and renders like abstractmethod staticmethod @foo """ from ._version import __version__ from docutils.parsers.rst import directives from sphinx import addnodes try: from sphinx.domains.python import PyFunction except ImportError: from sphinx.domains.python import PyModulelevel as PyFunction from sphinx.domains.python import PyObject try: from sphinx.domains.python import PyMethod, PyClassMethod, PyStaticMethod except ImportError: from sphinx.domains.python import PyClassmember as PyMethod from sphinx.domains.python import PyClassmember as PyClassMethod from sphinx.domains.python import PyClassmember as PyStaticMethod from sphinx.ext.autodoc import ( FunctionDocumenter, MethodDocumenter, ClassLevelDocumenter, Options, ModuleLevelDocumenter ) import inspect try: from async_generator import isasyncgenfunction except ImportError: try: from inspect import isasyncgenfunction except ImportError: # This python install has no way to make async generators def isasyncgenfunction(fn): return False CM_CODES = set() ACM_CODES = set() from contextlib import contextmanager CM_CODES.add(contextmanager(None).__code__) # type: ignore try: from contextlib2 import contextmanager as contextmanager2 except ImportError: pass else: CM_CODES.add(contextmanager2(None).__code__) # type: ignore try: from contextlib import asynccontextmanager except ImportError: pass else: ACM_CODES.add(asynccontextmanager(None).__code__) # type: ignore extended_function_option_spec = { "async": directives.flag, "decorator": directives.flag, "with": directives.unchanged, "async-with": directives.unchanged, "for": directives.unchanged, "async-for": directives.unchanged, } extended_method_option_spec = { **extended_function_option_spec, "abstractmethod": directives.flag, "staticmethod": directives.flag, "classmethod": directives.flag, "property": directives.flag, } autodoc_option_spec = { "no-auto-options": directives.flag, } ################################################################ # Extending the basic function and method directives ################################################################ class ExtendedCallableMixin(PyObject): # inherit PyObject to satisfy MyPy def needs_arglist(self): if "property" in self.options: return False if ("decorator" in self.options or self.objtype in ["decorator", "decoratormethod"]): return False return True # This does *not* override the superclass get_signature_prefix(), because # that gets called by the superclass handle_signature(), which then # may-or-may-not insert it into the signode (depending on whether or not # it returns an empty string). We want to insert the decorator @ after the # prefix but before the regular name. If we let the superclass # handle_signature() insert the prefix or maybe not, then we can't tell # where the @ goes. def _get_signature_prefix(self): ret = "" if "abstractmethod" in self.options: ret += "abstractmethod " # objtype checks are for backwards compatibility, to support # # .. staticmethod:: # # in addition to # # .. method:: # :staticmethod: # # it would be nice if there were a central place we could normalize # the directive name into the options dict instead of having to check # both here at time-of-use, but I don't understand sphinx well enough # to do that. # # Note that this is the code that determines the ordering of the # different prefixes. if "staticmethod" in self.options or self.objtype == "staticmethod": ret += "staticmethod " if "classmethod" in self.options or self.objtype == "classmethod": ret += "classmethod " # if "property" in self.options: # ret += "property " if "with" in self.options: ret += "with " if "async-with" in self.options: ret += "async with " for for_type, render in [("for", "for"), ("async-for", "async for")]: if for_type in self.options: name = self.options.get(for_type, "") if not name.strip(): name = "..." ret += "{} {} in ".format(render, name) if "async" in self.options: ret += "await " return ret # But we do want to override the superclass get_signature_prefix to stop # it from trying to do its own handling of staticmethod and classmethod # directives (the legacy ones) def get_signature_prefix(self, sig): return "" def handle_signature(self, sig, signode): ret = super().handle_signature(sig, signode) # Add the "@" prefix if ("decorator" in self.options or self.objtype in ["decorator", "decoratormethod"]): signode.insert(0, addnodes.desc_addname("@", "@")) # Now that the "@" has been taken care of, we can add in the regular # prefix. prefix = self._get_signature_prefix() if prefix: signode.insert(0, addnodes.desc_annotation(prefix, prefix)) # And here's the suffix: for optname in ["with", "async-with"]: if self.options.get(optname, "").strip(): # for some reason a regular space here gets stripped, so we # use U+00A0 NO-BREAK SPACE s = "\u00A0as {}".format(self.options[optname]) signode += addnodes.desc_annotation(s, s) return ret class ExtendedPyFunction(ExtendedCallableMixin, PyFunction): option_spec = { **PyFunction.option_spec, **extended_function_option_spec, } class ExtendedPyMethod(ExtendedCallableMixin, PyMethod): option_spec = { **PyMethod.option_spec, **extended_method_option_spec, } class ExtendedPyClassMethod(ExtendedCallableMixin, PyClassMethod): option_spec = { **PyClassMethod.option_spec, **extended_method_option_spec, } class ExtendedPyStaticMethod(ExtendedCallableMixin, PyStaticMethod): option_spec = { **PyStaticMethod.option_spec, **extended_method_option_spec, } ################################################################ # Autodoc ################################################################ # Our sniffer never reports more than one item from this set. In principle # it's possible for something to be, say, an async function that returns # a context manager ("with await foo(): ..."), but it's extremely unusual, and # OTOH it's very easy for these to get confused when walking the __wrapped__ # chain (e.g. because async_generator converts an async into an async-for, and # maybe that then gets converted into an async-with by an async version of # contextlib.contextmanager). So once we see one of these, we stop looking for # the others. EXCLUSIVE_OPTIONS = {"async", "for", "async-for", "with", "async-with"} def sniff_options(obj): options = set() # We walk the __wrapped__ chain to collect properties. while True: if getattr(obj, "__isabstractmethod__", False): options.add("abstractmethod") if isinstance(obj, classmethod): options.add("classmethod") if isinstance(obj, staticmethod): options.add("staticmethod") # if isinstance(obj, property): # options.add("property") # Only check for these if we haven't seen any of them yet: if not (options & EXCLUSIVE_OPTIONS): if inspect.iscoroutinefunction(obj): options.add("async") # in some versions of Python, isgeneratorfunction returns true for # coroutines, so we use elif elif inspect.isgeneratorfunction(obj): options.add("for") if isasyncgenfunction(obj): options.add("async-for") # Some heuristics to detect when something is a context manager if getattr(obj, "__code__", None) in CM_CODES: options.add("with") if getattr(obj, "__returns_contextmanager__", False): options.add("with") if getattr(obj, "__code__", None) in ACM_CODES: options.add("async-with") if getattr(obj, "__returns_acontextmanager__", False): options.add("async-with") if hasattr(obj, "__wrapped__"): obj = obj.__wrapped__ elif hasattr(obj, "__func__"): # for staticmethod & classmethod obj = obj.__func__ else: break return options def update_with_sniffed_options(obj, option_dict): if "no-auto-options" in option_dict: return sniffed = sniff_options(obj) for attr in sniffed: # Suppose someone has a generator, and they document it as: # # .. autofunction:: my_generator # :for: loop_var # # We don't want to blow away the existing attr["for"] = "loop_var" # with our autodetected attr["for"] = None. So we use setdefault. option_dict.setdefault(attr, None) def passthrough_option_lines(self, option_spec): sourcename = self.get_sourcename() for option in option_spec: if option in self.options: if self.options.get(option) is not None: line = " :{}: {}".format(option, self.options[option]) else: line = " :{}:".format(option) self.add_line(line, sourcename) class ExtendedFunctionDocumenter(FunctionDocumenter): priority = FunctionDocumenter.priority + 1 # You can explicitly set the options in case autodetection fails option_spec = { **FunctionDocumenter.option_spec, **extended_function_option_spec, **autodoc_option_spec, } def add_directive_header(self, sig): # We can't call super() here, because we want to *skip* executing # FunctionDocumenter.add_directive_header, because starting in Sphinx # 2.1 it does its own sniffing, which is worse than ours and will # break ours. So we jump straight to the superclass. ModuleLevelDocumenter.add_directive_header(self, sig) passthrough_option_lines(self, extended_function_option_spec) def import_object(self): ret = super().import_object() # autodoc likes to re-use dicts here for some reason (!?!) self.options = Options(self.options) update_with_sniffed_options(self.object, self.options) return ret class ExtendedMethodDocumenter(MethodDocumenter): priority = MethodDocumenter.priority + 1 # You can explicitly set the options in case autodetection fails option_spec = { **MethodDocumenter.option_spec, **extended_method_option_spec, **autodoc_option_spec, } def add_directive_header(self, sig): # We can't call super() here, because we want to *skip* executing # FunctionDocumenter.add_directive_header, because starting in Sphinx # 2.1 it does its own sniffing, which is worse than ours and will # break ours. So we jump straight to the superclass. ClassLevelDocumenter.add_directive_header(self, sig) passthrough_option_lines(self, extended_method_option_spec) def import_object(self): # MethodDocumenter overrides import_object to do some sniffing in # addition to just importing. But we do our own sniffing and just want # the import, so we un-override it. ret = ClassLevelDocumenter.import_object(self) # Use 'inspect.getattr_static' to properly detect class or static methods. # This also resolves the MRO entries for subclasses. obj = inspect.getattr_static(self.parent, self.object_name) # autodoc likes to re-use dicts here for some reason (!?!) self.options = Options(self.options) update_with_sniffed_options(obj, self.options) # Replicate the special ordering hacks in # MethodDocumenter.import_object if "classmethod" in self.options or "staticmethod" in self.options: self.member_order -= 1 return ret ################################################################ # Register everything ################################################################ def setup(app): app.add_directive_to_domain('py', 'function', ExtendedPyFunction) app.add_directive_to_domain('py', 'method', ExtendedPyMethod) app.add_directive_to_domain('py', 'classmethod', ExtendedPyClassMethod) app.add_directive_to_domain('py', 'staticmethod', ExtendedPyStaticMethod) app.add_directive_to_domain('py', 'decorator', ExtendedPyFunction) app.add_directive_to_domain('py', 'decoratormethod', ExtendedPyMethod) # Make sure sphinx.ext.autodoc is loaded before we try to mess with it. app.setup_extension("sphinx.ext.autodoc") # We're overriding these on purpose, so disable the warning about it del directives._directives["autofunction"] del directives._directives["automethod"] app.add_autodocumenter(ExtendedFunctionDocumenter) app.add_autodocumenter(ExtendedMethodDocumenter) # A monkey-patch to VariableCommentPicker to make autodoc_member_order = 'bysource' work. from sphinx.pycode.parser import VariableCommentPicker if not hasattr(VariableCommentPicker, "visit_AsyncFunctionDef"): # pragma: no branch VariableCommentPicker.visit_AsyncFunctionDef = ( # type: ignore VariableCommentPicker.visit_FunctionDef # type: ignore ) return {'version': __version__, 'parallel_read_safe': True} sphinxcontrib-trio-1.1.2/sphinxcontrib_trio/_version.py000066400000000000000000000000261365403637100235130ustar00rootroot00000000000000__version__ = "1.1.2" sphinxcontrib-trio-1.1.2/test-requirements.in000066400000000000000000000001041365403637100214130ustar00rootroot00000000000000pytest pytest-cov async_generator contextlib2 lxml cssselect sphinx sphinxcontrib-trio-1.1.2/test-requirements.txt000066400000000000000000000032431365403637100216330ustar00rootroot00000000000000# # This file is autogenerated by pip-compile # To update, run: # # pip-compile test-requirements.in # alabaster==0.7.12 # via sphinx async-generator==1.10 # via -r test-requirements.in attrs==19.3.0 # via pytest babel==2.8.0 # via sphinx certifi==2020.4.5.1 # via requests chardet==3.0.4 # via requests contextlib2==0.6.0.post1 # via -r test-requirements.in coverage==5.1 # via pytest-cov cssselect==1.1.0 # via -r test-requirements.in docutils==0.16 # via sphinx idna==2.9 # via requests imagesize==1.2.0 # via sphinx jinja2==2.11.2 # via sphinx lxml==4.5.0 # via -r test-requirements.in markupsafe==1.1.1 # via jinja2 more-itertools==8.2.0 # via pytest packaging==20.3 # via pytest, sphinx pluggy==0.13.1 # via pytest py==1.8.1 # via pytest pygments==2.6.1 # via sphinx pyparsing==2.4.7 # via packaging pytest-cov==2.8.1 # via -r test-requirements.in pytest==5.4.1 # via -r test-requirements.in, pytest-cov pytz==2020.1 # via babel requests==2.23.0 # via sphinx six==1.14.0 # via packaging snowballstemmer==2.0.0 # via sphinx sphinx==3.0.3 # via -r test-requirements.in sphinxcontrib-applehelp==1.0.2 # via sphinx sphinxcontrib-devhelp==1.0.2 # via sphinx sphinxcontrib-htmlhelp==1.0.3 # via sphinx sphinxcontrib-jsmath==1.0.1 # via sphinx sphinxcontrib-qthelp==1.0.3 # via sphinx sphinxcontrib-serializinghtml==1.1.4 # via sphinx urllib3==1.25.9 # via requests wcwidth==0.1.9 # via pytest sphinxcontrib-trio-1.1.2/tests/000077500000000000000000000000001365403637100165325ustar00rootroot00000000000000sphinxcontrib-trio-1.1.2/tests/test-docs-source/000077500000000000000000000000001365403637100217355ustar00rootroot00000000000000sphinxcontrib-trio-1.1.2/tests/test-docs-source/autodoc_examples.py000066400000000000000000000016751365403637100256540ustar00rootroot00000000000000import abc def basic(): pass async def asyncfn(x): pass def gen(): yield # Classes are a bit complicated for autodoc, because: # - there's the :members: option # - how you access the attributes matters class ExampleClass(abc.ABC): @abc.abstractmethod def abstractmethod_(self): pass @classmethod @abc.abstractmethod def classabstract(cls): pass @classmethod def classmethod_(cls): pass async def asyncmethod(self): pass @property def property_(self): pass class ExampleClassForOrder: async def d_asyncmethod(self): pass def a_syncmethod(self): pass async def c_asyncmethod(self): pass def b_syncmethod(self): pass class ExampleInheritedSubclass(ExampleClassForOrder): def a_syncmethod(self): pass async def c_asyncmethod(self): pass async def autosummary_me(): pass sphinxcontrib-trio-1.1.2/tests/test-docs-source/conf.py000066400000000000000000000005651365403637100232420ustar00rootroot00000000000000# So autodoc can find our test code import sys import os import os.path sys.path.insert(0, os.path.abspath(".")) extensions = [ # Don't include sphinx.ext.autodoc, to test for gh-9 "sphinxcontrib_trio", # Needed to test for gh-8 "sphinx.ext.autosummary", ] autosummary_generate = True source_suffix = ".rst" master_doc = "test" html_theme = "alabaster" sphinxcontrib-trio-1.1.2/tests/test-docs-source/test.rst000066400000000000000000000227411365403637100234540ustar00rootroot00000000000000===================================== sphinxcontrib-trio end-to-end tests ===================================== Each ``note`` in this file is a test case. The ``test_end_to_end`` function in ``test_sphinxcontrib_trio.py`` loops through the rendered output of each ``note``, and for each one it finds all the "none" code-blocks, and it makes sure that the contents of that code-block appears in the html source for the rest of the note. It also runs all ``warning``\s as tests in the same way, but for these it checks that they fail. This acts as a check that the test harness is actually working, and can be used for negative tests. Currently there is no normalization applied to the HTML. We can add it later if it turns out to be a problem... Basic smoke tests ================= .. note:: .. function:: foo(bar) :noindex: :async: .. code-block:: none await foo .. warning:: .. function:: foo(bar) :noindex: .. code-block:: none await foo Check all the formatting logic ============================== .. note:: .. method:: foo(bar) :noindex: :abstractmethod: :staticmethod: :async: .. code-block:: none abstractmethod staticmethod await foo .. note:: .. method:: foo(bar) :noindex: :classmethod: .. code-block:: none classmethod foo .. note:: .. function:: foo(bar) :noindex: :with: .. code-block:: none with foo .. note:: .. method:: foo(bar) :noindex: :with: baz .. code-block:: none with foo\(()?bar()?\) as baz .. note:: .. method:: foo(bar) :noindex: :async-with: .. code-block:: none async with foo .. note:: .. method:: foo(bar) :noindex: :async-with: baz .. code-block:: none async with foo\(()?bar()?\) as baz This one checks that decorators don't normally have parentheses: .. note:: .. decorator:: foo :noindex: .. code-block:: none @foo But if you do have arguments, they're displayed .. note:: .. decorator:: foo(bar) :noindex: .. code-block:: none @foo\(()?bar()? Same for properties, in case someone uses `.. method:: :property:` (instead of the more usual `.. data::`), or sphinx 2.1 uses it for us: .. note:: .. method:: foo() :noindex: :property: .. code-block:: none foo .. note:: .. method:: foo(bar) :noindex: :for: .. code-block:: none for ... in foo .. note:: .. method:: foo(bar) :noindex: :for: baz .. code-block:: none for baz in foo .. note:: .. method:: foo(bar) :noindex: :async-for: .. code-block:: none async for ... in foo .. note:: .. method:: foo(bar) :noindex: :async-for: baz .. code-block:: none async for baz in foo Backwards compatibility directives ================================== .. note:: .. decorator:: foo :noindex: .. code-block:: none @foo .. note:: .. decoratormethod:: foo :noindex: .. code-block:: none @foo .. note:: .. classmethod:: foo(bar) :noindex: .. code-block:: none classmethod foo .. note:: .. staticmethod:: foo(bar) :noindex: .. code-block:: none staticmethod foo Autodoc ======= .. module:: autodoc_examples Autodoc smoke tests: .. note:: .. autofunction:: basic :noindex: .. code-block:: none autodoc_examples.basic .. warning:: .. autofunction:: basic :noindex: .. code-block:: none basic .. note:: .. autofunction:: asyncfn :noindex: .. code-block:: none await autodoc_examples.asyncfn We don't bother testing every bizarro combination here, because we have unit tests for that. But classes in particular are tricky, because (a) you have to look up members the right way or ``classmethod`` and ``staticmethod`` hide from you, and (b) you have to integrate correctly with autodoc for ``:members:`` to automatically use your custom directives. .. note:: .. autoclass:: ExampleClass :noindex: :members: :undoc-members: .. code-block:: none abstractmethod abstractmethod_ .. code-block:: none abstractmethod classmethod classabstract .. code-block:: none classmethod classmethod_ .. code-block:: none await asyncmethod Autodoc + order by source: .. autoclass:: ExampleClassForOrder :members: :undoc-members: Autodoc + inherited methods: .. note:: .. autoclass:: ExampleInheritedSubclass :noindex: :members: :undoc-members: :inherited-members: .. code-block:: none await c_asyncmethod .. code-block:: none await d_asyncmethod .. warning:: .. autoclass:: ExampleInheritedSubclass :noindex: :members: :undoc-members: :inherited-members: .. code-block:: none await a_syncmethod .. code-block:: none await b_syncmethod Autodoc + explicit options: .. note:: .. autofunction:: basic :noindex: :for: :async: .. code-block:: none for ... in await autodoc_examples.basic Overriding sniffed ``:for:`` with ``:for: arg``: .. note:: .. autofunction:: gen :noindex: .. code-block:: none for ... in autodoc_examples.gen .. note:: .. autofunction:: gen :noindex: :for: arg .. code-block:: none for arg in autodoc_examples.gen Testing ``:no-auto-options:``: .. note:: .. autofunction:: gen :noindex: :no-auto-options: .. code-block:: none
autodoc_examples.gen .. warning:: .. autofunction:: gen :noindex: :no-auto-options: .. code-block:: none for .. note:: .. autofunction:: gen :noindex: :no-auto-options: :for: .. code-block:: none for ... in autodoc_examples.gen .. note:: .. autofunction:: gen :noindex: :no-auto-options: :async: .. code-block:: none await autodoc_examples.gen Autodoc + Autosummary --------------------- See: https://github.com/python-trio/sphinxcontrib-trio/issues/8 Previously the presence of this code in the file (when combined with ``autosummary_generate = True`` in ``conf.py``) would cause all the *other* ``autofunction`` tests to fail... .. autosummary:: :toctree: autosummary_me sphinxcontrib-trio-1.1.2/tests/test_sphinxcontrib_trio.py000066400000000000000000000165721365403637100241050ustar00rootroot00000000000000import re import abc import sys import shutil import inspect import textwrap import subprocess from pathlib import Path from functools import wraps from typing import Callable, cast from contextlib import contextmanager import lxml.html try: from contextlib2 import contextmanager as contextmanager2 except ImportError: have_contextmanager2 = False else: have_contextmanager2 = True try: from async_generator import async_generator, yield_ except ImportError: have_async_generator = False else: have_async_generator = True try: from contextlib import asynccontextmanager except ImportError: have_asynccontextmanager = False else: have_asynccontextmanager = True from sphinxcontrib_trio import sniff_options if sys.version_info >= (3, 6): agen_native = cast(Callable, lambda: None) # satisfy linter exec(textwrap.dedent(""" async def agen_native(): yield """)) def test_sniff_options(): def check(obj, *expected): __tracebackhide__ = True assert sniff_options(obj) == set(expected) def boring(): # pragma: no cover pass check(boring) class Basic: # pragma: no cover def a(self): pass @classmethod def b(cls): pass @staticmethod def c(self): pass @classmethod async def classasync(cls): pass check(inspect.getattr_static(Basic, "a")) check(inspect.getattr_static(Basic, "b"), "classmethod") check(inspect.getattr_static(Basic, "c"), "staticmethod") check(inspect.getattr_static(Basic, "classasync"), "classmethod", "async") class Abstract(abc.ABC): # pragma: no cover @abc.abstractmethod def abmeth(self): pass @staticmethod @abc.abstractmethod def abstatic(self): pass @staticmethod @abc.abstractmethod async def abstaticasync(self): pass check(inspect.getattr_static(Abstract, "abmeth"), "abstractmethod") check(inspect.getattr_static(Abstract, "abstatic"), "abstractmethod", "staticmethod") check( inspect.getattr_static(Abstract, "abstaticasync"), "abstractmethod", "staticmethod", "async", ) async def async_fn(): # pragma: no cover pass check(async_fn, "async") def gen(): # pragma: no cover yield check(gen, "for") if have_async_generator: @async_generator async def agen(): # pragma: no cover await yield_() check(agen, "async-for") if "agen_native" in globals(): check(agen_native, "async-for") @contextmanager def cm(): # pragma: no cover yield check(cm, "with") if have_contextmanager2: @contextmanager2 def cm2(): # pragma: no cover yield check(cm2, "with") def manual_cm(): # pragma: no cover pass manual_cm.__returns_contextmanager__ = True # type: ignore check(manual_cm, "with") def manual_acm(): # pragma: no cover pass manual_acm.__returns_acontextmanager__ = True # type: ignore check(manual_acm, "async-with") if have_async_generator: @async_generator async def acm_gen(): # pragma: no cover await yield_() @wraps(acm_gen) def acm_wrapped(): # pragma: no cover pass acm_wrapped.__returns_acontextmanager__ = True # type: ignore check(acm_wrapped, "async-with") if have_asynccontextmanager: acm = asynccontextmanager(agen_native) check(acm, "async-with") # A chain with complex overrides. We ignore the intermediate generator and # async function, because the outermost one is a contextmanager -- but we # still pick up the staticmethod at the end of the chain. @staticmethod # type: ignore def messy0(): # pragma: no cover pass async def messy1(): # pragma: no cover pass messy1.__wrapped__ = messy0 # type: ignore def messy2(): # pragma: no cover yield messy2.__wrapped__ = messy1 # type: ignore def messy3(): # pragma: no cover pass messy3.__wrapped__ = messy2 # type: ignore messy3.__returns_contextmanager__ = True # type: ignore check(messy3, "with", "staticmethod") # Hopefully the next sphinx release will have dedicated pytest-based testing # utilities: # # https://github.com/sphinx-doc/sphinx/issues/3458 # https://github.com/sphinx-doc/sphinx/pull/3718 # # Until then... def test_end_to_end(tmpdir): shutil.copytree(str(Path(__file__).parent / "test-docs-source"), str(tmpdir / "test-docs-source")) subprocess.run( ["sphinx-build", "-v", "-nW", "-nb", "html", str(tmpdir / "test-docs-source"), str(tmpdir / "out")]) tree = lxml.html.parse(str(tmpdir / "out" / "test.html")).getroot() def do_html_test(node, *, expect_match): original_content = node.text_content() print("\n-- test case --\n", lxml.html.tostring(node, encoding="unicode")) check_tags = node.cssselect(".highlight-none") checks = [] for tag in check_tags: text = tag.text_content().strip() # lxml normalizes   to the unicode \xa0, so we do the same text = text.replace(" ", "\xa0") checks.append(text) tag.drop_tree() # make sure we removed the tests from the top-level node, to avoid # potential false positives matching on the tests themselves! assert len(node.text_content()) < len(original_content) assert checks test_content = lxml.html.tostring(node, encoding="unicode") # some versions of sphinx (>= 1.6) replace "..." with the ellipsis # character \u2026. Normalize back to "..." for comparison # purposes. test_content = test_content.replace("\u2026", "...") for check in checks: try: if expect_match: assert re.search(check, test_content) is not None else: assert re.search(check, test_content) is None except AssertionError: print("failed check") print() print(repr(check)) print() print("failed test_content") print() print(repr(test_content)) raise print("\n-- NEGATIVE (WARNING) TESTS --\n") for warning in tree.cssselect(".warning"): do_html_test(warning, expect_match=False) print("\n-- POSITIVE (NOTE) TESTS --\n") for note in tree.cssselect(".note"): do_html_test(note, expect_match=True) def test_member_order(tmpdir): shutil.copytree(str(Path(__file__).parent / "test-docs-source"), str(tmpdir / "test-docs-source")) subprocess.run( ["sphinx-build", "-v", "-nW", "-D", "autodoc_member_order=bysource", "-nb", "html", str(tmpdir / "test-docs-source"), str(tmpdir / "out")]) tree = lxml.html.parse(str(tmpdir / "out" / "test.html")).getroot() print("\n-- test case member order by source. --\n") methods = ( tree.cssselect(r"#autodoc_examples\.ExampleClassForOrder")[0].getnext().cssselect("dt") ) names = [method.get("id").split(".")[-1] for method in methods] assert names == ["d_asyncmethod", "a_syncmethod", "c_asyncmethod", "b_syncmethod"]