pax_global_header00006660000000000000000000000064141166101300014503gustar00rootroot0000000000000052 comment=9793d89b3dc4577791cb14921bb635300759cd5c sphinxcontrib-bibtex-2.4.1/000077500000000000000000000000001411661013000156545ustar00rootroot00000000000000sphinxcontrib-bibtex-2.4.1/.coveragerc000066400000000000000000000002231411661013000177720ustar00rootroot00000000000000[run] branch = True source = test,sphinxcontrib [report] exclude_lines = pragma: no cover if TYPE_CHECKING: raise NotImplementedError sphinxcontrib-bibtex-2.4.1/.github/000077500000000000000000000000001411661013000172145ustar00rootroot00000000000000sphinxcontrib-bibtex-2.4.1/.github/workflows/000077500000000000000000000000001411661013000212515ustar00rootroot00000000000000sphinxcontrib-bibtex-2.4.1/.github/workflows/python-package.yml000066400000000000000000000033661411661013000247160ustar00rootroot00000000000000name: Python package on: push: branches: [ develop ] pull_request: branches: [ develop ] jobs: build: runs-on: ubuntu-latest strategy: fail-fast: false matrix: python-version: [3.7, 3.8, 3.9] pip-sphinx: [sphinx] include: - python-version: 3.9 pip-sphinx: sphinx==2.1 - python-version: 3.9 pip-sphinx: --pre sphinx steps: - uses: actions/checkout@v2 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v2 with: python-version: ${{ matrix.python-version }} - name: Install dependencies run: | python -m pip install --upgrade pip python -m pip install pytest codecov coverage python -m pip install ${{ matrix.pip-sphinx }} pip install . - name: Install extra dependencies run: | python -m pip install flake8 check-manifest mypy types-setuptools types-docutils if: matrix.pip-sphinx == 'sphinx' && matrix.python-version == '3.9' - name: Check manifest run: | check-manifest if: matrix.pip-sphinx == 'sphinx' && matrix.python-version == '3.9' - name: Lint with flake8 run: | flake8 . --count --select=E9,F63,F7,F82 --show-source flake8 . --count --max-complexity=10 if: matrix.pip-sphinx == 'sphinx' && matrix.python-version == '3.9' - name: Type checking with mypy run: mypy if: matrix.pip-sphinx == 'sphinx' && matrix.python-version == '3.9' - name: Documentation run: | pushd doc && make html && popd if: matrix.pip-sphinx == 'sphinx' && matrix.python-version == '3.9' - name: Test with pytest run: | coverage run -m pytest codecov sphinxcontrib-bibtex-2.4.1/.gitignore000066400000000000000000000002011411661013000176350ustar00rootroot00000000000000*~ *.pyc .noseids .coverage nosetests.xml doc/_build/ .pytest_cache/ .mypy_cache/ venv/ htmlcov/ .idea/ *.egg-info/ dist/ build/ sphinxcontrib-bibtex-2.4.1/CHANGELOG.rst000066400000000000000000000413471411661013000177060ustar00rootroot000000000000002.4.1 (10 September 2021) ------------------------- * Gracefully handle textual citations when author or year are missing (see issue #267, reported by fbkarsdorp). 2.4.0 (8 September 2021) ------------------------ * Allow specific warnings to be suppressed (see issue #255, contributed by stevenrhall). * Fix parsing of LaTeX url commands in bibtex fields (see issue #258, reported by Matthew Giassa). * Remove space between footnote and author for textual footnote citations in the default foot referencing style. * Document how to use a backslash escaped space to suppress space before footnotes (see issue #256, reported by hagenw). * Parse all bib files together, so macros specified in one file can be used in another file (see issue #216, reported by mforbes). As a consequence, duplicate citation keys across bib files will now also result in proper warnings. The ``parse_bibfile`` and ``process_bibfile`` functions have been been replaced by ``parse_bibdata`` and ``process_bibdata`` in the API. * New ``bibtex_cite_id``, ``bibtex_footcite_id``, ``bibtex_bibliography_id``, and ``bibtex_footbibliography_id`` settings, which allow custom ids (which can be used as html anchors) to be generated for citations and bibliographies, based on the citation keys rather than some random numbers (see issue #264, reported by kmuehlbauer). Refer to the documentation for detailed usage and examples. * Switch to github actions for regression testing. * The API is now fully type checked. * Various minor improvements in documentation and code. 2.3.0 (1 June 2021) ------------------- * Add ``:footcite:p:`` and ``:footcite:t:`` roles. For capitalizing the first letter and/or listing the full author list, you can use ``:footcite:ct:``, ``:footcite:ts:``, ``:footcite:cts:``, and ``:footcite:ps:``. * To configure your footnote referencing style, an optional config setting ``bibtex_foot_reference_style`` has been added. If not specified, this defaults to the ``foot`` style, which will use plain footnote references for citation references, matching the referencing style as in previous versions. Footnote reference styles can be fully customized to your heart's desire, similar to regular citation reference styles. * New ``:cite:empty:`` role which registers a citation without generating a reference, similar to LaTeX's nocite command (see issue #131). * Citation keys can now be listed directly under the bibliography directive, one key per line; such citations will always be included, regardless of any filter settings (see issue #54). * A plain text preview of the full citation information will be shown when hovering over a citation reference (see issue #198, requested by eric-wieser). * The separator between the text and the reference of all textual citation styles can now be customized. 2.2.1 (16 May 2021) ------------------- * The LaTeX output now uses hyperlink instead of sphinxcite. This fixes issues with double brackets and other mismatches between LaTeX and HTML outputs (see issue #244 reported by zhi-wang). * The setup function now also returns the version of the extension (see issue #239 reported by lcnittl). 2.2.0 (5 March 2021) -------------------- * Support the ``:any:`` role (see issue #232). * New natbib/biblatex inspired roles for textual and parenthetical citation references (see issue #203 reported by matthew-brett). For textual citation references, use ``:cite:t:`` and for parenthetical citation references, use ``:cite:p:``. The old ``:cite:`` role is an alias for ``:cite:p:``. * Use the ``s`` suffix to include the full author list rather than abbreviating it with "et al.": ``:cite:ts:``, ``:cite:ps:``. * For textual citation references, use the ``c`` prefix to capitalize the first letter: ``:cite:ct:``, ``:cite:cts:``. * New natbib inspired roles for citing just the author, year, or label, optionally with brackets, and optionally capitalizing the first letter of the author: ``:cite:author:``, ``:cite:authorpar:``, ``:cite:cauthor:``, ``:cite:cauthorpar:`` ``:cite:year:``, ``:cite:yearpar:``, ``:cite:label:``, ``:cite:labelpar:`` (see issue #71 reported by bk322). * To configure your referencing style, an optional config setting ``bibtex_reference_style`` has been added. If not specified, this defaults to the ``label`` style, which will use the label to format citation references, matching the referencing style as in previous versions. The other style currently available is ``author_year``, for author-year style referencing. * Reference styles can be fully customized to your heart's desire (see issue #203 reported by amichuda). They are based on pybtex's template system, which was already used for customizing bibliography styles. Refer to the user documentation for examples, and to the API documentation for full details. * Other packages can register custom reference styles through entry points. Refer to the user documentation for details. * Propagate pybtex FieldIsMissing exception as a warning (see issue #235 reported by Zac-HD). 2.1.4 (8 January 2021) ---------------------- * Fix ValueError exception when having citations from orphans (see issue #228, reported by VincentRouvreau). 2.1.3 (1 January 2021) ---------------------- * Sphinx 2.1 or later is now formally required (up from 2.0). * Fix unresolved references when running the latex build immediately after the html build, or when rerunning the html build after deleting the generated html files without deleting the pickled doctrees/environment (see issue #226, reported by skirpichev). * No longer insert user defined header for bibliography directives if there are no citations in it. * Warnings now consistently provide source file and line number of where the issue originated. * Simpler and faster implementation of footcite and footbibliography. * Improved type annotations throughout the API, now using forward declarations where possible. 2.1.2 (30 December 2020) ------------------------ * Fix KeyError exception when building documents with footbibliography directives but without any footnotes needing to be generated for this directive (see issue #223, reported by drammock). 2.1.1 (29 December 2020) ------------------------ * Fix latex builder KeyError exception (see issue #221, reported by jedbrown). * Fix citation references across documents in latex build. 2.1.0 (28 December 2020) ------------------------ * The extension no longer relies on the ``bibtex.json`` method. Instead, the extension now postpones identifying all citation cross-references to Sphinx's consistency check phase. The actual citation references and bibliography citations are then generated in the resolve phase using post-transforms. As a result, ``bibtex.json`` is no longer needed and thus Sphinx no longer needs to run twice as in the past if the file did not exist (closes issues #214 and #215). *Thanks to everyone who chimed in on this, especially everyone who made helpful suggestions to find better implementation approaches, and everyone who helped with testing.* * Citations with multiple keys will now reside in the same bracket (closes issue #94). * Consistent use of doctutils note_explicit_target to set ids, to ensure no clashing ids. * Improved and robustified test suite, using regular expressions to verify generated html. * The test suite now includes a patched version of the awesome but abandoned sphinx-natbib extension, to help comparing and testing implementations and features. The long term intention is to fully support sphinx-natbib style citations. * **BACKWARD INCOMPATIBLE** The API has been refactored to accommodate the new design. Refer to the API documentation for details. 2.0.0 (12 December 2020) ------------------------ * There is a new ``footcite`` role and a new ``footbibliography`` directive, to allow easy and simple local (per document) bibliographies through footnotes. See issues #184 and #185. * Parallel builds are now finally supported. See issues #80, #96, and #164, as well as pull request #210. * **BACKWARD INCOMPATIBLE** To enable parallel builds, a new mandatory config setting ``bibtex_bibfiles`` has been added. This setting specifies all bib files used throughout the project, relative to the source folder. * **BACKWARD INCOMPATIBLE** The encoding of bib files has been moved to an optional config setting ``bibtex_encoding``. The ``:encoding:`` option is no longer supported. * Headers for ``bibliography`` and ``footbibliography`` directives can be configured via the ``bibtex_bibliography_header`` and ``bibtex_footbibliography_header`` config setting. * The ``bibliography`` directive no longer requires the bib files to be specified as an argument. However, if you do, citations will be constrained to those bib files. * Support newlines/whitespace around cite keys when multiple keys are specified. Thanks to dizcza for help with testing. See issue #205 and pull request #206. * Improve citation ordering code (reported by ukos-git, see issue #182). * The unresolved citations across documents issue has been resolved. The extension stores all citation information in a ``bibtex.json`` file. If it does not exist, the file will be created on your first sphinx build, and you will have to rerun the build to make use of it. The file is automatically kept up to date, with a warning whenever you need to rerun the build. Thanks to dizcza for help with testing. See issues #197 and #204. Also see pull request #208. * Migrate test suite to pytest, using sphinx's testing fixtures. * **BACKWARD INCOMPATIBLE** The API has been refactored. Some functions have moved to different modules. Refer to the API documentation for details. * Drop Python 3.5 support. * Add Python 3.9 support. 1.0.0 (20 September 2019) ------------------------- * Drop Python 2.7 and 3.4 support (as upstream sphinx has dropped support for these as well). * Add Python 3.8 support (contributed by hroncok). * Update for Sphinx 2.x, and drop Sphinx 1.x support (as there is too much difference between the two versions). * Non-bibtex citations will now no longer issue warnings (fix contributed by chrisjsewell). * Switch to codecov for coverage reporting. 0.4.2 (7 January 2018) ---------------------- * Drop Python 3.3 support, add Python 3.7 support. * Work around issue with sphinx-testing on Fedora (reported by jamesjer in issue #157, fix contributed by mitya57 in pull request #158). 0.4.1 (28 November 2018) ------------------------ * Disable tinkerer test due to upstream bug. * Remove crossref test due to changed upstream behaviour in pybtex. * Fix latex test to match new upstream code generation. * Fix documentation of encoding option (contributed by Kai Mühlbauer). * Migrate to sphinx.util.logging in favour of old deprecated logging method. 0.4.0 (19 April 2018) --------------------- * Remove latexcodec and curly bracket strip functionality, as this is now supported by pybtex natively (see issue #127, reported by erosennin). * Fix tests failures with Sphinx 1.7 (see pull request #136, reported and fixed by mitya57). 0.3.6 (25 September 2017) ------------------------- * Real fix for issue #111 (again reported by jamesjer). * Fix test regressions due to latest Sphinx updates (see issues #115, #120, #121, and #122, reported by ndarmage and ghisvail). * Fix test regressions on ascii locale (see issue #121, reported by ghisvail). * Support and test Python 3.6. 0.3.5 (22 February 2017) ------------------------ * Fix extremely high memory usage when handling large bibliographies (reported by agjohnson, see issue #102). * Fix tests for Sphinx 1.5.1 (see issue #111, reported by jamesjer). 0.3.4 (20 May 2016) ------------------- * Document LaTeX workaround for ``:cite:`` in figure captions (contributed by xuhdev, see issue #92 and pull request #93). * Add ``bibtex_default_style`` config value to override the default bibliography style (see issue #91 and pull request #97). * Support Python 3.5 (see issue #100). 0.3.3 (23 October 2015) ----------------------- * Add per-bibliography key prefixes, enabling local bibliographies to be used in isolation from each other (see issue #87, reported by marscher). * Documentation now points to new location of pybtex on bitbucket. * Simplified testing code by using the new sphinx_testing package. 0.3.2 (20 March 2015) --------------------- * Document how to create custom label styles (see issue #77, reported by tino). * Disable parallel_read_safe for Sphinx 1.3 and later (see issue #80, reported by andreacassioli). 0.3.1 (10 July 2014) -------------------- * Fix for ``type_.lower()`` bug: pybtex 0.18 expects type to be a string (this fixes issue #68 reported by jluttine). 0.3.0 (4 May 2014) ------------------ * **BACKWARD INCOMPATIBLE** The alpha style is now default, so citations are labelled in a way that is more standard for Sphinx. To get the old behaviour back, add ``:style: plain`` to your bibliography directives. * **BACKWARD INCOMPATIBLE** :meth:`~sphinxcontrib.bibtex.cache.Cache.is_cited` has been removed. Use :meth:`~sphinxcontrib.bibtex.cache.Cache.get_cited_docnames` instead, which will return an empty list for keys that are not cited. * Improved support for local bibliographies (see issues #52, #62, and #63; test case provided by Boris Kheyfets): - New ``docname`` and ``docnames`` filter identifiers. - Filter expressions now also support set literals and the operators ``in``, ``not in``, ``&``, and ``|``. See documentation for details. * Multiple comma-separated citation keys per cite command (see issue #61, suggested by Boris Kheyfets). * Add support for pypy and Python 3.4. * Drop support for Python 2.6 and Python 3.2. * Drop 2to3 and instead use six to support both Python 2 and 3 from a single code base. * Simplify instructions for custom styles. * Various test suite improvements. 0.2.9 (9 October 2013) ---------------------- * Upgrade to the latest pybtex-docutils to produce more optimal html output (specifically: no more nested ````\ s). * Remove latex codec code, and rely on latexcodec package instead. * :class:`FilterVisitor` has been removed from the public API. Use :meth:`~sphinxcontrib.bibtex.cache.Cache.get_bibliography_entries` instead. * Fix upstream Sphinx bug concerning LaTeX citation hyperlinks (contributed by erikb85; see pull request #45). * Fix most pylint warnings, refactor code. 0.2.8 (7 August 2013) --------------------- * Use pybtex-docutils to remove dependency on pybtex.backends.doctree. 0.2.7 (4 August 2013) --------------------- * Integrate with coveralls.io, first release with 100% test coverage. * Minor bug fixes and code improvements. * Remove ordereddict dependency for Python 2.7 and higher (contributed by Paul Romano, see pull requests #27 and #28). * New ``:filter:`` option for advanced filtering (contributed by d9pouces, see pull requests #30 and #31). * Refactor documentation of advanced features. * Document how to create custom pybtex styles (see issues #25, #29, and #34). * Code is now mostly pep8 compliant. 0.2.6 (2 March 2013) -------------------- * For unsorted styles, citation entries are now sorted in the order they are cited, instead of following the order in the bib file, to reflect more closely the way LaTeX handles unsorted styles (addresses issue #15). * Skip citation label warnings on Sphinx [source] links (issue #17, contributed by Simon Clift). 0.2.5 (18 October 2012) ----------------------- * Duplicate label detection (issue #14). * New ``:labelprefix:`` option to avoid duplicate labels when having multiple bibliographies with a numeric label style (addresses issue #14). 0.2.4 (24 August 2012) ---------------------- * New options for the bibliography directive for rendering the bibliography as bullet lists or enumerated lists: ``:list:``, ``:enumtype:``, and ``:start:``. * Minor latex codec fixes. * Turn exception into warning when a citation cannot be relabeled (fixes issue #2). * Document LaTeX encoding, and how to turn it off (issue #4). * Use pybtex labels (fixes issue #6 and issue #7). * Cache tracked citation keys and labels, and bibliography enumeration counts (fixes issues with citations in repeated Sphinx runs). * Bibliography ids are now unique across documents (fixes issue that could cause the wrong bibliography to be inserted). * The plain style is now the default (addresses issue #9). 0.2.3 (30 July 2012) -------------------- * Document workaround for Tinkerer (issue #1). * Use tox for testing. * Full 2to3 compatibility. * Document supported versions of Python (2.6, 2.7, 3.1, and 3.2). 0.2.2 (6 July 2012) ------------------- * Documentation and manifest fixes. 0.2.1 (19 June 2012) -------------------- * First public release. sphinxcontrib-bibtex-2.4.1/LICENSE.rst000066400000000000000000000025541411661013000174760ustar00rootroot00000000000000| sphinxcontrib-bibtex is a Sphinx extension for BibTeX style citations | Copyright (c) 2011-2021 by Matthias C. M. Troffaes | All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. sphinxcontrib-bibtex-2.4.1/MANIFEST.in000066400000000000000000000005161411661013000174140ustar00rootroot00000000000000include README.rst include CHANGELOG.rst include LICENSE.rst include requirements.txt include mypy.ini include pytest.ini include .coveragerc recursive-include src *.py py.typed recursive-include doc * recursive-include test * global-exclude *.pyc exclude .gitignore exclude .travis.yml exclude release_checklist.txt prune doc/_build sphinxcontrib-bibtex-2.4.1/README.rst000066400000000000000000000111571411661013000173500ustar00rootroot00000000000000sphinxcontrib-bibtex ==================== |ci| |codecov| |version| |license| Sphinx extension for BibTeX style citations. Overview -------- The bibtex extension allows `BibTeX `_ citations to be inserted into documentation generated by `Sphinx `_, via a ``bibliography`` directive, along with ``:cite:p:`` and ``:cite:t:`` roles. These work similarly to LaTeX's ``thebibliography`` environment and the ``\citet`` and ``\citep`` commands. For formatting, the extension relies on `pybtex `_ written by Andrey Golovizin. The extension is inspired by Matthew Brett's `bibstuff.sphinxext.bibref `_ and Weston Nielson's `sphinx-natbib `_. * Download: https://pypi.org/project/sphinxcontrib-bibtex/#files * Documentation: https://sphinxcontrib-bibtex.readthedocs.io/en/latest/ * Development: https://github.com/mcmtroffaes/sphinxcontrib-bibtex/ .. |ci| image:: https://github.com/mcmtroffaes/sphinxcontrib-bibtex/actions/workflows/python-package.yml/badge.svg :target: https://github.com/mcmtroffaes/sphinxcontrib-bibtex/actions/workflows/python-package.yml :alt: ci .. |codecov| image:: https://codecov.io/gh/mcmtroffaes/sphinxcontrib-bibtex/branch/develop/graph/badge.svg :target: https://app.codecov.io/gh/mcmtroffaes/sphinxcontrib-bibtex :alt: codecov .. |version| image:: https://img.shields.io/pypi/v/sphinxcontrib-bibtex.svg :target: https://pypi.org/project/sphinxcontrib-bibtex/ :alt: latest version .. |license| image:: https://img.shields.io/pypi/l/sphinxcontrib-bibtex.svg :target: https://pypi.org/project/sphinxcontrib-bibtex/ :alt: license Installation ------------ Install the module with ``pip install sphinxcontrib-bibtex``, or from source using ``pip install -e .``. Then add: .. code-block:: python extensions = ['sphinxcontrib.bibtex'] bibtex_bibfiles = ['refs.bib'] to your project's Sphinx configuration file ``conf.py``. Installation with ``python setup.py install`` is discouraged due to potential issues with the sphinxcontrib namespace. Minimal Example --------------- In your project's documentation, you can use ``:cite:t:`` for textual citation references, ``:cite:p:`` for parenthetical citation references, and ``.. bibliography::`` for inserting the bibliography. For `example `_: .. code-block:: rest See :cite:t:`1987:nelson` for an introduction to non-standard analysis. Non-standard analysis is fun :cite:p:`1987:nelson`. .. bibliography:: where ``refs.bib`` would contain an entry:: @Book{1987:nelson, author = {Edward Nelson}, title = {Radically Elementary Probability Theory}, publisher = {Princeton University Press}, year = {1987} } In the default style, this will get rendered as: See Nelson [Nel87a]_ for an introduction to non-standard analysis. Non-standard analysis is fun [Nel87a]_. .. [Nel87a] Edward Nelson. *Radically Elementary Probability Theory*. Princeton University Press, 1987. Citations in sphinx are resolved globally across all documents. Typically, you have a single ``bibliography`` directive across your entire project which collects all citations. Advanced use cases with multiple ``bibliography`` directives across your project are also supported, but some care needs to be taken from your end to avoid duplicate citations. In contrast, footnotes in sphinx are resolved locally per document. To achieve local bibliographies per document, you can use citations represented by footnotes as follows: .. code-block:: rest See :footcite:t:`1987:nelson` for an introduction to non-standard analysis. Non-standard analysis is fun\ :footcite:p:`1987:nelson`. .. footbibliography:: which will get rendered as: See Nelson\ [#Nel87b]_ for an introduction to non-standard analysis. Non-standard analysis is fun\ [#Nel87b]_. .. [#Nel87b] Edward Nelson. *Radically Elementary Probability Theory*. Princeton University Press, 1987. Note the use of the `backslash escaped space `_ to suppress the space that would otherwise precede the footnote. Typically, you have a single ``footbibliography`` directive at the bottom of each document that has footnote citations. Advanced use cases with multiple ``footbibliography`` directives per document are also supported. Since everything is local, there is no concern with duplicate citations when using footnotes. sphinxcontrib-bibtex-2.4.1/doc/000077500000000000000000000000001411661013000164215ustar00rootroot00000000000000sphinxcontrib-bibtex-2.4.1/doc/Makefile000066400000000000000000000127631411661013000200720ustar00rootroot00000000000000# Makefile for Sphinx documentation # # You can set these variables from the command line. SPHINXOPTS = SPHINXBUILD = sphinx-build PAPER = BUILDDIR = _build # Internal variables. PAPEROPT_a4 = -D latex_paper_size=a4 PAPEROPT_letter = -D latex_paper_size=letter ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . # the i18n builder cannot share the environment and doctrees with the others I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext help: @echo "Please use \`make ' where is one of" @echo " html to make standalone HTML files" @echo " dirhtml to make HTML files named index.html in directories" @echo " singlehtml to make a single large HTML file" @echo " pickle to make pickle files" @echo " json to make JSON files" @echo " htmlhelp to make HTML files and a HTML help project" @echo " qthelp to make HTML files and a qthelp project" @echo " devhelp to make HTML files and a Devhelp project" @echo " epub to make an epub" @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" @echo " latexpdf to make LaTeX files and run them through pdflatex" @echo " text to make text files" @echo " man to make manual pages" @echo " texinfo to make Texinfo files" @echo " info to make Texinfo files and run them through makeinfo" @echo " gettext to make PO message catalogs" @echo " changes to make an overview of all changed/added/deprecated items" @echo " linkcheck to check all external links for integrity" @echo " doctest to run all doctests embedded in the documentation (if enabled)" clean: rm -rf $(BUILDDIR)/* html: $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." dirhtml: $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." singlehtml: $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml @echo @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." pickle: $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle @echo @echo "Build finished; now you can process the pickle files." json: $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json @echo @echo "Build finished; now you can process the JSON files." htmlhelp: $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp @echo @echo "Build finished; now you can run HTML Help Workshop with the" \ ".hhp project file in $(BUILDDIR)/htmlhelp." qthelp: $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp @echo @echo "Build finished; now you can run "qcollectiongenerator" with the" \ ".qhcp project file in $(BUILDDIR)/qthelp, like this:" @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/sphinxcontrib-bibtex.qhcp" @echo "To view the help file:" @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/sphinxcontrib-bibtex.qhc" devhelp: $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp @echo @echo "Build finished." @echo "To view the help file:" @echo "# mkdir -p $$HOME/.local/share/devhelp/sphinxcontrib-bibtex" @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/sphinxcontrib-bibtex" @echo "# devhelp" epub: $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub @echo @echo "Build finished. The epub file is in $(BUILDDIR)/epub." latex: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." @echo "Run \`make' in that directory to run these through (pdf)latex" \ "(use \`make latexpdf' here to do that automatically)." latexpdf: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo "Running LaTeX files through pdflatex..." $(MAKE) -C $(BUILDDIR)/latex all-pdf @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." text: $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text @echo @echo "Build finished. The text files are in $(BUILDDIR)/text." man: $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man @echo @echo "Build finished. The manual pages are in $(BUILDDIR)/man." texinfo: $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo @echo @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." @echo "Run \`make' in that directory to run these through makeinfo" \ "(use \`make info' here to do that automatically)." info: $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo @echo "Running Texinfo files through makeinfo..." make -C $(BUILDDIR)/texinfo info @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." gettext: $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale @echo @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." changes: $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes @echo @echo "The overview file is in $(BUILDDIR)/changes." linkcheck: $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck @echo @echo "Link check complete; look for any errors in the above output " \ "or in $(BUILDDIR)/linkcheck/output.txt." doctest: $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest @echo "Testing of doctests in the sources finished, look at the " \ "results in $(BUILDDIR)/doctest/output.txt." sphinxcontrib-bibtex-2.4.1/doc/api.rst000066400000000000000000000003421411661013000177230ustar00rootroot00000000000000Extension API ~~~~~~~~~~~~~ .. toctree:: :maxdepth: 2 api/interface api/roles api/nodes api/directives api/transforms api/domains api/bibfile api/referencing api/plugin api/pybtex sphinxcontrib-bibtex-2.4.1/doc/api/000077500000000000000000000000001411661013000171725ustar00rootroot00000000000000sphinxcontrib-bibtex-2.4.1/doc/api/bibfile.rst000066400000000000000000000001021411661013000213110ustar00rootroot00000000000000Bib Files ========= .. automodule:: sphinxcontrib.bibtex.bibfile sphinxcontrib-bibtex-2.4.1/doc/api/directives.rst000066400000000000000000000002261411661013000220650ustar00rootroot00000000000000New Docutils Directives ======================= .. automodule:: sphinxcontrib.bibtex.directives .. automodule:: sphinxcontrib.bibtex.foot_directives sphinxcontrib-bibtex-2.4.1/doc/api/domains.rst000066400000000000000000000001661411661013000213610ustar00rootroot00000000000000New Domains =========== .. automodule:: sphinxcontrib.bibtex.domain .. automodule:: sphinxcontrib.bibtex.foot_domain sphinxcontrib-bibtex-2.4.1/doc/api/interface.rst000066400000000000000000000001101411661013000216540ustar00rootroot00000000000000Sphinx Interface ================ .. automodule:: sphinxcontrib.bibtex sphinxcontrib-bibtex-2.4.1/doc/api/nodes.rst000066400000000000000000000001221411661013000210270ustar00rootroot00000000000000New Docutils Nodes ================== .. automodule:: sphinxcontrib.bibtex.nodes sphinxcontrib-bibtex-2.4.1/doc/api/plugin.rst000066400000000000000000000001121411661013000212140ustar00rootroot00000000000000Plugins ======= .. automodule:: sphinxcontrib.bibtex.plugin :members: sphinxcontrib-bibtex-2.4.1/doc/api/pybtex.rst000066400000000000000000000005261411661013000212420ustar00rootroot00000000000000Pybtex Extensions ================= New Text Elements ----------------- .. automodule:: sphinxcontrib.bibtex.richtext :members: New Template Nodes ------------------ .. automodule:: sphinxcontrib.bibtex.style.template :members: New Names Styles ---------------- .. automodule:: sphinxcontrib.bibtex.style.names.last :members: sphinxcontrib-bibtex-2.4.1/doc/api/referencing.rst000066400000000000000000000032061411661013000222140ustar00rootroot00000000000000Referencing Styles ================== Base Classes For Composing Styles --------------------------------- .. automodule:: sphinxcontrib.bibtex.style.referencing :members: Basic Styles ------------ Basic styles that support both textual and parenthetical citations. Should provide roles with names ``p``, ``ps``, ``t``, ``ts``, ``ct``, and ``cts``. Here, ``t`` stands for textual and ``p`` for parenthetical. The ``c`` prefix causes the first letter to be capitalized, and the ``s`` suffix causes all authors to be named rather than shortening the list using "et al." or some other suffix as specified by the style. .. automodule:: sphinxcontrib.bibtex.style.referencing.basic_label :members: .. automodule:: sphinxcontrib.bibtex.style.referencing.basic_author_year :members: Extra Styles ------------ For styles providing additional roles, e.g. for citations that specifically use the label, the author, the year, etc. The convention for these styles is to have one role for producing whichever text needs to be had, and to have a ``par`` suffix in the role name if the citation text needs to be embedded in brackets (for example ``label`` and ``labelpar``). .. automodule:: sphinxcontrib.bibtex.style.referencing.extra_label :members: .. automodule:: sphinxcontrib.bibtex.style.referencing.extra_author :members: .. automodule:: sphinxcontrib.bibtex.style.referencing.extra_year :members: Full Styles ----------- For styles that combine a basic style with one or more extra styles. .. automodule:: sphinxcontrib.bibtex.style.referencing.label :members: .. automodule:: sphinxcontrib.bibtex.style.referencing.author_year :members: sphinxcontrib-bibtex-2.4.1/doc/api/roles.rst000066400000000000000000000001601411661013000210450ustar00rootroot00000000000000New Roles ========= .. automodule:: sphinxcontrib.bibtex.roles .. automodule:: sphinxcontrib.bibtex.foot_roles sphinxcontrib-bibtex-2.4.1/doc/api/transforms.rst000066400000000000000000000001171411661013000221210ustar00rootroot00000000000000New Transforms ============== .. automodule:: sphinxcontrib.bibtex.transforms sphinxcontrib-bibtex-2.4.1/doc/changes.rst000066400000000000000000000000761411661013000205660ustar00rootroot00000000000000:tocdepth: 1 Changes ======= .. include:: ../CHANGELOG.rst sphinxcontrib-bibtex-2.4.1/doc/conf.py000066400000000000000000000176101411661013000177250ustar00rootroot00000000000000# sphinxcontrib-bibtex documentation build configuration file, created by # sphinx-quickstart on Thu Jun 13 13:56:25 2013. # # 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. import re # for extracting version # -- General configuration ----------------------------------------------- # If your documentation needs a minimal Sphinx version, state it here. needs_sphinx = '2.1' # 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', 'sphinx.ext.coverage', 'sphinx.ext.viewcode'] # The master toctree document. master_doc = 'index' # General information about the project. project = u'sphinxcontrib-bibtex' copyright = u'2011-2021, Matthias C. M. Troffaes' # 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. # # The full version, including alpha/beta/rc tags. with open("../src/sphinxcontrib/bibtex/__init__.py", "rt") as version_file: release = re.search("'version': '(.+)'", version_file.read()).group(1) # The short X.Y version. version = '.'.join(release.split('.')[:2]) # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. # language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: # today = '' # Else, today_fmt is used as the format for a strftime call. # today_fmt = '%B %d, %Y' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. exclude_patterns = ['_build'] # The reST default role (used for this markup: `text`) to use for all # documents. # default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. # add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). # add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. # show_authors = False # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' # A list of ignored prefixes for module index sorting. # modindex_common_prefix = [] # -- 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 = 'default' # uncommented for readthedocs # 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 themes here, relative to this directory. # html_theme_path = [] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". # html_title = None # A shorter title for the navigation bar. Default is the same as html_title. # html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. # html_logo = None # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. # html_favicon = None # 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'] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. # html_last_updated_fmt = '%b %d, %Y' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. # html_use_smartypants = True # Custom sidebar templates, maps document names to template names. # html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. # html_additional_pages = {} # If false, no module index is generated. # html_domain_indices = True # If false, no index is generated. # html_use_index = True # If true, the index is split into individual pages for each letter. # html_split_index = False # If true, links to the reST sources are added to the pages. # html_show_sourcelink = True # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. # html_show_sphinx = True # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. # html_show_copyright = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. # html_use_opensearch = '' # This is the file name suffix for HTML files (e.g. ".xhtml"). # html_file_suffix = None # Output file base name for HTML help builder. htmlhelp_basename = 'sphinxcontrib-bibtexdoc' # -- 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': '', } # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, documentclass # [howto/manual]). latex_documents = [ ('index', 'sphinxcontrib-bibtex.tex', u'sphinxcontrib-bibtex Documentation', u'Matthias C. M. Troffaes', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of # the title page. # latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. # latex_use_parts = False # If true, show page references after internal links. # latex_show_pagerefs = False # If true, show URL addresses after external links. # latex_show_urls = False # Documents to append as an appendix to all manuals. # latex_appendices = [] # If false, no module index is generated. # latex_domain_indices = True # -- Options for manual page output -------------------------------------- # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ ('index', 'sphinxcontrib-bibtex', u'sphinxcontrib-bibtex Documentation', [u'Matthias C. M. Troffaes'], 1) ] # If true, show URL addresses after external links. # man_show_urls = False # -- 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 = [ ('index', 'sphinxcontrib-bibtex', u'sphinxcontrib-bibtex Documentation', u'Matthias C. M. Troffaes', 'sphinxcontrib-bibtex', 'One line description of project.', 'Miscellaneous'), ] # Documents to append as an appendix to all manuals. # texinfo_appendices = [] # If false, no module index is generated. # texinfo_domain_indices = True # How to display URL addresses: 'footnote', 'no', or 'inline'. # texinfo_show_urls = 'footnote' # If true, do not generate a @detailmenu in the "Top" node's menu. # texinfo_no_detailmenu = False # Example configuration for intersphinx: refer to the Python standard library. intersphinx_mapping = { 'python': ('https://docs.python.org/3/', None), 'sphinx': ('http://www.sphinx-doc.org/en/master/', None), } sphinxcontrib-bibtex-2.4.1/doc/index.rst000066400000000000000000000005271411661013000202660ustar00rootroot00000000000000Welcome to sphinxcontrib-bibtex's documentation! ================================================ :Release: |release| :Date: |today| Contents -------- .. toctree:: :maxdepth: 2 quickstart usage api changes license related Indices and tables ================== * :ref:`genindex` * :ref:`modindex` * :ref:`search` sphinxcontrib-bibtex-2.4.1/doc/license.rst000066400000000000000000000000561411661013000205760ustar00rootroot00000000000000License ======= .. include:: ../LICENSE.rst sphinxcontrib-bibtex-2.4.1/doc/make.bat000066400000000000000000000120041411661013000200230ustar00rootroot00000000000000@ECHO OFF REM Command file for Sphinx documentation if "%SPHINXBUILD%" == "" ( set SPHINXBUILD=sphinx-build ) set BUILDDIR=_build set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . set I18NSPHINXOPTS=%SPHINXOPTS% . if NOT "%PAPER%" == "" ( set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% ) if "%1" == "" goto help if "%1" == "help" ( :help echo.Please use `make ^` where ^ is one of echo. html to make standalone HTML files echo. dirhtml to make HTML files named index.html in directories echo. singlehtml to make a single large HTML file echo. pickle to make pickle files echo. json to make JSON files echo. htmlhelp to make HTML files and a HTML help project echo. qthelp to make HTML files and a qthelp project echo. devhelp to make HTML files and a Devhelp project echo. epub to make an epub echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter echo. text to make text files echo. man to make manual pages echo. texinfo to make Texinfo files echo. gettext to make PO message catalogs echo. changes to make an overview over all changed/added/deprecated items echo. linkcheck to check all external links for integrity echo. doctest to run all doctests embedded in the documentation if enabled goto end ) if "%1" == "clean" ( for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i del /q /s %BUILDDIR%\* goto end ) if "%1" == "html" ( %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html if errorlevel 1 exit /b 1 echo. echo.Build finished. The HTML pages are in %BUILDDIR%/html. goto end ) if "%1" == "dirhtml" ( %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml if errorlevel 1 exit /b 1 echo. echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. goto end ) if "%1" == "singlehtml" ( %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml if errorlevel 1 exit /b 1 echo. echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. goto end ) if "%1" == "pickle" ( %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can process the pickle files. goto end ) if "%1" == "json" ( %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can process the JSON files. goto end ) if "%1" == "htmlhelp" ( %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can run HTML Help Workshop with the ^ .hhp project file in %BUILDDIR%/htmlhelp. goto end ) if "%1" == "qthelp" ( %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp if errorlevel 1 exit /b 1 echo. echo.Build finished; now you can run "qcollectiongenerator" with the ^ .qhcp project file in %BUILDDIR%/qthelp, like this: echo.^> qcollectiongenerator %BUILDDIR%\qthelp\sphinxcontrib-bibtex.qhcp echo.To view the help file: echo.^> assistant -collectionFile %BUILDDIR%\qthelp\sphinxcontrib-bibtex.ghc goto end ) if "%1" == "devhelp" ( %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp if errorlevel 1 exit /b 1 echo. echo.Build finished. goto end ) if "%1" == "epub" ( %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub if errorlevel 1 exit /b 1 echo. echo.Build finished. The epub file is in %BUILDDIR%/epub. goto end ) if "%1" == "latex" ( %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex if errorlevel 1 exit /b 1 echo. echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. goto end ) if "%1" == "text" ( %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text if errorlevel 1 exit /b 1 echo. echo.Build finished. The text files are in %BUILDDIR%/text. goto end ) if "%1" == "man" ( %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man if errorlevel 1 exit /b 1 echo. echo.Build finished. The manual pages are in %BUILDDIR%/man. goto end ) if "%1" == "texinfo" ( %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo if errorlevel 1 exit /b 1 echo. echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. goto end ) if "%1" == "gettext" ( %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale if errorlevel 1 exit /b 1 echo. echo.Build finished. The message catalogs are in %BUILDDIR%/locale. goto end ) if "%1" == "changes" ( %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes if errorlevel 1 exit /b 1 echo. echo.The overview file is in %BUILDDIR%/changes. goto end ) if "%1" == "linkcheck" ( %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck if errorlevel 1 exit /b 1 echo. echo.Link check complete; look for any errors in the above output ^ or in %BUILDDIR%/linkcheck/output.txt. goto end ) if "%1" == "doctest" ( %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest if errorlevel 1 exit /b 1 echo. echo.Testing of doctests in the sources finished, look at the ^ results in %BUILDDIR%/doctest/output.txt. goto end ) :end sphinxcontrib-bibtex-2.4.1/doc/quickstart.rst000066400000000000000000000001161411661013000213430ustar00rootroot00000000000000Getting Started =============== .. include:: ../README.rst :start-line: 7 sphinxcontrib-bibtex-2.4.1/doc/related.rst000066400000000000000000000027061411661013000206000ustar00rootroot00000000000000Related Projects ================ Below is a list of projects which include functionality that is similar or related to sphinxcontrib-bibtex. If you know of any other, leave a message on the issue tracker. * Andrey Golovizin's `pybtex `_, a general purpose Python library for working with bibtex files. Drives sphinxcontrib-bibtex. * Matthew Brett's `bibstuff `_. Includes a Sphinx extension similar to sphinxcontrib-bibtex, as well as an assorted collection of bibtex tools. This is a fork of Dylan W. Schwilk and Alan G. Isaac's `dschwilk/bibstuff `_. * Weston Nielson's sphinx-natbib. This extension is similar to sphinxcontrib-bibtex, and aims to support `natbib `_ style citations. Sadly, sphinx-natbib appears no longer maintained and the original repository is no longer available. A `patched version of sphinx-natbib `_, with various bug fixes, is maintained in the test suite of sphinxcontrib-bibtex, for the purpose of comparison. Additionally, a few forks of the original repository can be `found on github `_. * Jeff Terrace's Sphinx Thesis Resource `sphinxtr `_, is a fork of Sphinx which includes a fork of sphinx-natbib. sphinxcontrib-bibtex-2.4.1/doc/usage.rst000066400000000000000000000722471411661013000202730ustar00rootroot00000000000000Usage ===== Configuration ------------- Bibliography Files and Encoding ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. versionadded:: 2.0.0 To configure the extension, in your ``conf.py`` file, set ``bibtex_bibfiles`` to your list of bib files. For instance, a minimal configuration may look as follows: .. code-block:: python extensions = ['sphinxcontrib.bibtex'] bibtex_bibfiles = ['refs.bib'] In bib files, LaTeX control characters are automatically converted to unicode characters (for instance, to convert ``\'e`` into ``é``). Be sure to write ``\%`` when you intend to format a percent sign. You can set the encoding of the bibliography files, using the ``bibtex_encoding`` variable in your ``conf.py``. If no encoding is specified, ``utf-8-sig`` is assumed. For example: .. code-block:: python bibtex_encoding = 'latin' Bibliography Style ~~~~~~~~~~~~~~~~~~ You can change the bibliography style, using the ``bibtex_default_style`` variable in your ``conf.py``. If none is specified, the ``alpha`` style is used. Other supported styles are ``plain``, ``unsrt``, and ``unsrtalpha``. Note that these four styles are identical except for labelling and sorting. For example: .. code-block:: python bibtex_default_style = 'unsrt' You can also create your own style (see :ref:`bibtex-custom-formatting`). Referencing Style ~~~~~~~~~~~~~~~~~ .. versionadded:: 2.2.0 You can change the inline referencing style (i.e. the formatting of the citation references themselves) using the ``bibtex_reference_style`` variable in your ``conf.py``. Currently available built-in styles are: * ``label``: Use the labels generated by the bibliography style. Similar to natbib's ``numbers`` style and biblatex's ``numeric`` and ``alphabetic`` styles (depending on the labelling style of your bibliography style). This is the default style. * ``author_year``: Use the author and year. Similar to natbib's and biblatex's ``authoryear`` style. Note that this does not remove labels from bibliographies. This is because, in docutils, every citation must have a label. * ``super``: Use the labels generated by the bibliography style as superscripts. This works best with numeric bibliography styles such as ``plain``. Similar to natbib's ``super`` style and biblatex's ``\supercite`` command. The inline referencing style for footnote citations can be configured through the ``bibtex_foot_reference_style`` variable in your ``conf.py``. Currently available built-in styles are: * ``foot``: Use footnotes for parenthetical citations, and author with footnote for textual citations. This is the default style (and currently also the only built-in style). Python packages can make new styles available through the ``sphinxcontrib.bibtex.style.referencing`` `entry point `_ group. See sphinxcontrib-bibtex's own ``setup.py`` script for examples. Roles and Directives -------------------- .. rst:role:: cite:p .. versionadded:: 2.2.0 Create a parenthetical citation reference to a bibliographic entry. This will put the citation reference information (author and year, or label, depending on the style) between brackets. Similar to natbib's ``\citep`` command, or biblatex's ``\parencite`` command. For example: .. code-block:: rest We will make use of non-standard analysis :cite:p:`1987:nelson`. which would be equivalent to the following LaTeX code: .. code-block:: latex We will make use of non-standard analysis \citep{1987:nelson}. Multiple keys can be specified at once: .. code-block:: rest I love analysis :cite:p:`1987:nelson,2001:schechter`! .. rst:role:: cite:t .. versionadded:: 2.2.0 Create a textual citation. This will typically render the name of the first author followed by the year or by the label, depending on the citation reference style. Similar to natbib's ``\citet`` command, or biblatex's ``\textcite`` command. For example: .. code-block:: rest See :cite:t:`1987:nelson` for an introduction to non-standard analysis. which would be equivalent to the following LaTeX code: .. code-block:: latex See \citet{1987:nelson} for an introduction to non-standard analysis. Here too, multiple keys can be specified at once. .. rst:role:: cite:ps .. rst:role:: cite:ts .. rst:role:: cite:ct .. rst:role:: cite:cts .. versionadded:: 2.2.0 All these roles modify :rst:role:`cite:p` and :rst:role:`cite:t`. The ones starting with ``c`` will capitalize the first letter. The ones ending with ``s`` will give the full author list. .. rst:role:: cite This is an alias for the :rst:role:`cite:p` role, and will create a parenthetical citation reference. Provided for convenience and compatibility with older versions. .. rst:role:: cite:label .. rst:role:: cite:labelpar .. versionadded:: 2.2.0 Create a citation using just the label. Use the ``par`` version to include brackets. .. rst:role:: cite:year .. rst:role:: cite:yearpar .. versionadded:: 2.2.0 Create a citation using just the year. Use the ``par`` version to include brackets. .. rst:role:: cite:author .. rst:role:: cite:authors .. rst:role:: cite:authorpar .. rst:role:: cite:authorpars .. rst:role:: cite:cauthor .. rst:role:: cite:cauthors .. versionadded:: 2.2.0 Create a citation using just the author(s). Use the ``par`` version to include brackets, and the ``c`` version to capitalize the first letter. .. rst:role:: cite:empty .. versionadded:: 2.3.0 Register a citation key as being cited without generating a reference, similar to LaTeX's nocite command. .. rst:directive:: .. bibliography:: Create bibliography for all cited references. Citations in sphinx are resolved globally across all documents. Typically, you have a single bibliography directive across your entire project which collects all citations. Citation keys can also be explicitly listed under the directive; see :ref:`section-listing-citation-keys`. .. warning:: Sphinx will attempt to resolve references to the bibliography across all documents, so you must take care that no citation key is included more than once. The following options are recognized (all are optional). .. rst:directive:option:: all Include all references, instead of just the cited ones (equivalent to ``\nocite{*}`` in LaTeX). For example: .. code-block:: rest .. bibliography:: :all: .. rst:directive:option:: notcited Causes all references that were not cited to be included. Listed references remain included. .. rst:directive:option:: cited This is the default and need not be specified. .. rst:directive:option:: style Overrides the default bibliography style. For example: .. code-block:: rest .. bibliography:: :style: unsrt .. rst:directive:option:: list .. rst:directive:option:: enumtype .. rst:directive:option:: start See :ref:`section-lists`. .. rst:directive:option:: labelprefix See :ref:`section-label-prefixing`. .. rst:directive:option:: keyprefix See :ref:`section-key-prefixing`. .. rst:directive:option:: filter See :ref:`section-filtering`. Note that listed references are always included, regardless of any filtering. .. XXX not documenting disable-curly-bracket-strip for now; might remove it Finally, curly brackets are automatically removed when the bib file is parsed. Usually, this is what you want. If you desire to disable this behaviour, use the ``disable-curly-bracket-strip`` option: .. code-block:: rest .. bibliography:: :disable-curly-bracket-strip: .. rst:role:: footcite:p .. versionadded:: 2.3.0 Create a parenthetical footnote reference to a bibliographic entry. For example: .. code-block:: rest We will make use of non-standard analysis\ :footcite:p:`1987:nelson`. which would be equivalent to the following LaTeX code: .. code-block:: latex We will make use of non-standard analysis\footcite{1987:nelson}. Note the use of the `backslash escaped space `_ to suppress the space that would otherwise precede the footnote. As with all citation roles, multiple keys can be specified: .. code-block:: rest I love analysis\ :footcite:p:`1987:nelson,2001:schechter`! .. rst:role:: footcite:t .. versionadded:: 2.3.0 Create a textual footnote reference to a bibliographic entry. For example: .. code-block:: rest See :footcite:t:`1987:nelson` for an introduction to non-standard analysis. which would be equivalent to the following LaTeX code: .. code-block:: latex See Nelson\footcite{1987:nelson} for an introduction to non-standard analysis. Here too, multiple keys can be specified at once. .. rst:role:: footcite:ps .. rst:role:: footcite:ts .. rst:role:: footcite:ct .. rst:role:: footcite:cts .. versionadded:: 2.3.0 All these roles modify :rst:role:`footcite:p` and :rst:role:`footcite:t`. The ones starting with ``c`` will capitalize the first letter. The ones ending with ``s`` will give the full author list. .. rst:role:: footcite .. versionadded:: 2.0.0 This is an alias for the :rst:role:`footcite:p` role, and will create a parenthetical footnote citation reference. Provided for convenience and compatibility with older versions. .. rst:directive:: .. footbibliography:: .. versionadded:: 2.0.0 Create footnotes at this location for all references that are cited in the current document up to this point. Typically, you have a single footbibliography directive at the bottom of each document that has footcite citations. Standard numeric footnote labels are used, so the label style is ignored. Footnotes are inserted in the order in which they occur in the document, so the sorting style is also ignored. If specified multiple times in the same document, footnotes are only created for references that do not yet have a footnote earlier in the document. Advanced Features ----------------- Splitting Bibliographies Per Bib File ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. versionadded:: 2.0.0 If you want multiple bibliographies each of which only contains references from specific bib files, you can specify the relevant bib files as an optional argument to the directive. The next example shows how to split your citations between articles and books, assuming your articles are in ``articles.bib`` and your books are in ``books1.bib`` and ``books2.bib``. .. code-block:: rest .. rubric:: Articles .. bibliography:: articles.bib .. rubric:: Books .. bibliography:: books1.bib books2.bib The bib files must be specified as a path that is relative to the containing document. .. _section-lists: Bullet Lists and Enumerated Lists ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. versionadded:: 0.2.4 You can change the type of list used for rendering the bibliography. By default, a paragraph of standard citations is generated. However, instead, you can also generate a bullet list, or an enumerated list. .. code-block:: rest .. bibliography:: :list: bullet :all: .. bibliography:: :list: enumerated :all: Note that citations to these types of bibliography lists will not be resolved. For enumerated lists, you can also specify the type (default is ``arabic``), and the start of the sequence (default is ``1``). .. code-block:: rest .. bibliography:: :list: enumerated :enumtype: upperroman :start: 3 :all: The enumtype can be any of ``arabic`` (1, 2, 3, ...), ``loweralpha`` (a, b, c, ...), ``upperalpha`` (A, B, C, ...), ``lowerroman`` (i, ii, iii, ...), or ``upperroman`` (I, II, III, ...). The start can be any positive integer (1, 2, 3, ...) or ``continue`` if you wish the enumeration to continue from the last :rst:dir:`bibliography` directive. This is helpful if you split up your bibliography but still want to enumerate the entries continuously. .. _section-listing-citation-keys: Listing Citation Keys ~~~~~~~~~~~~~~~~~~~~~ .. versionadded:: 2.3.0 If you have many citations to include that are not referenced anywhere, then instead of using :rst:role:`cite:empty` it can be more convenient to simply list the citation keys directly under the bibliography directive where you want them to appear. Such references can be listed by having one bibtex key per line under the directive. The keys should not have a key prefix if you are using that option (see :ref:`section-key-prefixing`). For example: .. code-block:: rest .. bibliography:: nelson1987 boole1854 This would cause the bibliography to generate citations for all cited references, in addition to citations with bibtex keys ``nelson1987`` and ``boole1854``. The listed keys are always included regardless of filtering. So, if you only want the listed keys to be included, you can use the ``:filter: False`` option: .. code-block:: rest .. bibliography:: :filter: False nelson1987 boole1854 See :ref:`section-filtering` for more information on filtering. .. _section-label-prefixing: Label Prefixing ~~~~~~~~~~~~~~~ .. versionadded:: 0.2.5 If you have multiple bibliographies, and experience duplicate labels, use the ``labelprefix`` option. .. code-block:: rest .. rubric:: References .. bibliography:: :cited: :labelprefix: A .. rubric:: Further reading .. bibliography:: :notcited: :labelprefix: B .. _section-key-prefixing: Key Prefixing ~~~~~~~~~~~~~ .. versionadded:: 0.3.3 If you have multiple bibliographies, and you would like entries to be repeated in different documents, then use the ``keyprefix`` option. For example, suppose you have two documents, and you would like to cite ``boole1854`` in both of these documents, with the bibliography entries showing in both of the documents. In one document you could have: .. code-block:: rest See :cite:`a-boole1854` .. bibliography:: :labelprefix: A :keyprefix: a- whilst in the other document you could have: .. code-block:: rest See :cite:`b-boole1854` .. bibliography:: :labelprefix: B :keyprefix: b- The bibliographies will then both generate an entry for ``boole1854``, with links and backlinks as expected. If you list citation keys, you should include those *without* key prefix. For example: .. code-block:: rest .. bibliography:: :labelprefix: B :keyprefix: b- nelson1987 .. seealso:: :ref:`section-local-bibliographies` .. _section-filtering: Filtering ~~~~~~~~~ .. versionadded:: 0.2.7 Whilst the ``cited``, ``all``, and ``notcited`` options along with :ref:`section-listing-citation-keys` will cover many use cases, sometimes more advanced selection of bibliographic entries is desired. For this purpose, you can use the ``filter`` option: .. code-block:: rest .. bibliography:: :list: bullet :filter: author % "Einstein" The string specified in the filter option must be a valid Python expression. .. note:: The expression is parsed using :func:`ast.parse` and then evaluated using an :class:`ast.NodeVisitor`, so it should be reasonably safe against malicious code. The filter expression supports: * The boolean operators ``and``, ``or``. * The unary operator ``not``. * The comparison operators ``==``, ``<=``, ``<``, ``>=``, and ``>``. * Regular expression matching using the ``%`` operator, where the left hand side is the string to be matched, and the right hand side is the regular expression. Matching is case insensitive. For example: .. code-block:: rest .. bibliography:: :list: bullet :filter: title % "relativity" would include all entries that have the word "relativity" in the title. .. note:: The implementation uses :func:`re.search`. * Single and double quoted strings, such as ``'hello'`` or ``"world"``. * Set literals, such has ``{"hello", "world"}``, as well as the set operators ``&``, ``|``, ``in``, and ``not in``. .. versionadded:: 0.3.0 * Various identifiers, such as: - ``type`` is the entry type, as a lower case string (i.e. ``"inproceedings"``). - ``key`` is the entry key, as a lower case string (this is because keys are considered case insensitive). - ``cited`` evaluates to ``True`` if the entry was cited in the document, and to ``False`` otherwise. - ``docname`` evaluates to the name of the current document. .. versionadded:: 0.3.0 - ``docnames`` evaluates to a set of names from which the entry is cited. .. versionadded:: 0.3.0 - ``True`` and ``False``. - ``author`` is the entry string of authors in standard format (last, first), separated by "and". - ``editor`` is similar to ``author`` but for editors. - Any other (lower case) identifier evaluates to a string containing the value of the correspondingly named field, such as ``title``, ``publisher``, ``year``, and so on. If the item is missing in the entry then it evaluates to the empty string. Here is an example of how one would typically write an expression to filter on an optional field: .. code-block:: rest .. bibliography:: :list: bullet :filter: cited and year and (year <= "2003") which would include all cited entries that have a year that is less or equal than 2003; any entries that do not specify a year would be omitted. .. _section-local-bibliographies: Local Bibliographies ~~~~~~~~~~~~~~~~~~~~ The easiest way to have a local bibliography per document is to use :rst:role:`footcite` along with :rst:dir:`footbibliography`. If you prefer to have regular citations instead of footnotes, both the ``keyprefix`` and ``filter`` options can be used to achieve local bibliographies with :rst:role:`cite` and :rst:dir:`bibliography`. The ``filter`` system for local bibliographies can only be used if no citation key is used in more than one document. This is not always satisfied. If you need to cite the same reference in multiple documents with references to multiple local bibliographies, use the ``keyprefix`` system; see :ref:`section-key-prefixing`. To create a bibliography that includes only citations that were cited in the current document, use the following filter: .. code-block:: rest .. bibliography:: :filter: docname in docnames More generally, you can create bibliographies for citations that were cited from specific documents only: .. code-block:: rest .. bibliography:: :filter: {"doc1", "doc2"} & docnames This bibliography will include all citations that were cited from :file:`doc1.rst` or :file:`doc2.rst`. Another hypothetical example: .. code-block:: rest .. bibliography:: :filter: cited and ({"doc1", "doc2"} >= docnames) This bibliography will include all citations that were cited in :file:`doc1.rst` or :file:`doc2.rst`, but nowhere else. .. _bibtex-custom-formatting: Custom Formatting, Sorting, and Labelling ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :mod:`pybtex` provides a very powerful way to create and register new styles, using setuptools entry points, as documented here: https://docs.pybtex.org/api/plugins.html Simply add the following code to your ``conf.py``: .. code-block:: python import pybtex.plugin from pybtex.style.formatting.unsrt import Style as UnsrtStyle from pybtex.style.template import toplevel # ... and anything else needed class MyStyle(UnsrtStyle): def format_XXX(self, e): template = toplevel [ # etc. ] return template.format_data(e) pybtex.plugin.register_plugin('pybtex.style.formatting', 'mystyle', MyStyle) Now ``mystyle`` will be available to you as a formatting style: .. code-block:: python bibtex_default_style = 'mystyle' An minimal example is available here: https://github.com/mcmtroffaes/sphinxcontrib-bibtex/tree/develop/test/roots/test-bibliography_style_nowebref The formatting code uses a very intuitive template engine. The source code for ``unsrt`` provides many great examples: https://bitbucket.org/pybtex-devs/pybtex/src/master/pybtex/style/formatting/unsrt.py?at=master&fileviewer=file-view-default The above example only demonstrates a custom formatting style plugin. It is also possible to register custom author/editor naming plugins (using the ``pybtex.style.names`` group), labelling plugins (using the ``pybtex.style.labels`` group), and sorting plugins (using the ``pybtex.style.sorting`` group). A few minimal examples demonstrating how to create custom label styles are available here: * https://github.com/mcmtroffaes/sphinxcontrib-bibtex/tree/develop/test/roots/test-bibliography_style_label_1 * https://github.com/mcmtroffaes/sphinxcontrib-bibtex/tree/develop/test/roots/test-bibliography_style_label_2 Custom Inline Citation References ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. versionadded:: 2.2.0 You can create and register your own referencing styles. For instance, say we wish to use the author-year style with round brackets instead of the default square brackets. Simply add the following code to your ``conf.py``: .. code-block:: python import dataclasses import sphinxcontrib.bibtex.plugin from sphinxcontrib.bibtex.style.referencing import BracketStyle from sphinxcontrib.bibtex.style.referencing.author_year \ import AuthorYearReferenceStyle my_bracket_style = BracketStyle( left='(', right=')', ) @dataclasses.dataclass class MyReferenceStyle(AuthorYearReferenceStyle): bracket_parenthetical: BracketStyle = my_bracket_style bracket_textual: BracketStyle = my_bracket_style bracket_author: BracketStyle = my_bracket_style bracket_label: BracketStyle = my_bracket_style bracket_year: BracketStyle = my_bracket_style sphinxcontrib.bibtex.plugin.register_plugin( 'sphinxcontrib.bibtex.style.referencing', 'author_year_round', MyReferenceStyle) .. warning:: You must decorate your style as a dataclass, and **include a type annotation with every field**, to ensure these values are correctly passed to the constructor when sphinxcontrib-bibtex instantiates your style. Now ``author_year_round`` will be available to you as a formatting style: .. code-block:: python bibtex_reference_style = 'author_year_round' An minimal example is available here: https://github.com/mcmtroffaes/sphinxcontrib-bibtex/tree/develop/test/roots/test-citation_style_round_brackets Custom Html Anchors ~~~~~~~~~~~~~~~~~~~ .. versionadded:: 2.4.0 For every citation and every bibliography, an identifier of the form ``idxxx`` (where ``xxx`` is some number) is generated. These identifiers can be used as html anchors. They are automatically generated by docutils and are thereby guaranteed not to clash. However, sometimes it is useful to refer to bibliographic entries from other external documents that have not been generated with Sphinx. Since the generated identifiers can easily break when updating documents, they can be customized through string templates should you need this. If you do so, it is your responsibility to ensure that no anchors will clash, by setting up the appropriate identifier templates in your ``conf.py`` file, for instance as follows: .. code-block:: python bibtex_cite_id = "cite-{bibliography_count}-{key}" bibtex_footcite_id = "footcite-{key}" bibtex_bibliography_id = "bibliography-{bibliography_count}" bibtex_footbibliography_id = "footbibliography-{footbibliography_count}" If you have at most one :rst:dir:`bibliography` directive per document, then you can also use: .. code-block:: python bibtex_cite_id = "cite-{key}" The ``bibliography_count`` template variable counts :rst:dir:`bibliography` directives in the current document, thus giving a unique number for each :rst:dir:`bibliography` directive within a document. The ``footbibliography_count`` template variable works similarly but for :rst:dir:`footbibliography` directives. The ``key`` template variable corresponds to the bibtex citation key, including the key prefix if specified. After formatting the template, the resulting string is filtered through docutils's ``make_id`` function, which will remove and/or translate any illegal characters. In particular, colons and underscores will be translated into dashes. .. warning:: If you have more than one :rst:dir:`bibliography` directive in any document, then you *must* include ``bibliography_count`` as part of your ``bibtex_cite_id`` template to avoid issues with duplicate identifiers, *even if there are no duplicate citations*. This is because the extension must generate an identifier for every key for each :rst:dir:`bibliography` directive prior to knowing whether or not the citation needs to be included. Custom Bibliography Header ~~~~~~~~~~~~~~~~~~~~~~~~~~ .. versionadded:: 2.0.0 By default, the :rst:dir:`bibliography` and :rst:dir:`footbibliography` directives simply insert a paragraph. The ``bibtex_bibliography_header`` and ``bibtex_footbibliography_header`` configuration variables can be set to add a header to this. For example, in your ``conf.py`` you could have: .. code-block:: python bibtex_bibliography_header = ".. rubric:: References" bibtex_footbibliography_header = bibtex_bibliography_header This adds a rubric title to every bibliography. Suppressing Warnings ~~~~~~~~~~~~~~~~~~~~ .. versionadded:: 2.3.1 To suppress *all* warnings from ``sphinxcontrib-bibtex`` (which is probably a bad idea!), add this to your ``conf.py``: .. code-block:: python suppress_warnings = ["bibtex"] To suppress only a subset of warnings, such as duplicate label warnings, you can use: .. code-block:: python suppress_warnings = ["bibtex.duplicate_label"] The complete list of warning subtypes that can be suppressed is:: bibtex.bibfile_data_error bibtex.bibfile_error bibtex.duplicate_citation bibtex.duplicate_id bibtex.duplicate_label bibtex.filter_overrides bibtex.filter_syntax_error bibtex.key_not_found bibtex.list_type_error bibtex.missing_field Known Issues and Workarounds ---------------------------- Encoding: Percent Signs ~~~~~~~~~~~~~~~~~~~~~~~ Be sure to write ``\%`` for percent signs at all times in your bib files (unless your file contains a genuine comment), otherwise the pybtex parser will ignore the remainder of the line. Duplicate Labels When Using ``:style: plain`` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ With ``:style: plain``, labels are numeric, restarting at ``[1]`` for each :rst:dir:`bibliography` directive. Consequently, when inserting multiple :rst:dir:`bibliography` directives with ``:style: plain``, you are bound to get duplicate labels for entries. There are a few ways to work around this problem: * Use a single bibliography directive for all your references. * Use the ``labelprefix`` option, as documented above. * Use a style that has non-numeric labelling, such as ``:style: alpha``. LaTeX Backend Fails with Citations In Figure Captions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Sphinx generates ``\phantomsection`` commands for references, however LaTeX does not support these in figure captions. You can work around this problem by adding the following code to your ``conf.py``: .. code-block:: python latex_elements = { 'preamble': r''' % make phantomsection empty inside figures \usepackage{etoolbox} \AtBeginEnvironment{figure}{\renewcommand{\phantomsection}{}} ''' } Mismatch Between Output of HTML/Text and LaTeX Backends ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Sphinx's LaTeX writer currently collects all citations together, and puts them on a separate page, with a separate title, whereas the html and text writers puts citations at the location where they are defined. This issue will occur also if you use regular citations in Sphinx: it has nothing to do with sphinxcontrib-bibtex per se. To get a closer match between the two outputs, you can tell Sphinx to generate a rubric title only for html or text outputs: .. code-block:: rest .. only:: html or text .. rubric:: References .. bibliography:: This code could be placed in a :file:`references.rst` file that you include at the end of your toctree. Alternatively, to remove the bibliography section title from the LaTeX output, you can add the following to your LaTeX preamble: .. code-block:: latex \usepackage{etoolbox} \patchcmd{\thebibliography}{\section*{\refname}}{}{}{} Import errors after using setup.py install ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Because sphinxcontrib-bibtex uses the standard sphinxcontrib namespace, installing the package using .. code-block:: python setup.py install may result in a broken installation. This appears to be an issue with setuptools. As pip does not have this problem, it is recommended to install the package with pip: .. code-block:: pip install . Import errors when running pytest ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The test suit relies on the entry points being installed, whence, sphinxcontrib-bibtex cannot be tested without first installing the package. To run the tests, please do as follows (ideally, in a virtual environment): .. code-block:: pip install . -e cd test/ pytest sphinxcontrib-bibtex-2.4.1/mypy.ini000066400000000000000000000003421411661013000173520ustar00rootroot00000000000000[mypy] files = src/sphinxcontrib/**/*.py,test/*.py,setup.py [mypy-pybtex.*] ignore_missing_imports = True [mypy-setuptools] ignore_missing_imports = True [mypy-docutils.parsers.rst.directives] ignore_missing_imports = True sphinxcontrib-bibtex-2.4.1/pytest.ini000066400000000000000000000000641411661013000177050ustar00rootroot00000000000000[pytest] norecursedirs = doc src testpaths = test sphinxcontrib-bibtex-2.4.1/release_checklist.txt000066400000000000000000000026421411661013000220720ustar00rootroot00000000000000* git checkout -b release/x.x.x * sphinxcontrib/bibtex/__init__.py: set final version * CHANGELOG.rst: - set release date - all important changes are documented * doc: - all new features are properly documented - all new features have versionadded - all workarounds are properly documented - fixed workarounds are removed - git clean -xfd - python setup.py install --user && cd doc && make html && make linkcheck * make pull request on github - travis build passes - coverage at 100% - on github, merge release/x.x.x into develop and delete the release branch - git remote update --prune && git checkout develop && git merge --ff-only origin/develop * create and register source zip - git clean -xfd - python3 setup.py sdist bdist_wheel - twine upload dist/* * test upload - pip uninstall sphinxcontrib-bibtex - pip install --user -U sphinxcontrib-bibtex - cd sphinxcontrib-bibtex/test - nosetests * push release - git checkout master && git merge --ff-only develop - git tag -a -m "Tagging version `cat VERSION`" `cat VERSION` - git push origin master - git push --tags - git checkout develop - git branch -d release/x.x.x * activate new version on readthedocs.org * prep for next cycle - git checkout develop - sphinxcontrib/bibtex/__init__.py: bump to x.x.xa0 - CHANGELOG.rst: bump to x.x.x (in development) - git commit -a -m "Version bump. [skip ci]" - git push origin develop sphinxcontrib-bibtex-2.4.1/requirements.txt000066400000000000000000000001421411661013000211350ustar00rootroot00000000000000Sphinx>=2.1 docutils>=0.8 pybtex>=0.20 pybtex-docutils>=1.0.0 dataclasses; python_version < '3.7' sphinxcontrib-bibtex-2.4.1/setup.py000066400000000000000000000052771411661013000174010ustar00rootroot00000000000000import io import re from setuptools import setup, find_packages from typing import Optional def readfile(filename: str) -> str: with io.open(filename, encoding="utf-8") as stream: return stream.read() readme = readfile("README.rst").split("\n")[5:] # skip title and badges requires = readfile("requirements.txt").split("\n") version_match = re.search("'version': '(.+)'", readfile("src/sphinxcontrib/bibtex/__init__.py")) assert version_match is not None, "version not found" version = version_match.group(1) # make entry point specifications def plugin(plugin_name: str, mod_name: Optional[str] = None) -> str: if mod_name is None: mod_name = plugin_name path = "sphinxcontrib.bibtex.style.referencing" class_name = ''.join(part.capitalize() for part in plugin_name.split("_")) return f"{plugin_name} = {path}.{mod_name}:{class_name}ReferenceStyle" setup( name='sphinxcontrib-bibtex', version=version, url='https://github.com/mcmtroffaes/sphinxcontrib-bibtex', download_url='https://pypi.python.org/pypi/sphinxcontrib-bibtex', license='BSD', author='Matthias C. M. Troffaes', author_email='matthias.troffaes@gmail.com', description=readme[0], long_description="\n".join(readme[2:]), zip_safe=False, classifiers=[ 'Development Status :: 5 - Production/Stable', 'Environment :: Console', 'Environment :: Web Environment', 'Intended Audience :: Developers', 'License :: OSI Approved :: BSD License', 'Operating System :: OS Independent', 'Programming Language :: Python', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', 'Programming Language :: Python :: 3.8', 'Programming Language :: Python :: 3.9', 'Programming Language :: Python :: Implementation :: CPython', 'Programming Language :: Python :: Implementation :: PyPy', 'Topic :: Documentation', 'Topic :: Utilities', ], platforms='any', packages=find_packages('src'), package_dir={'': 'src'}, package_data={'sphinxcontrib.bibtex': ['py.typed']}, include_package_data=True, python_requires='>=3.6', install_requires=requires, tests_require=['pytest', 'pytest-cov'], namespace_packages=['sphinxcontrib'], entry_points={ 'pybtex.style.names': [ 'last = sphinxcontrib.bibtex.style.names.last:LastNameStyle', ], 'sphinxcontrib.bibtex.style.referencing': [ plugin('author_year'), plugin('label'), plugin('super', 'super_'), plugin('foot'), ], } ) sphinxcontrib-bibtex-2.4.1/src/000077500000000000000000000000001411661013000164435ustar00rootroot00000000000000sphinxcontrib-bibtex-2.4.1/src/sphinxcontrib/000077500000000000000000000000001411661013000213355ustar00rootroot00000000000000sphinxcontrib-bibtex-2.4.1/src/sphinxcontrib/__init__.py000066400000000000000000000005251411661013000234500ustar00rootroot00000000000000""" sphinxcontrib ~~~~~~~~~~~~~ This package is a namespace package that contains all extensions distributed in the ``sphinx-contrib`` distribution. :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ __import__('pkg_resources').declare_namespace(__name__) sphinxcontrib-bibtex-2.4.1/src/sphinxcontrib/bibtex/000077500000000000000000000000001411661013000226125ustar00rootroot00000000000000sphinxcontrib-bibtex-2.4.1/src/sphinxcontrib/bibtex/__init__.py000066400000000000000000000040121411661013000247200ustar00rootroot00000000000000""" .. autofunction:: setup """ from typing import Any, Dict from sphinx.application import Sphinx from .domain import BibtexDomain from .foot_domain import BibtexFootDomain from .nodes import bibliography, raw_latex, visit_raw_latex, depart_raw_latex from .roles import CiteRole from .directives import BibliographyDirective from .transforms import BibliographyTransform from .foot_roles import FootCiteRole from .foot_directives import FootBibliographyDirective def setup(app: Sphinx) -> Dict[str, Any]: """Set up the bibtex extension: * register config values * register directives * register nodes * register roles * register transforms * connect events to functions """ app.add_config_value("bibtex_default_style", "alpha", "html") app.add_config_value("bibtex_bibfiles", None, "html") app.add_config_value("bibtex_encoding", "utf-8-sig", "html") app.add_config_value("bibtex_bibliography_header", "", "html") app.add_config_value("bibtex_footbibliography_header", "", "html") app.add_config_value("bibtex_reference_style", "label", "env") app.add_config_value("bibtex_foot_reference_style", "foot", "env") app.add_config_value("bibtex_cite_id", "", "html") app.add_config_value("bibtex_footcite_id", "", "html") app.add_config_value("bibtex_bibliography_id", "", "html") app.add_config_value("bibtex_footbibliography_id", "", "html") app.add_domain(BibtexDomain) app.add_directive("bibliography", BibliographyDirective) app.add_role("cite", CiteRole()) app.add_node(bibliography, override=True) app.add_node(raw_latex, latex=(visit_raw_latex, depart_raw_latex), override=True) app.add_post_transform(BibliographyTransform) app.add_domain(BibtexFootDomain) app.add_directive("footbibliography", FootBibliographyDirective) app.add_role("footcite", FootCiteRole()) return { 'version': '2.4.1', 'env_version': 9, 'parallel_read_safe': True, 'parallel_write_safe': True, } sphinxcontrib-bibtex-2.4.1/src/sphinxcontrib/bibtex/bibfile.py000066400000000000000000000103701411661013000245610ustar00rootroot00000000000000""" Classes and methods to work with bib files. .. autoclass:: BibFile :members: .. autoclass:: BibData :members: .. autofunction:: normpath_filename .. autofunction:: parse_bibdata .. autofunction:: is_bibdata_outdated .. autofunction:: process_bibdata """ import math import os.path from typing import TYPE_CHECKING, Dict, NamedTuple, List, Set from docutils.nodes import make_id from pybtex.database.input.bibtex import Parser from pybtex.database import BibliographyData, BibliographyDataError from sphinx.util.logging import getLogger if TYPE_CHECKING: from sphinx.environment import BuildEnvironment logger = getLogger(__name__) class BibFile(NamedTuple): """Contains information about a parsed bib file.""" mtime: float #: Modification time of file when last parsed. keys: Dict[str, None] #: Set of keys for this bib file as ordered dict. class BibData(NamedTuple): """Contains information about a collection of bib files.""" encoding: str #: Encoding of all bib files. bibfiles: Dict[str, BibFile] #: Maps bib filename to information about it. data: BibliographyData #: Data parsed from all bib files. def normpath_filename(env: "BuildEnvironment", filename: str) -> str: """Return normalised path to *filename* for the given environment *env*.""" return os.path.normpath(env.relfn2path(filename.strip())[1]) def get_mtime(bibfilename: str) -> float: try: return os.path.getmtime(bibfilename) except OSError: return -math.inf def parse_bibdata(bibfilenames: List[str], encoding: str) -> BibData: """Parse *bibfilenames* with given *encoding*, and return parsed data.""" parser = Parser(encoding) bibfiles: Dict[str, BibFile] = {} keys: Dict[str, None] = {} for filename in bibfilenames: logger.info("parsing bibtex file {0}... ".format(filename), nonl=True) if not os.path.isfile(filename): logger.warning( "could not open bibtex file {0}.".format(filename), type="bibtex", subtype="bibfile_error") new_keys: Dict[str, None] = {} else: try: parser.parse_file(filename) except BibliographyDataError as exc: logger.warning( "bibliography data error in {0}: {1}".format( filename, exc), type="bibtex", subtype="bibfile_data_error") keys, old_keys = dict.fromkeys(parser.data.entries.keys()), keys assert all(key in keys for key in old_keys) new_keys = dict.fromkeys( key for key in keys if key not in old_keys) logger.info("parsed {0} entries".format(len(new_keys))) bibfiles[filename] = BibFile(mtime=get_mtime(filename), keys=new_keys) return BibData(encoding=encoding, bibfiles=bibfiles, data=parser.data) def is_bibdata_outdated(bibdata: BibData, bibfilenames: List[str], encoding: str) -> bool: return ( bibdata.encoding != encoding or list(bibdata.bibfiles) != bibfilenames or any(bibfile.mtime != get_mtime(filename) for filename, bibfile in bibdata.bibfiles.items())) def process_bibdata(bibdata: BibData, bibfilenames: List[str], encoding: str) -> BibData: """Parse *bibfilenames* and store parsed data in *bibdata*.""" logger.info("checking bibtex cache... ", nonl=True) if is_bibdata_outdated(bibdata, bibfilenames, encoding): logger.info("out of date") return parse_bibdata(bibfilenames, encoding) else: logger.info("up to date") return bibdata # function does not really fit in any module, but used by both # cite and footcite domains, so for now it's residing here def _make_ids(docname: str, lineno: int, ids: Set[str], raw_id: str ) -> List[str]: if raw_id: id_ = make_id(raw_id) if id_ in ids: logger.warning(f"duplicate citation id {id_}", location=(docname, lineno), type="bibtex", subtype="duplicate_id") return [] else: ids.add(id_) return [id_] else: return [] sphinxcontrib-bibtex-2.4.1/src/sphinxcontrib/bibtex/directives.py000066400000000000000000000214361411661013000253330ustar00rootroot00000000000000""" .. autoclass:: BibliographyKey :members: .. autoclass:: BibliographyValue :members: .. autoclass:: BibliographyDirective .. automethod:: run """ from typing import TYPE_CHECKING, cast, NamedTuple, List, Dict from docutils.parsers.rst import Directive import docutils.parsers.rst.directives as directives import ast # parse(), used for filter import docutils.nodes import sphinx.util from .bibfile import normpath_filename, _make_ids from .nodes import bibliography as bibliography_node if TYPE_CHECKING: from sphinx.environment import BuildEnvironment from .domain import BibtexDomain logger = sphinx.util.logging.getLogger(__name__) class BibliographyKey(NamedTuple): """Unique key for each bibliography directive.""" docname: str #: Name of the document where the bibliography resides. id_: str #: The id of the bibliography node in the document. class BibliographyValue(NamedTuple): """Contains information about a bibliography directive.""" line: int #: Line number of the directive in the document. bibfiles: List[str] #: List of bib files for this directive. style: str #: The pybtex style. list_: str #: The list type. enumtype: str #: The sequence type (for enumerated lists). start: int #: The start of the sequence (for enumerated lists). labelprefix: str #: String prefix for pybtex generated labels. keyprefix: str #: String prefix for citation keys. filter_: ast.AST #: Parsed filter expression. citation_nodes: Dict[str, docutils.nodes.Element] #: key -> citation node keys: List[str] #: Keys listed as content of the directive. class BibliographyDirective(Directive): """Class for processing the :rst:dir:`bibliography` directive. Produces a :class:`~sphinxcontrib.bibtex.nodes.bibliography` node, along with (empty) citation nodes that will be formatted later in the *env-updated* stage, and inserted into the document in a post-transform. We cannot insert the citation nodes here because we do not yet know which keys have been cited. .. seealso:: Further processing of the resulting :class:`~sphinxcontrib.bibtex.nodes.bibliography` node is done by :class:`~sphinxcontrib.bibtex.transforms.BibliographyTransform`. """ required_arguments = 0 optional_arguments = 1 final_argument_whitespace = True has_content = True option_spec = { 'cited': directives.flag, 'notcited': directives.flag, 'all': directives.flag, 'filter': directives.unchanged, 'style': directives.unchanged, 'list': directives.unchanged, 'enumtype': directives.unchanged, 'start': ( lambda value: directives.positive_int(value) if value != 'continue' else -1), 'labelprefix': directives.unchanged, 'keyprefix': directives.unchanged, } def _get_filter(self): """Get parsed filter from options.""" env = cast("BuildEnvironment", self.state.document.settings.env) if "filter" in self.options: if "all" in self.options: logger.warning(":filter: overrides :all:", location=(env.docname, self.lineno), type="bibtex", subtype="filter_overrides") if "notcited" in self.options: logger.warning(":filter: overrides :notcited:", location=(env.docname, self.lineno), type="bibtex", subtype="filter_overrides") if "cited" in self.options: logger.warning(":filter: overrides :cited:", location=(env.docname, self.lineno), type="bibtex", subtype="filter_overrides") try: return ast.parse(self.options["filter"]) except SyntaxError: logger.warning( "syntax error in :filter: expression" + " (" + self.options["filter"] + "); " "the option will be ignored", location=(env.docname, self.lineno), type="bibtex", subtype="filter_syntax_error") return ast.parse("cited") elif "all" in self.options: return ast.parse("True") elif "notcited" in self.options: return ast.parse("not cited") else: # the default filter: include only cited entries return ast.parse("cited") def run(self): """Process .bib files, set file dependencies, and create a node that is to be transformed to the entries of the bibliography. """ env = cast("BuildEnvironment", self.state.document.settings.env) domain = cast("BibtexDomain", env.get_domain('cite')) filter_ = self._get_filter() if self.arguments: bibfiles = [] for bibfile in self.arguments[0].split(): normbibfile = normpath_filename(env, bibfile) if normbibfile not in domain.bibdata.bibfiles: logger.warning( "{0} not found or not configured" " in bibtex_bibfiles".format(bibfile), location=(env.docname, self.lineno), type="bibtex", subtype="bibfile_error") else: bibfiles.append(normbibfile) else: bibfiles = list(domain.bibdata.bibfiles.keys()) for bibfile in bibfiles: env.note_dependency(bibfile) # generate nodes and ids keyprefix: str = self.options.get("keyprefix", "") list_: str = self.options.get("list", "citation") if list_ not in {"bullet", "enumerated", "citation"}: logger.warning( "unknown bibliography list type '{0}'.".format(list_), location=(env.docname, self.lineno), type="bibtex", subtype="list_type_error") list_ = "citation" if list_ in {"bullet", "enumerated"}: citation_node_class = docutils.nodes.list_item else: citation_node_class = docutils.nodes.citation bibliography_count = env.temp_data["bibtex_bibliography_count"] = \ env.temp_data.get("bibtex_bibliography_count", 0) + 1 ids = set(self.state.document.ids.keys()) node = bibliography_node( '', docname=env.docname, ids=_make_ids( docname=env.docname, lineno=self.lineno, ids=ids, raw_id=env.app.config.bibtex_bibliography_id.format( bibliography_count=bibliography_count))) self.state.document.note_explicit_target(node, node) # we only know which citations to included at resolve stage # but we need to know their ids before resolve stage # so for now we generate a node, and thus, an id, for every entry citation_nodes: Dict[str, docutils.nodes.Element] = { keyprefix + entry.key: citation_node_class(ids=_make_ids( docname=env.docname, lineno=self.lineno, ids=ids, raw_id=env.app.config.bibtex_cite_id.format( bibliography_count=bibliography_count, key=keyprefix + entry.key))) for entry in domain.get_entries(bibfiles)} for citation_node in citation_nodes.values(): self.state.document.note_explicit_target( citation_node, citation_node) # check and get keys keys = [] for key in self.content: if keyprefix + key not in citation_nodes: logger.warning('could not find bibtex key "%s"' % key, location=(env.docname, self.lineno), type="bibtex", subtype="key_not_found") else: keys.append(key) # create bibliography object bibliography = BibliographyValue( line=self.lineno, list_=list_, enumtype=self.options.get("enumtype", "arabic"), start=self.options.get("start", 1), style=self.options.get( "style", env.app.config.bibtex_default_style), filter_=filter_, labelprefix=self.options.get("labelprefix", ""), keyprefix=keyprefix, bibfiles=bibfiles, citation_nodes=citation_nodes, keys=keys, ) bib_key = BibliographyKey(docname=env.docname, id_=node['ids'][0]) assert bib_key not in domain.bibliographies domain.bibliographies[bib_key] = bibliography return [node] sphinxcontrib-bibtex-2.4.1/src/sphinxcontrib/bibtex/domain.py000066400000000000000000000531271411661013000244430ustar00rootroot00000000000000""" Classes and methods to maintain any bibtex information that is stored outside the doctree. .. autoclass:: Citation :members: .. autoclass:: SphinxReferenceInfo :members: .. autoclass:: SphinxReferenceText :members: .. autoclass:: BibtexDomain :members: """ import ast from typing import TYPE_CHECKING from typing import List, Dict, NamedTuple, cast, Iterable, Tuple, Set import docutils.frontend import docutils.nodes import docutils.parsers.rst import docutils.utils import pybtex_docutils import pybtex.plugin from pybtex.richtext import Tag from pybtex.style.template import FieldIsMissing from pybtex.style import FormattedEntry import sphinxcontrib.bibtex.plugin import sphinx.util import re from sphinx.domains import Domain, ObjType from sphinx.errors import ExtensionError from sphinx.locale import _ from sphinx.util.nodes import make_refnode from .roles import CiteRole from .bibfile import normpath_filename, process_bibdata, BibData from .nodes import raw_latex from .style.referencing import ( BaseReferenceText, BaseReferenceStyle, format_references ) if TYPE_CHECKING: from pybtex.backends import BaseBackend from pybtex.database import Entry from pybtex.style.formatting import BaseStyle from sphinx.addnodes import pending_xref from sphinx.application import Sphinx from sphinx.builders import Builder from sphinx.environment import BuildEnvironment from .directives import BibliographyKey, BibliographyValue from .roles import CitationRef logger = sphinx.util.logging.getLogger(__name__) def _raise_invalid_node(node): """Helper method to raise an exception when an invalid node is visited. """ raise ValueError("invalid node %s in filter expression" % node) class _FilterVisitor(ast.NodeVisitor): """Visit the abstract syntax tree of a parsed filter expression.""" entry = None """The bibliographic entry to which the filter must be applied.""" cited_docnames = False """The documents where the entry is cited (empty if not cited).""" def __init__(self, entry, docname, cited_docnames): self.entry = entry self.docname = docname self.cited_docnames = cited_docnames def visit_Module(self, node): if len(node.body) != 1: raise ValueError( "filter expression cannot contain multiple expressions") return self.visit(node.body[0]) def visit_Expr(self, node): return self.visit(node.value) def visit_BoolOp(self, node): outcomes = (self.visit(value) for value in node.values) if isinstance(node.op, ast.And): return all(outcomes) elif isinstance(node.op, ast.Or): return any(outcomes) else: # pragma: no cover # there are no other boolean operators # so this code should never execute assert False, "unexpected boolean operator %s" % node.op def visit_UnaryOp(self, node): if isinstance(node.op, ast.Not): return not self.visit(node.operand) else: _raise_invalid_node(node) def visit_BinOp(self, node): left = self.visit(node.left) op = node.op right = self.visit(node.right) if isinstance(op, ast.Mod): # modulo operator is used for regular expression matching if not isinstance(left, str): raise ValueError( "expected a string on left side of %s" % node.op) if not isinstance(right, str): raise ValueError( "expected a string on right side of %s" % node.op) return re.search(right, left, re.IGNORECASE) elif isinstance(op, ast.BitOr): return left | right elif isinstance(op, ast.BitAnd): return left & right else: _raise_invalid_node(node) def visit_Compare(self, node): # keep it simple: binary comparators only if len(node.ops) != 1: raise ValueError("syntax for multiple comparators not supported") left = self.visit(node.left) op = node.ops[0] right = self.visit(node.comparators[0]) if isinstance(op, ast.Eq): return left == right elif isinstance(op, ast.NotEq): return left != right elif isinstance(op, ast.Lt): return left < right elif isinstance(op, ast.LtE): return left <= right elif isinstance(op, ast.Gt): return left > right elif isinstance(op, ast.GtE): return left >= right elif isinstance(op, ast.In): return left in right elif isinstance(op, ast.NotIn): return left not in right else: # not used currently: ast.Is | ast.IsNot _raise_invalid_node(op) def visit_Name(self, node): """Calculate the value of the given identifier.""" id_ = node.id if id_ == 'type': return self.entry.type.lower() elif id_ == 'key': return self.entry.key.lower() elif id_ == 'cited': return bool(self.cited_docnames) elif id_ == 'docname': return self.docname elif id_ == 'docnames': return self.cited_docnames elif id_ == 'author' or id_ == 'editor': if id_ in self.entry.persons: return u' and '.join( str(person) # XXX needs fix in pybtex? for person in self.entry.persons[id_]) else: return u'' else: return self.entry.fields.get(id_, "") def visit_Set(self, node): return frozenset(self.visit(elt) for elt in node.elts) # NameConstant is Python 3.4 only def visit_NameConstant(self, node): return node.value # pragma: no cover # Constant is Python 3.6+ only # Since 3.8 Num, Str, Bytes, NameConstant and Ellipsis are just Constant def visit_Constant(self, node): return node.value # Not used on 3.8+ def visit_Str(self, node): return node.s # pragma: no cover def generic_visit(self, node): _raise_invalid_node(node) def get_docnames(env): """Get document names in order.""" rel = env.collect_relations() docname = env.config.master_doc docnames = set() while docname is not None: docnames.add(docname) yield docname parent, prevdoc, nextdoc = rel[docname] docname = nextdoc for docname in sorted(env.found_docs - docnames): yield docname class Citation(NamedTuple): """Information about a citation.""" citation_id: str #: Unique id of this citation. bibliography_key: "BibliographyKey" #: Key of its bibliography directive. key: str #: Key (with prefix). entry: "Entry" #: Entry from pybtex. formatted_entry: "FormattedEntry" #: Entry as formatted by pybtex. class SphinxReferenceInfo(NamedTuple): """Tuple containing reference info to enable sphinx to resolve a reference to a citation. """ builder: "Builder" #: The Sphinx builder. fromdocname: str #: Document name of the citation reference. todocname: str #: Document name of the bibliography. citation_id: str #: Unique id of the citation within the bibliography. title: str #: Title attribute for reference node. class SphinxReferenceText(BaseReferenceText[SphinxReferenceInfo]): """Pybtex rich text class for citation references with the docutils backend, for use with :class:`SphinxReferenceInfo`. """ def render(self, backend: "BaseBackend"): assert isinstance(backend, pybtex_docutils.Backend), \ "SphinxReferenceText only supports the docutils backend" info = self.info[0] if info.builder.name == 'latex': key = f'cite.{info.todocname}:{info.citation_id}' return ( [raw_latex(f'\\hyperlink{{{key}}}{{')] + super().render(backend) + [raw_latex('}')] ) else: children = super().render(backend) # make_refnode only takes a single child refnode = make_refnode( builder=info.builder, fromdocname=info.fromdocname, todocname=info.todocname, targetid=info.citation_id, child=children[0], title=info.title, ) refnode.extend(children[1:]) # type: ignore return [refnode] def env_updated(app: "Sphinx", env: "BuildEnvironment") -> Iterable[str]: domain = cast(BibtexDomain, env.get_domain('cite')) return domain.env_updated() def parse_header(header: str, source_path: str): parser = docutils.parsers.rst.Parser() # note: types stub for docutils doesn't know about components argument settings = docutils.frontend.OptionParser( components=(docutils.parsers.rst.Parser,) # type: ignore ).get_default_values() document = docutils.utils.new_document(source_path, settings) parser.parse(header, document) return document[0] class BibtexDomain(Domain): """Sphinx domain for the bibtex extension.""" name = 'cite' label = 'BibTeX Citations' data_version = 4 initial_data = dict( bibdata=BibData( encoding='', bibfiles={}, data=pybtex.database.BibliographyData()), bibliography_header=docutils.nodes.paragraph(), bibliographies={}, citations=[], citation_refs=[], ) backend = pybtex_docutils.Backend() reference_style: BaseReferenceStyle @property def bibdata(self) -> BibData: """Information about the bibliography files.""" return self.data['bibdata'] @property def bibliography_header(self) -> docutils.nodes.Element: return self.data['bibliography_header'] @property def bibliographies(self) -> Dict["BibliographyKey", "BibliographyValue"]: """Map storing information about each bibliography directive.""" return self.data['bibliographies'] @property def citations(self) -> List[Citation]: """Citation data.""" return self.data['citations'] @property def citation_refs(self) -> List["CitationRef"]: """Citation reference data.""" return self.data['citation_refs'] def __init__(self, env: "BuildEnvironment"): # set up referencing style style = sphinxcontrib.bibtex.plugin.find_plugin( 'sphinxcontrib.bibtex.style.referencing', env.app.config.bibtex_reference_style) self.reference_style = style() # set up object types and roles for referencing style role_names = self.reference_style.role_names() self.object_types = dict( citation=ObjType(_('citation'), *role_names, searchprio=-1), ) self.roles = dict((name, CiteRole()) for name in role_names) # initialize the domain super().__init__(env) # connect env-updated env.app.connect('env-updated', env_updated) # check config if env.app.config.bibtex_bibfiles is None: raise ExtensionError( "You must configure the bibtex_bibfiles setting") # update bib file information in the cache bibfiles = [ normpath_filename(env, "/" + bibfile) for bibfile in env.app.config.bibtex_bibfiles] self.data['bibdata'] = process_bibdata( self.bibdata, bibfiles, env.app.config.bibtex_encoding) # parse bibliography header header = getattr(env.app.config, "bibtex_bibliography_header") if header: self.data["bibliography_header"] = \ parse_header(header, "bibliography_header") def clear_doc(self, docname: str) -> None: self.data['citations'] = [ citation for citation in self.citations if citation.bibliography_key.docname != docname] self.data['citation_refs'] = [ ref for ref in self.citation_refs if ref.docname != docname] for bib_key in list(self.bibliographies.keys()): if bib_key.docname == docname: del self.bibliographies[bib_key] def merge_domaindata(self, docnames: List[str], otherdata: Dict) -> None: for bib_key, bib_value in otherdata['bibliographies'].items(): if bib_key.docname in docnames: self.bibliographies[bib_key] = bib_value for citation_ref in otherdata['citation_refs']: if citation_ref.docname in docnames: self.citation_refs.append(citation_ref) # 'citations' domain data calculated in env_updated def env_updated(self) -> Iterable[str]: # This function is called when all doctrees are parsed, # but before any post transforms are applied. We use it to # determine which citations will be added to which bibliography # directive, and also to format the labels. We need to format # the labels here because they must be known when resolve_xref is # called. self.citations.clear() # might have been restored from pickle docnames = list(get_docnames(self.env)) # we keep track of this to quickly check for duplicates used_keys: Set[str] = set() used_labels: Dict[str, str] = {} for bibliography_key, bibliography in self.bibliographies.items(): for entry, formatted_entry in self.get_formatted_entries( bibliography_key, docnames): key = bibliography.keyprefix + formatted_entry.key if bibliography.list_ == 'citation' and key in used_keys: logger.warning( 'duplicate citation for key "%s"' % key, location=(bibliography_key.docname, bibliography.line), type="bibtex", subtype="duplicate_citation") self.citations.append(Citation( citation_id=bibliography.citation_nodes[key]['ids'][0], bibliography_key=bibliography_key, key=key, entry=entry, formatted_entry=formatted_entry, )) if bibliography.list_ == 'citation': used_keys.add(key) if formatted_entry.label not in used_labels: used_labels[formatted_entry.label] = key elif used_labels[formatted_entry.label] != key: # if used_label[label] == key then already # duplicate key warning logger.warning( 'duplicate label "%s" for keys "%s" and "%s"' % ( formatted_entry.label, used_labels[formatted_entry.label], key), location=(bibliography_key.docname, bibliography.line), type="bibtex", subtype="duplicate_label") return [] # expects list of updated docnames def resolve_xref(self, env: "BuildEnvironment", fromdocname: str, builder: "Builder", typ: str, target: str, node: "pending_xref", contnode: docutils.nodes.Element ) -> docutils.nodes.Element: """Replace node by list of citation references (one for each key).""" keys = [key.strip() for key in target.split(',')] citations: Dict[str, Citation] = { cit.key: cit for cit in self.citations if cit.key in keys and self.bibliographies[cit.bibliography_key].list_ == 'citation'} for key in keys: if key not in citations: logger.warning('could not find bibtex key "%s"' % key, location=node, type="bibtex", subtype="key_not_found") plaintext = pybtex.plugin.find_plugin('pybtex.backends', 'plaintext')() references = [ (citation.entry, citation.formatted_entry, SphinxReferenceInfo( builder=builder, fromdocname=fromdocname, todocname=citation.bibliography_key.docname, citation_id=citation.citation_id, title=citation.formatted_entry.text.render(plaintext))) for citation in citations.values()] formatted_references = \ format_references( self.reference_style, SphinxReferenceText, typ, references) result_node = docutils.nodes.inline(rawsource=target) result_node += formatted_references.render(self.backend) return result_node def resolve_any_xref(self, env: "BuildEnvironment", fromdocname: str, builder: "Builder", target: str, node: "pending_xref", contnode: docutils.nodes.Element ) -> List[Tuple[str, docutils.nodes.Element]]: """Replace node by list of citation references (one for each key), provided that the target has citation keys. """ keys = [key.strip() for key in target.split(',')] citations: Set[str] = { cit.key for cit in self.citations if cit.key in keys and self.bibliographies[cit.bibliography_key].list_ == 'citation'} if any(key in citations for key in keys): result_node = self.resolve_xref( env, fromdocname, builder, 'p', target, node, contnode) return [('p', result_node)] else: return [] def get_all_cited_keys(self, docnames): """Yield all citation keys for given *docnames* in order, then ordered by citation order. """ for citation_ref in sorted( self.citation_refs, key=lambda c: docnames.index(c.docname)): for key in citation_ref.keys: yield key def get_entries( self, bibfiles: List[str]) -> Iterable["Entry"]: """Return all bibliography entries from the bib files, unsorted (i.e. in order of appearance in the bib files. """ for bibfile in bibfiles: for key in self.bibdata.bibfiles[bibfile].keys: yield self.bibdata.data.entries[key] def get_filtered_entries( self, bibliography_key: "BibliographyKey" ) -> Iterable[Tuple[str, "Entry"]]: """Return unsorted bibliography entries filtered by the filter expression. """ bibliography = self.bibliographies[bibliography_key] for entry in self.get_entries(bibliography.bibfiles): key = bibliography.keyprefix + entry.key cited_docnames = { citation_ref.docname for citation_ref in self.citation_refs if key in citation_ref.keys } visitor = _FilterVisitor( entry=entry, docname=bibliography_key.docname, cited_docnames=cited_docnames) try: success = visitor.visit(bibliography.filter_) except ValueError as err: logger.warning( "syntax error in :filter: expression; %s" % err, location=(bibliography_key.docname, bibliography.line), type="bibtex", subtype="filter_syntax_error") # recover by falling back to the default success = bool(cited_docnames) if success or entry.key in bibliography.keys: yield key, entry def get_sorted_entries( self, bibliography_key: "BibliographyKey", docnames: List[str] ) -> Iterable[Tuple[str, "Entry"]]: """Return filtered bibliography entries sorted by citation order.""" entries = dict( self.get_filtered_entries(bibliography_key)) for key in self.get_all_cited_keys(docnames): try: entry = entries.pop(key) except KeyError: pass else: yield key, entry # then all remaining keys, in order of bibliography file for key, entry in entries.items(): yield key, entry def get_formatted_entries( self, bibliography_key: "BibliographyKey", docnames: List[str] ) -> Iterable[Tuple["Entry", "FormattedEntry"]]: """Get sorted bibliography entries along with their pybtex labels, with additional sorting and formatting applied from the pybtex style. """ bibliography = self.bibliographies[bibliography_key] entries = dict( self.get_sorted_entries(bibliography_key, docnames)) style = cast("BaseStyle", pybtex.plugin.find_plugin( 'pybtex.style.formatting', bibliography.style)()) sorted_entries = style.sort(entries.values()) labels = style.format_labels(sorted_entries) for label, entry in zip(labels, sorted_entries): try: yield ( entry, style.format_entry( bibliography.labelprefix + label, entry), ) except FieldIsMissing as exc: logger.warning( str(exc), location=(bibliography_key.docname, bibliography.line), type="bibtex", subtype="missing_field") yield( entry, FormattedEntry(entry.key, Tag('b', str(exc)), bibliography.labelprefix + label) ) sphinxcontrib-bibtex-2.4.1/src/sphinxcontrib/bibtex/foot_directives.py000066400000000000000000000043001411661013000263510ustar00rootroot00000000000000""" .. autoclass:: FootBibliographyDirective .. automethod:: run """ from typing import TYPE_CHECKING, cast from docutils.parsers.rst import Directive from .bibfile import _make_ids if TYPE_CHECKING: from sphinx.environment import BuildEnvironment from .domain import BibtexDomain from .foot_domain import BibtexFootDomain class FootBibliographyDirective(Directive): """Class for processing the :rst:dir:`footbibliography` directive.""" required_arguments = 0 optional_arguments = 0 has_content = False def run(self): """Set file dependencies, and insert the footnotes that were created earlier by :meth:`.foot_roles.FootCiteRole.result_nodes`. """ env = cast("BuildEnvironment", self.state.document.settings.env) foot_old_refs = env.temp_data.setdefault("bibtex_foot_old_refs", set()) foot_new_refs = env.temp_data.setdefault("bibtex_foot_new_refs", set()) footbibliography_count = \ env.temp_data["bibtex_footbibliography_count"] = \ env.temp_data.get("bibtex_footbibliography_count", 0) + 1 if not foot_new_refs: return [] else: foot_old_refs |= foot_new_refs foot_new_refs.clear() # bibliography stored in env.temp_data["bibtex_foot_bibliography"] foot_domain = cast("BibtexFootDomain", env.get_domain('footcite')) foot_bibliography, env.temp_data["bibtex_foot_bibliography"] = ( env.temp_data["bibtex_foot_bibliography"], foot_domain.bibliography_header.deepcopy()) domain = cast("BibtexDomain", env.get_domain('cite')) for bibfile in domain.bibdata.bibfiles: env.note_dependency(bibfile) foot_bibliography['ids'] += _make_ids( docname=env.docname, lineno=self.lineno, ids=set(self.state.document.ids.keys()), raw_id=env.app.config.bibtex_footbibliography_id.format( footbibliography_count=footbibliography_count)) self.state.document.note_explicit_target( foot_bibliography, foot_bibliography) return [foot_bibliography] sphinxcontrib-bibtex-2.4.1/src/sphinxcontrib/bibtex/foot_domain.py000066400000000000000000000055061411661013000254700ustar00rootroot00000000000000""" Domain for footnote citations. .. autoclass:: BibtexFootDomain :members: """ from typing import TYPE_CHECKING, List, Dict, Tuple import docutils.nodes import docutils.utils import sphinxcontrib.bibtex.plugin import sphinx.util from sphinx.domains import Domain, ObjType from sphinx.locale import _ from .foot_roles import FootCiteRole from .domain import parse_header from .style.referencing import BaseReferenceStyle if TYPE_CHECKING: from sphinx.environment import BuildEnvironment from sphinx.addnodes import pending_xref from sphinx.builders import Builder logger = sphinx.util.logging.getLogger(__name__) class BibtexFootDomain(Domain): """Sphinx domain for footnote citations.""" name = 'footcite' label = 'BibTeX Footnote Citations' data_version = 0 initial_data = dict( bibliography_header=docutils.nodes.paragraph(), ) reference_style: BaseReferenceStyle @property def bibliography_header(self) -> docutils.nodes.Element: return self.data['bibliography_header'] def __init__(self, env: "BuildEnvironment"): # set up referencing style style = sphinxcontrib.bibtex.plugin.find_plugin( 'sphinxcontrib.bibtex.style.referencing', env.app.config.bibtex_foot_reference_style) self.reference_style = style() # set up object types and roles for referencing style role_names = self.reference_style.role_names() self.object_types = dict( citation=ObjType(_('citation'), *role_names, searchprio=-1), ) self.roles = dict((name, FootCiteRole()) for name in role_names) # initialize the domain super().__init__(env) # parse bibliography header header = getattr(env.app.config, "bibtex_footbibliography_header") if header: self.data["bibliography_header"] = \ parse_header(header, "foot_bibliography_header") def merge_domaindata(self, docnames: List[str], otherdata: Dict) -> None: """Merge in data regarding *docnames* from domain data inventory *otherdata*. As there is no document specific data for this domain, this function does nothing. """ pass def resolve_any_xref(self, env: "BuildEnvironment", fromdocname: str, builder: "Builder", target: str, node: "pending_xref", contnode: docutils.nodes.Element ) -> List[Tuple[str, docutils.nodes.Element]]: """Resolve the pending reference *node* with the given *target*, where the reference comes from an "any" role. Since citation references are resolved to regular citations, and not to footnote citations, this implementation simply returns an empty list. """ return [] sphinxcontrib-bibtex-2.4.1/src/sphinxcontrib/bibtex/foot_roles.py000066400000000000000000000133461411661013000253460ustar00rootroot00000000000000""" .. autoclass:: FootReferenceInfo :members: .. autoclass:: FootReferenceText :members: .. autoclass:: FootCiteRole :show-inheritance: .. automethod:: result_nodes """ from typing import TYPE_CHECKING, cast, Tuple, List, NamedTuple import docutils.nodes import pybtex_docutils from docutils.nodes import make_id from pybtex.plugin import find_plugin from sphinx.roles import XRefRole from sphinx.util.logging import getLogger from .richtext import BaseReferenceText from .style.referencing import format_references from .transforms import node_text_transform if TYPE_CHECKING: from sphinx.environment import BuildEnvironment from .domain import BibtexDomain from .foot_domain import BibtexFootDomain from pybtex.backends import BaseBackend logger = getLogger(__name__) class FootReferenceInfo(NamedTuple): """Tuple containing reference info to enable sphinx to resolve a footnote reference. """ key: str #: Citation key. document: "docutils.nodes.document" #: Current docutils document. refname: str #: Citation reference name. class FootReferenceText(BaseReferenceText[FootReferenceInfo]): """Pybtex rich text class for footnote references with the docutils backend, for use with :class:`FootReferenceInfo`. """ def render(self, backend: "BaseBackend"): assert isinstance(backend, pybtex_docutils.Backend), \ "FootReferenceText only supports the docutils backend" info = self.info[0] # see docutils.parsers.rst.states.Body.footnote_reference() refnode = docutils.nodes.footnote_reference( '[#%s]_' % info.key, refname=info.refname, auto=1) info.document.note_autofootnote_ref(refnode) info.document.note_footnote_ref(refnode) return [refnode] class FootCiteRole(XRefRole): """Class for processing the :rst:role:`footcite` role.""" def result_nodes(self, document: "docutils.nodes.document", env: "BuildEnvironment", node: "docutils.nodes.Element", is_ref: bool ) -> Tuple[List["docutils.nodes.Node"], List["docutils.nodes.system_message"]]: """Transform node into footnote references, and add footnotes to a node stored in the environment's temporary data if they are not yet present. .. seealso:: The node containing all footnotes is inserted into the document by :meth:`.foot_directives.FootBibliographyDirective.run`. """ if not node.get('refdomain'): assert node['reftype'] == 'footcite' node['refdomain'] = 'footcite' node['reftype'] = 'p' foot_domain = cast("BibtexFootDomain", self.env.get_domain('footcite')) keys = [key.strip() for key in self.target.split(',')] # type: ignore try: foot_bibliography = env.temp_data["bibtex_foot_bibliography"] except KeyError: env.temp_data["bibtex_foot_bibliography"] = foot_bibliography = \ foot_domain.bibliography_header.deepcopy() foot_old_refs = env.temp_data.setdefault("bibtex_foot_old_refs", set()) foot_new_refs = env.temp_data.setdefault("bibtex_foot_new_refs", set()) style = find_plugin( 'pybtex.style.formatting', self.config.bibtex_default_style)() references = [] domain = cast("BibtexDomain", self.env.get_domain('cite')) # count only incremented at directive, see foot_directives run method footbibliography_count = env.temp_data.setdefault( "bibtex_footbibliography_count", 0) footcite_names = env.temp_data.setdefault( "bibtex_footcite_names", {}) for key in keys: entry = domain.bibdata.data.entries.get(key) if entry is not None: formatted_entry = style.format_entry(label='', entry=entry) if key not in (foot_old_refs | foot_new_refs): footnote = docutils.nodes.footnote(auto=1) # no automatic ids for footnotes: force non-empty template template: str = \ env.app.config.bibtex_footcite_id \ if env.app.config.bibtex_footcite_id \ else "footcite-{key}" raw_id = template.format( footbibliography_count=footbibliography_count + 1, key=entry.key) # format name with make_id for consistency with cite role name = make_id(raw_id) footnote['names'] += [name] footcite_names[entry.key] = name footnote += domain.backend.paragraph(formatted_entry) document.note_autofootnote(footnote) document.note_explicit_target(footnote, footnote) node_text_transform(footnote) foot_bibliography += footnote foot_new_refs.add(key) references.append( (entry, formatted_entry, FootReferenceInfo( key=entry.key, refname=footcite_names[entry.key], document=document))) else: logger.warning('could not find bibtex key "%s"' % key, location=(env.docname, self.lineno), type="bibtex", subtype="key_not_found") ref_nodes = format_references( foot_domain.reference_style, FootReferenceText, node['reftype'], references).render(domain.backend) return ref_nodes, [] sphinxcontrib-bibtex-2.4.1/src/sphinxcontrib/bibtex/nodes.py000066400000000000000000000016571411661013000243050ustar00rootroot00000000000000""" .. autoclass:: bibliography .. autoclass:: raw_latex .. autofunction:: visit_raw_latex .. autofunction:: depart_raw_latex """ from docutils import nodes from sphinx.writers.latex import LaTeXTranslator class bibliography(nodes.General, nodes.Element): """Node for representing a bibliography. Replaced by a list of citations by :class:`~sphinxcontrib.bibtex.transforms.BibliographyTransform`. """ pass class raw_latex( nodes.Special, nodes.Inline, nodes.PreBibliographic, nodes.FixedTextElement): """Node for representing raw latex data.""" pass def visit_raw_latex(self: LaTeXTranslator, node: raw_latex): """Called when entering a raw_latex node. Appends the node's raw source to the latex body. """ self.body.append(node.rawsource) def depart_raw_latex(self: LaTeXTranslator, node: raw_latex): """Called when leaving a raw_latex node.""" pass sphinxcontrib-bibtex-2.4.1/src/sphinxcontrib/bibtex/plugin.py000066400000000000000000000021721411661013000244640ustar00rootroot00000000000000import pkg_resources from pybtex.plugin import _FakeEntryPoint from typing import Type, Any, Dict def find_plugin(group: str, name: str) -> Type[Any]: """Load a sphinxcontrib-bibtex plugin.""" dist = pkg_resources.get_distribution('sphinxcontrib-bibtex') if group not in dist.get_entry_map(): raise ImportError(f"plugin group {group} not found") for entry_point in pkg_resources.iter_entry_points(group, name): return entry_point.load() raise ImportError(f"plugin {group}.{name} not found") def register_plugin(group: str, name: str, klass: Type[Any], force: bool = False) -> bool: """Register a sphinxcontrib-bibtex plugin at runtime.""" dist = pkg_resources.get_distribution('sphinxcontrib-bibtex') entry_map: Dict[str, Dict[str, pkg_resources.EntryPoint]] \ = dist.get_entry_map() try: entry_points = entry_map[group] except KeyError: raise ImportError(f"plugin group {group} not found") if name not in entry_points or force: entry_points[name] = _FakeEntryPoint(name, klass) return True else: return False sphinxcontrib-bibtex-2.4.1/src/sphinxcontrib/bibtex/py.typed000066400000000000000000000000001411661013000242770ustar00rootroot00000000000000sphinxcontrib-bibtex-2.4.1/src/sphinxcontrib/bibtex/richtext.py000066400000000000000000000017071411661013000250230ustar00rootroot00000000000000from abc import ABC from typing import TypeVar, Generic from pybtex.richtext import BaseMultipartText, BaseText ReferenceInfo = TypeVar('ReferenceInfo') """Generic type parameter for types that store reference information. To be implemented by clients. See for instance :class:`~sphinxcontrib.bibtex.domain.SphinxReferenceInfo`. """ class BaseReferenceText(BaseMultipartText, Generic[ReferenceInfo], ABC): """Generic rich text element for citation references. Instances store some extra reference info that can be used when formatting. This base class renders its children without further formatting. Implementations must create a derivation from this class which overrides the *render* method to create the desired output. See for instance :class:`~sphinxcontrib.bibtex.domain.SphinxReferenceText`. """ def __init__(self, info: ReferenceInfo, *parts: "BaseText"): self.info = (info,) super().__init__(*parts) sphinxcontrib-bibtex-2.4.1/src/sphinxcontrib/bibtex/roles.py000066400000000000000000000030411411661013000243060ustar00rootroot00000000000000""" .. autoclass:: CitationRef :members: .. autoclass:: CiteRole :show-inheritance: .. automethod:: result_nodes """ import docutils.nodes from typing import TYPE_CHECKING, cast, NamedTuple, List from pybtex.plugin import find_plugin from sphinx.roles import XRefRole if TYPE_CHECKING: from .domain import BibtexDomain class CitationRef(NamedTuple): """Information about a citation reference.""" citation_ref_id: str #: Unique id of this citation reference. docname: str #: Document name. line: int #: Line number. keys: List[str] #: Citation keys (including key prefix). class CiteRole(XRefRole): """Class for processing the :rst:role:`cite` role.""" backend = find_plugin('pybtex.backends', 'docutils')() innernodeclass = docutils.nodes.inline def result_nodes(self, document, env, node, is_ref): """Associate the pending_xref with the cite domain, and note the cited citation keys. """ if not node.get('refdomain'): assert node['reftype'] == 'cite' node['refdomain'] = 'cite' node['reftype'] = 'p' document.note_explicit_target(node, node) # for backrefs domain = cast("BibtexDomain", env.get_domain('cite')) domain.citation_refs.append(CitationRef( citation_ref_id=node['ids'][0], docname=env.docname, line=document.line, keys=[key.strip() for key in self.target.split(',')], )) return [node], [] sphinxcontrib-bibtex-2.4.1/src/sphinxcontrib/bibtex/style/000077500000000000000000000000001411661013000237525ustar00rootroot00000000000000sphinxcontrib-bibtex-2.4.1/src/sphinxcontrib/bibtex/style/__init__.py000066400000000000000000000000001411661013000260510ustar00rootroot00000000000000sphinxcontrib-bibtex-2.4.1/src/sphinxcontrib/bibtex/style/names/000077500000000000000000000000001411661013000250555ustar00rootroot00000000000000sphinxcontrib-bibtex-2.4.1/src/sphinxcontrib/bibtex/style/names/__init__.py000066400000000000000000000000001411661013000271540ustar00rootroot00000000000000sphinxcontrib-bibtex-2.4.1/src/sphinxcontrib/bibtex/style/names/last.py000066400000000000000000000006441411661013000263760ustar00rootroot00000000000000from pybtex.style.names import BaseNameStyle, name_part from pybtex.style.template import join class LastNameStyle(BaseNameStyle): """A simple name style for formatting the last name of an author.""" def format(self, person, abbr=True): """Format last names.""" return join[ name_part(tie=True)[person.rich_prelast_names], name_part[person.rich_last_names], ] sphinxcontrib-bibtex-2.4.1/src/sphinxcontrib/bibtex/style/referencing/000077500000000000000000000000001411661013000262415ustar00rootroot00000000000000sphinxcontrib-bibtex-2.4.1/src/sphinxcontrib/bibtex/style/referencing/__init__.py000066400000000000000000000160561411661013000303620ustar00rootroot00000000000000import dataclasses from abc import ABC import pybtex.plugin from pybtex.richtext import Text, Tag from sphinxcontrib.bibtex.richtext import ReferenceInfo, BaseReferenceText from sphinxcontrib.bibtex.style.template import ( names, sentence, join, author_or_editor_or_title ) from typing import ( TYPE_CHECKING, Tuple, List, Union, Iterable, Type, Optional, Dict ) if TYPE_CHECKING: from pybtex.database import Entry from pybtex.richtext import BaseText from pybtex.style import FormattedEntry from pybtex.style.names import BaseNameStyle from pybtex.style.template import Node @dataclasses.dataclass class BaseReferenceStyle(ABC): """Base class for citation reference styles. For consistency, all subclasses of this class must be decorated as a :class:`dataclasses.dataclass`, and must provide a type annotation and default value for all attributes (unless ``init=False`` is used, in which case they can be initialized in :meth:`~dataclasses.dataclass.__post_init__`). This allows client code to instantiate any reference style without needing to specify any arguments through the constructor. """ # see https://stackoverflow.com/a/59987363 as to why this is here def __post_init__(self): pass def role_names(self) -> Iterable[str]: """Get list of role names supported by this style.""" raise NotImplementedError def outer( self, role_name: str, children: List["BaseText"]) -> "Node": """Returns outer template for formatting the references.""" raise NotImplementedError def inner(self, role_name: str) -> "Node": """Returns inner template for formatting the references.""" raise NotImplementedError def format_references( style: BaseReferenceStyle, reference_text_class: Type[BaseReferenceText[ReferenceInfo]], role_name: str, references: Iterable[Tuple[ "Entry", "FormattedEntry", ReferenceInfo]], ) -> "BaseText": """Format the list of references according to the given role. First formats each reference using the style's :meth:`~BaseReferenceStyle.get_inner` method, then joins all these formatted references together using the style's :meth:`~BaseReferenceStyle.get_outer` method. """ children = [ style.inner(role_name).format_data( data=dict( entry=entry, formatted_entry=formatted_entry, reference_info=info, reference_text_class=reference_text_class, style=style)) for entry, formatted_entry, info in references] return style.outer(role_name, children).format() @dataclasses.dataclass class BracketStyle: """A class which provides brackets, as well as separators and a function to facilitate formatting of the outer template. """ #: Left bracket. left: Union["BaseText", str] = '[' #: Right bracket. right: Union["BaseText", str] = ']' #: Separators used for outer template (i.e. in between references #: if multiple keys are referenced in a single citation). sep: Union["BaseText", str] = ', ' #: Separator for outer template, if only two items. sep2: Optional[Union["BaseText", str]] = None #: Separator for outer template, for last item if three or more items. last_sep: Optional[Union["BaseText", str]] = None def outer( self, children: List["BaseText"], brackets=False, capfirst=False) -> "Node": """Creates an outer template with separators, adding brackets if requested, and capitalizing the first word if requested. """ return join[ self.left if brackets else '', sentence( capfirst=capfirst, add_period=False, sep=self.sep, sep2=self.sep2, last_sep=self.last_sep, )[children], self.right if brackets else '', ] @dataclasses.dataclass class PersonStyle: """A class providing additional data and helper functions to facilitate formatting of person names. """ #: Plugin name of the style used for formatting person names. style: str = 'last' #: Plugin class instance used for formatting person names. #: Automatically initialised from :attr:`style`. style_plugin: "BaseNameStyle" = dataclasses.field(init=False) #: Whether or not to abbreviate first names. abbreviate: bool = True #: Separator between persons. sep: Union["BaseText", str] = ', ' #: Separator between persons, if only two persons. sep2: Optional[Union["BaseText", str]] = ' and ' #: Separator between persons, for last person if three or more persons. last_sep: Optional[Union["BaseText", str]] = ', and ' #: Abbreviation text if three or more persons. other: Optional[Union["BaseText", str]] = \ Text(' ', Tag('em', 'et al.')) def __post_init__(self): self.style_plugin = pybtex.plugin.find_plugin( 'pybtex.style.names', name=self.style)() def names(self, role: str, full: bool) -> "Node": """Returns a template formatting the persons with correct separators and using the full person list if so requested. """ return names( role=role, sep=self.sep, sep2=self.sep2, last_sep=self.last_sep, other=None if full else self.other, ) def author_or_editor_or_title(self, full: bool) -> "Node": """Returns a template formatting the author, falling back on editor or title if author is not specified. """ return author_or_editor_or_title( sep=self.sep, sep2=self.sep2, last_sep=self.last_sep, other=None if full else self.other, ) @dataclasses.dataclass class GroupReferenceStyle(BaseReferenceStyle): """Composes a group of reference styles into a single consistent style.""" #: List of style types. styles: List[BaseReferenceStyle] \ = dataclasses.field(default_factory=list) #: Dictionary from role names to styles. #: Automatically initialized from :attr:`styles`. role_style: Dict[str, BaseReferenceStyle] \ = dataclasses.field(default_factory=dict) def __post_init__(self): super().__post_init__() self.role_style.update( (role_name, style) for style in self.styles for role_name in style.role_names() ) def role_names(self): return self.role_style.keys() def outer(self, role_name: str, children: List["BaseText"]) -> "Node": """Gets the outer template associated with *role_name* in one of the :attr:`styles`. """ style = self.role_style[role_name] return style.outer(role_name, children) def inner(self, role_name: str) -> "Node": """Gets the inner template associated with *role_name* in one of the :attr:`styles`. """ style = self.role_style[role_name] return style.inner(role_name) sphinxcontrib-bibtex-2.4.1/src/sphinxcontrib/bibtex/style/referencing/author_year.py000066400000000000000000000047421411661013000311440ustar00rootroot00000000000000import dataclasses from typing import Union, TYPE_CHECKING from sphinxcontrib.bibtex.style.referencing import ( BracketStyle, PersonStyle, GroupReferenceStyle ) from .basic_author_year import ( BasicAuthorYearParentheticalReferenceStyle, BasicAuthorYearTextualReferenceStyle, ) from .extra_author import ExtraAuthorReferenceStyle from .extra_label import ExtraLabelReferenceStyle from .extra_year import ExtraYearReferenceStyle from .extra_empty import ExtraEmptyReferenceStyle if TYPE_CHECKING: from pybtex.richtext import BaseText @dataclasses.dataclass class AuthorYearReferenceStyle(GroupReferenceStyle): """Textual or parenthetical reference by author-year, or just by author, label, or year. """ #: Bracket style for textual citations (:cite:t: and variations). bracket_textual: BracketStyle = BracketStyle() #: Bracket style for parenthetical citations #: (:cite:p: and variations). bracket_parenthetical: BracketStyle = BracketStyle() #: Bracket style for author citations #: (:cite:author: and variations). bracket_author: BracketStyle = BracketStyle() #: Bracket style for label citations #: (:cite:label: and variations). bracket_label: BracketStyle = BracketStyle() #: Bracket style for year citations #: (:cite:year: and variations). bracket_year: BracketStyle = BracketStyle() #: Person style (applies to all relevant citation commands). person: PersonStyle = PersonStyle() #: Separator between author and year for parenthetical citations. author_year_sep: Union["BaseText", str] = ', ' #: Separator between text and reference for textual citations. text_reference_sep: Union["BaseText", str] = ' ' def __post_init__(self): self.styles.extend([ BasicAuthorYearParentheticalReferenceStyle( bracket=self.bracket_parenthetical, person=self.person, author_year_sep=self.author_year_sep, ), BasicAuthorYearTextualReferenceStyle( bracket=self.bracket_textual, person=self.person, text_reference_sep=self.text_reference_sep, ), ExtraAuthorReferenceStyle( bracket=self.bracket_author, person=self.person), ExtraLabelReferenceStyle(bracket=self.bracket_label), ExtraYearReferenceStyle(bracket=self.bracket_year), ExtraEmptyReferenceStyle(), ]) super().__post_init__() sphinxcontrib-bibtex-2.4.1/src/sphinxcontrib/bibtex/style/referencing/basic_author_year.py000066400000000000000000000043111411661013000322750ustar00rootroot00000000000000import dataclasses from typing import TYPE_CHECKING, List, Iterable, Union from sphinxcontrib.bibtex.style.template import reference, join, year from . import BaseReferenceStyle, BracketStyle, PersonStyle if TYPE_CHECKING: from pybtex.richtext import BaseText from pybtex.style.template import Node @dataclasses.dataclass class BasicAuthorYearParentheticalReferenceStyle(BaseReferenceStyle): """Parenthetical reference by author-year.""" #: Bracket style. bracket: BracketStyle = BracketStyle() #: Person style. person: PersonStyle = PersonStyle() #: Separator between author and year. author_year_sep: Union["BaseText", str] = ', ' def role_names(self) -> Iterable[str]: return [f'p{full_author}' for full_author in ['', 's']] def outer(self, role_name: str, children: List["BaseText"]) -> "Node": return self.bracket.outer( children, brackets=True, capfirst=False) def inner(self, role_name: str) -> "Node": return reference[ join(sep=self.author_year_sep)[ self.person.author_or_editor_or_title(full='s' in role_name), year ] ] @dataclasses.dataclass class BasicAuthorYearTextualReferenceStyle(BaseReferenceStyle): """Textual reference by author-year.""" #: Bracket style. bracket: BracketStyle = BracketStyle() #: Person style. person: PersonStyle = PersonStyle() #: Separator between text and reference. text_reference_sep: Union["BaseText", str] = ' ' def role_names(self) -> Iterable[str]: return [f'{capfirst}t{full_author}' for capfirst in ['', 'c'] for full_author in ['', 's']] def outer(self, role_name: str, children: List["BaseText"]) -> "Node": return self.bracket.outer( children, brackets=False, capfirst='c' in role_name) def inner(self, role_name: str) -> "Node": return join(sep=self.text_reference_sep)[ self.person.author_or_editor_or_title(full='s' in role_name), join[ self.bracket.left, reference[year], self.bracket.right ] ] sphinxcontrib-bibtex-2.4.1/src/sphinxcontrib/bibtex/style/referencing/basic_foot.py000066400000000000000000000031321411661013000307220ustar00rootroot00000000000000import dataclasses from typing import TYPE_CHECKING, List, Iterable, Union from sphinxcontrib.bibtex.style.template import footnote_reference, join from . import BaseReferenceStyle, PersonStyle, BracketStyle if TYPE_CHECKING: from pybtex.richtext import BaseText from pybtex.style.template import Node @dataclasses.dataclass class BasicFootParentheticalReferenceStyle(BaseReferenceStyle): """Parenthetical footnote reference.""" def role_names(self) -> Iterable[str]: return ['p', 'ps'] def outer(self, role_name: str, children: List["BaseText"]) -> "Node": return join[children] def inner(self, role_name: str) -> "Node": return footnote_reference @dataclasses.dataclass class BasicFootTextualReferenceStyle(BaseReferenceStyle): """Textual footnote reference.""" #: Bracket style. bracket: BracketStyle = BracketStyle() #: Person style. person: PersonStyle = PersonStyle() #: Separator between text and reference. text_reference_sep: Union["BaseText", str] = ' ' def role_names(self) -> Iterable[str]: return [f'{capfirst}t{full_author}' for capfirst in ['', 'c'] for full_author in ['', 's']] def outer(self, role_name: str, children: List["BaseText"]) -> "Node": return self.bracket.outer( children, brackets=False, capfirst='c' in role_name) def inner(self, role_name: str) -> "Node": return join(sep=self.text_reference_sep)[ self.person.author_or_editor_or_title(full='s' in role_name), footnote_reference, ] sphinxcontrib-bibtex-2.4.1/src/sphinxcontrib/bibtex/style/referencing/basic_label.py000066400000000000000000000040571411661013000310410ustar00rootroot00000000000000import dataclasses from typing import TYPE_CHECKING, List, Iterable, Union from sphinxcontrib.bibtex.style.template import reference, entry_label, join from . import BracketStyle, PersonStyle, BaseReferenceStyle if TYPE_CHECKING: from pybtex.richtext import BaseText from pybtex.style.template import Node @dataclasses.dataclass class BasicLabelParentheticalReferenceStyle(BaseReferenceStyle): """Reference by label if parenthetical, and by author and label if textual. """ #: Bracket style. bracket: BracketStyle = BracketStyle() #: Person style. person: PersonStyle = PersonStyle() def role_names(self) -> Iterable[str]: return [f'p{full_author}' for full_author in ['', 's']] def outer(self, role_name: str, children: List["BaseText"]) -> "Node": return self.bracket.outer( children, brackets=True, capfirst=False) def inner(self, role_name: str) -> "Node": return reference[entry_label] @dataclasses.dataclass class BasicLabelTextualReferenceStyle(BaseReferenceStyle): """Reference by label if parenthetical, and by author and label if textual. """ #: Bracket style. bracket: BracketStyle = BracketStyle() #: Person style. person: PersonStyle = PersonStyle() #: Separator between text and reference. text_reference_sep: Union["BaseText", str] = ' ' def role_names(self) -> Iterable[str]: return [f'{capfirst}t{full_author}' for capfirst in ['', 'c'] for full_author in ['', 's']] def outer(self, role_name: str, children: List["BaseText"]) -> "Node": return self.bracket.outer( children, brackets=False, capfirst='c' in role_name) def inner(self, role_name: str) -> "Node": return join(sep=self.text_reference_sep)[ self.person.author_or_editor_or_title(full='s' in role_name), join[ self.bracket.left, reference[entry_label], self.bracket.right ] ] sphinxcontrib-bibtex-2.4.1/src/sphinxcontrib/bibtex/style/referencing/basic_super.py000066400000000000000000000045331411661013000311170ustar00rootroot00000000000000import dataclasses from typing import TYPE_CHECKING, List, Iterable, Union from pybtex.style.template import tag from sphinxcontrib.bibtex.style.template import reference, entry_label, join from . import BracketStyle, PersonStyle, BaseReferenceStyle if TYPE_CHECKING: from pybtex.richtext import BaseText from pybtex.style.template import Node @dataclasses.dataclass class BasicSuperParentheticalReferenceStyle(BaseReferenceStyle): """Reference by label superscript if parenthetical, and by author and label superscript if textual. """ #: Bracket style. Left and right brackets are empty by default. bracket: BracketStyle = BracketStyle(left='', right='', sep=',') #: Person style. person: PersonStyle = PersonStyle() def role_names(self) -> Iterable[str]: return [f'p{full_author}' for full_author in ['', 's']] def outer(self, role_name: str, children: List["BaseText"]) -> "Node": return tag('sup')[self.bracket.outer( children, brackets=True, capfirst=False)] def inner(self, role_name: str) -> "Node": return reference[entry_label] @dataclasses.dataclass class BasicSuperTextualReferenceStyle(BaseReferenceStyle): """Reference by label superscript if parenthetical, and by author and label superscript if textual. """ #: Bracket style. Left and right brackets are empty by default. bracket: BracketStyle = BracketStyle(left='', right='', sep=', ') #: Person style. person: PersonStyle = PersonStyle() #: Separator between text and reference. text_reference_sep: Union["BaseText", str] = '' def role_names(self) -> Iterable[str]: return [f'{capfirst}t{full_author}' for capfirst in ['', 'c'] for full_author in ['', 's']] def outer(self, role_name: str, children: List["BaseText"]) -> "Node": return self.bracket.outer( children, brackets=False, capfirst='c' in role_name) def inner(self, role_name: str) -> "Node": return join(sep=self.text_reference_sep)[ self.person.author_or_editor_or_title(full='s' in role_name), tag('sup')[ join[ self.bracket.left, reference[entry_label], self.bracket.right ] ] ] sphinxcontrib-bibtex-2.4.1/src/sphinxcontrib/bibtex/style/referencing/extra_author.py000066400000000000000000000022601411661013000313200ustar00rootroot00000000000000import dataclasses from sphinxcontrib.bibtex.style.template import reference from typing import TYPE_CHECKING, List, Iterable from . import BracketStyle, PersonStyle, BaseReferenceStyle if TYPE_CHECKING: from pybtex.richtext import BaseText from pybtex.style.template import Node @dataclasses.dataclass class ExtraAuthorReferenceStyle(BaseReferenceStyle): """Reference just by author names.""" #: Bracket style. bracket: BracketStyle = BracketStyle() #: Person style. person: PersonStyle = PersonStyle() def role_names(self) -> Iterable[str]: return [ f'{capfirst}author{parenthetical}{full_author}' for parenthetical in ['par', ''] for capfirst in (['', 'c'] if parenthetical == '' else ['']) for full_author in ['', 's'] ] def outer(self, role_name: str, children: List["BaseText"]) -> "Node": return self.bracket.outer( children, brackets='par' in role_name, capfirst='c' in role_name, ) def inner(self, role_name: str) -> "Node": return reference[ self.person.author_or_editor_or_title(full='s' in role_name)] sphinxcontrib-bibtex-2.4.1/src/sphinxcontrib/bibtex/style/referencing/extra_empty.py000066400000000000000000000011761411661013000311610ustar00rootroot00000000000000import dataclasses from typing import TYPE_CHECKING, List, Iterable from sphinxcontrib.bibtex.style.template import join from . import BaseReferenceStyle if TYPE_CHECKING: from pybtex.richtext import BaseText from pybtex.style.template import Node @dataclasses.dataclass class ExtraEmptyReferenceStyle(BaseReferenceStyle): """A style which generates nothing, similar to LaTeX's nocite.""" def role_names(self) -> Iterable[str]: return ['empty'] def outer(self, role_name: str, children: List["BaseText"]) -> "Node": return join def inner(self, role_name: str) -> "Node": return join sphinxcontrib-bibtex-2.4.1/src/sphinxcontrib/bibtex/style/referencing/extra_label.py000066400000000000000000000015171411661013000311010ustar00rootroot00000000000000import dataclasses from sphinxcontrib.bibtex.style.template import reference, entry_label from typing import TYPE_CHECKING, List, Iterable from . import BaseReferenceStyle, BracketStyle if TYPE_CHECKING: from pybtex.richtext import BaseText from pybtex.style.template import Node @dataclasses.dataclass class ExtraLabelReferenceStyle(BaseReferenceStyle): """Reference just by label.""" #: Bracket style. bracket: BracketStyle = BracketStyle() def role_names(self) -> Iterable[str]: return ['label', 'labelpar'] def outer(self, role_name: str, children: List["BaseText"]) -> "Node": return self.bracket.outer( children, brackets='par' in role_name, capfirst=False, ) def inner(self, role_name: str) -> "Node": return reference[entry_label] sphinxcontrib-bibtex-2.4.1/src/sphinxcontrib/bibtex/style/referencing/extra_year.py000066400000000000000000000014751411661013000307650ustar00rootroot00000000000000import dataclasses from typing import TYPE_CHECKING, List, Iterable from sphinxcontrib.bibtex.style.template import reference, year from . import BaseReferenceStyle, BracketStyle if TYPE_CHECKING: from pybtex.richtext import BaseText from pybtex.style.template import Node @dataclasses.dataclass class ExtraYearReferenceStyle(BaseReferenceStyle): """Reference just by year.""" #: Bracket style. bracket: BracketStyle = BracketStyle() def role_names(self) -> Iterable[str]: return ['year', 'yearpar'] def outer(self, role_name: str, children: List["BaseText"]) -> "Node": return self.bracket.outer( children, brackets='par' in role_name, capfirst=False, ) def inner(self, role_name: str) -> "Node": return reference[year] sphinxcontrib-bibtex-2.4.1/src/sphinxcontrib/bibtex/style/referencing/foot.py000066400000000000000000000021441411661013000275630ustar00rootroot00000000000000import dataclasses from typing import Union, TYPE_CHECKING from . import PersonStyle, GroupReferenceStyle, BracketStyle from .basic_foot import ( BasicFootParentheticalReferenceStyle, BasicFootTextualReferenceStyle, ) if TYPE_CHECKING: from pybtex.richtext import BaseText @dataclasses.dataclass class FootReferenceStyle(GroupReferenceStyle): """Textual or parenthetical reference using footnotes.""" #: Bracket style for textual citations (:cite:t: and variations). bracket_textual: BracketStyle = BracketStyle() #: Person style (applies to all relevant citation commands). person: PersonStyle = PersonStyle() #: Separator between text and reference for textual citations. text_reference_sep: Union["BaseText", str] = '' def __post_init__(self): self.styles.extend([ BasicFootParentheticalReferenceStyle(), BasicFootTextualReferenceStyle( bracket=self.bracket_textual, person=self.person, text_reference_sep=self.text_reference_sep, ), ]) super().__post_init__() sphinxcontrib-bibtex-2.4.1/src/sphinxcontrib/bibtex/style/referencing/label.py000066400000000000000000000043031411661013000276720ustar00rootroot00000000000000import dataclasses from typing import Union, TYPE_CHECKING from sphinxcontrib.bibtex.style.referencing import ( BracketStyle, PersonStyle, GroupReferenceStyle ) from .basic_label import ( BasicLabelParentheticalReferenceStyle, BasicLabelTextualReferenceStyle, ) from .extra_author import ExtraAuthorReferenceStyle from .extra_label import ExtraLabelReferenceStyle from .extra_year import ExtraYearReferenceStyle from .extra_empty import ExtraEmptyReferenceStyle if TYPE_CHECKING: from pybtex.richtext import BaseText @dataclasses.dataclass class LabelReferenceStyle(GroupReferenceStyle): """Textual or parenthetical reference by label, or just by author, label, or year. """ #: Bracket style for textual citations (:cite:t: and variations). bracket_textual: BracketStyle = BracketStyle() #: Bracket style for parenthetical citations #: (:cite:p: and variations). bracket_parenthetical: BracketStyle = BracketStyle() #: Bracket style for author citations #: (:cite:author: and variations). bracket_author: BracketStyle = BracketStyle() #: Bracket style for label citations #: (:cite:label: and variations). bracket_label: BracketStyle = BracketStyle() #: Bracket style for year citations #: (:cite:year: and variations). bracket_year: BracketStyle = BracketStyle() #: Person style. person: PersonStyle = PersonStyle() #: Separator between text and reference for textual citations. text_reference_sep: Union["BaseText", str] = ' ' def __post_init__(self): self.styles.extend([ BasicLabelParentheticalReferenceStyle( bracket=self.bracket_parenthetical, person=self.person), BasicLabelTextualReferenceStyle( bracket=self.bracket_textual, person=self.person, text_reference_sep=self.text_reference_sep, ), ExtraAuthorReferenceStyle( bracket=self.bracket_author, person=self.person), ExtraLabelReferenceStyle(bracket=self.bracket_label), ExtraYearReferenceStyle(bracket=self.bracket_year), ExtraEmptyReferenceStyle(), ]) super().__post_init__() sphinxcontrib-bibtex-2.4.1/src/sphinxcontrib/bibtex/style/referencing/super_.py000066400000000000000000000044271411661013000301170ustar00rootroot00000000000000import dataclasses from typing import Union, TYPE_CHECKING from sphinxcontrib.bibtex.style.referencing import ( BracketStyle, PersonStyle, GroupReferenceStyle ) from .basic_super import ( BasicSuperParentheticalReferenceStyle, BasicSuperTextualReferenceStyle, ) from .extra_author import ExtraAuthorReferenceStyle from .extra_label import ExtraLabelReferenceStyle from .extra_year import ExtraYearReferenceStyle from .extra_empty import ExtraEmptyReferenceStyle if TYPE_CHECKING: from pybtex.richtext import BaseText @dataclasses.dataclass class SuperReferenceStyle(GroupReferenceStyle): """Textual or parenthetical reference by superscripted label, or just by author, label, or year. """ #: Bracket style for textual citations (:cite:t: and variations). bracket_textual: BracketStyle = BracketStyle( left='', right='', sep=', ') #: Bracket style for parenthetical citations #: (:cite:p: and variations). bracket_parenthetical: BracketStyle = BracketStyle( left='', right='', sep=',') #: Bracket style for author citations #: (:cite:author: and variations). bracket_author: BracketStyle = BracketStyle() #: Bracket style for label citations #: (:cite:label: and variations). bracket_label: BracketStyle = BracketStyle() #: Bracket style for year citations #: (:cite:year: and variations). bracket_year: BracketStyle = BracketStyle() #: Person style. person: PersonStyle = PersonStyle() #: Separator between text and reference for textual citations. text_reference_sep: Union["BaseText", str] = '' def __post_init__(self): self.styles.extend([ BasicSuperParentheticalReferenceStyle( bracket=self.bracket_parenthetical, person=self.person), BasicSuperTextualReferenceStyle( bracket=self.bracket_textual, person=self.person, text_reference_sep=self.text_reference_sep, ), ExtraAuthorReferenceStyle( bracket=self.bracket_author, person=self.person), ExtraLabelReferenceStyle(bracket=self.bracket_label), ExtraYearReferenceStyle(bracket=self.bracket_year), ExtraEmptyReferenceStyle(), ]) super().__post_init__() sphinxcontrib-bibtex-2.4.1/src/sphinxcontrib/bibtex/style/template.py000066400000000000000000000113001411661013000261320ustar00rootroot00000000000000""" .. autofunction:: sphinxcontrib.bibtex.style.template.join(\ sep='', sep2=None, last_sep=None, other=None) .. autofunction:: sphinxcontrib.bibtex.style.template.sentence(\ capfirst=False, capitalize=False, add_period=True, \ sep=', ', sep2=None, last_sep=None, other=None) .. autofunction:: sphinxcontrib.bibtex.style.template.names(\ role, sep='', sep2=None, last_sep=None, other=None) .. autofunction:: sphinxcontrib.bibtex.style.template.entry_label() .. autofunction:: sphinxcontrib.bibtex.style.template.reference() """ from pybtex.richtext import Text from pybtex.style.template import ( Node, _format_list, FieldIsMissing, field, first_of, optional, tag ) from typing import TYPE_CHECKING, Dict, Any, cast, Type from sphinxcontrib.bibtex.richtext import BaseReferenceText if TYPE_CHECKING: from pybtex.richtext import BaseText from pybtex.style import FormattedEntry # extended from pybtex: also copies the docstring into the wrapped object def node(f): n = Node(f.__name__, f) n.__doc__ = f.__doc__ return n # copied from pybtex join but extended to allow "et al" formatting @node def join(children, data, sep='', sep2=None, last_sep=None, other=None): """Join text fragments together.""" if sep2 is None: sep2 = sep if last_sep is None: last_sep = sep parts = [part for part in _format_list(children, data) if part] if len(parts) <= 1: return Text(*parts) elif len(parts) == 2: return Text(sep2).join(parts) elif other is None: return Text(last_sep).join([Text(sep).join(parts[:-1]), parts[-1]]) else: return Text(parts[0], other) # copied from pybtex names but using the new join @node def sentence(children, data, capfirst=False, capitalize=False, add_period=True, sep=', ', sep2=None, last_sep=None, other=None): """Join text fragments, capitalize the first letter, and add a period to the end. """ text = join(sep=sep, sep2=sep2, last_sep=last_sep, other=other)[ children ].format_data(data) if capfirst: text = text.capfirst() if capitalize: text = text.capitalize() if add_period: text = text.add_period() return text # copied from pybtex names but using the new join allowing "et al" formatting @node def names(children, data, role, **kwargs): """Return formatted names.""" assert not children try: persons = data['entry'].persons[role] except KeyError: raise FieldIsMissing(role, data['entry']) style = data['style'] formatted_names = [ style.person.style_plugin.format(person, style.person.abbreviate) for person in persons] return join(**kwargs)[formatted_names].format_data(data) @node def entry_label(children, data) -> "BaseText": """Node for inserting the label of a formatted entry.""" assert not children entry = cast("FormattedEntry", data['formatted_entry']) return Text(entry.label) @node def reference(children, data: Dict[str, Any]): """Node for inserting a citation reference. The children of the node comprise the content of the reference, and any referencing information is stored in the *reference_info* key of the *data*. The data must also contain a *style* key pointing to the corresponding :class:`~sphinxcontrib.bibtex.style.referencing.BaseReferenceStyle`. """ parts = _format_list(children, data) info = data['reference_info'] reference_text_class: Type[BaseReferenceText] \ = data['reference_text_class'] return reference_text_class(info, *parts) @node def footnote_reference(children, data: Dict[str, Any]): """Node for inserting a footnote reference. The children of the node comprise the content of the reference, and any referencing information is stored in the *reference_info* key of the *data*. The data must also contain a *style* key pointing to the corresponding :class:`~sphinxcontrib.bibtex.style.referencing.BaseReferenceStyle`. """ assert not children info = data['reference_info'] reference_text_class: Type[BaseReferenceText] \ = data['reference_text_class'] # we need to give the footnote text some fake content # otherwise pybtex richtext engine will mess things up return reference_text_class(info, '#') @node def year(children, data: Dict[str, Any]) -> "BaseText": assert not children return first_of[optional[field('year')], 'n.d.'].format_data(data) @node def author_or_editor_or_title(children, data, **kwargs): assert not children return first_of[ optional[names('author', **kwargs)], optional[names('editor', **kwargs)], tag('em')[field('title')]].format_data(data) sphinxcontrib-bibtex-2.4.1/src/sphinxcontrib/bibtex/transforms.py000066400000000000000000000112301411661013000253570ustar00rootroot00000000000000""" .. autoclass:: BibliographyTransform :show-inheritance: .. autoattribute:: default_priority .. automethod:: run """ import docutils.nodes from typing import TYPE_CHECKING, cast from pybtex.plugin import find_plugin from sphinx.transforms.post_transforms import SphinxPostTransform from sphinx.util.logging import getLogger from .directives import BibliographyKey from .nodes import bibliography as bibliography_node if TYPE_CHECKING: from sphinx.environment import BuildEnvironment from .domain import BibtexDomain logger = getLogger(__name__) def node_text_transform(node: docutils.nodes.Element) -> None: """Apply extra text transformations to a node.""" for child, next_child in zip(node.children[:], node.children[1:] + [None]): if isinstance(child, docutils.nodes.Text): if (child.endswith(r'\url ') and isinstance(next_child, docutils.nodes.Text)): node.replace(child, docutils.nodes.Text(child[:-5])) ref_node = docutils.nodes.reference(refuri=next_child.astext()) ref_node += next_child node.replace(next_child, ref_node) else: node_text_transform(child) class BibliographyTransform(SphinxPostTransform): """A docutils transform to generate citation entries for bibliography nodes. """ # transform must be applied before sphinx runs its ReferencesResolver # which has priority 10, so when ReferencesResolver calls the cite domain # resolve_xref, the target is present and all will work fine default_priority = 5 backend = find_plugin('pybtex.backends', 'docutils')() def run(self, **kwargs): """Transform each :class:`~sphinxcontrib.bibtex.nodes.bibliography` node into a list of citations. """ env = cast("BuildEnvironment", self.document.settings.env) domain = cast("BibtexDomain", env.get_domain('cite')) for bibnode in self.document.traverse(bibliography_node): # reminder: env.docname may be equal to 'index' instead of # bibnode['docname'] in post-transform phase (e.g. latex builder) bib_key = BibliographyKey( docname=bibnode['docname'], id_=bibnode['ids'][0]) bibliography = domain.bibliographies[bib_key] citations = [citation for citation in domain.citations if citation.bibliography_key == bib_key] # create citation nodes for all references if bibliography.list_ == "enumerated": nodes = docutils.nodes.enumerated_list() nodes['enumtype'] = bibliography.enumtype if bibliography.start >= 1: nodes['start'] = bibliography.start env.temp_data['bibtex_enum_count'] = bibliography.start else: nodes['start'] = env.temp_data.setdefault( 'bibtex_enum_count', 1) elif bibliography.list_ == "bullet": nodes = docutils.nodes.bullet_list() else: # "citation" nodes = [] for citation in citations: citation_node = bibliography.citation_nodes[citation.key] if bibliography.list_ in {"enumerated", "bullet"}: citation_node += self.backend.paragraph( citation.formatted_entry) else: # "citation" # backrefs only supported in same document backrefs = [ citation_ref.citation_ref_id for citation_ref in domain.citation_refs if bib_key.docname == citation_ref.docname and citation.key in citation_ref.keys] if backrefs: citation_node['backrefs'] = backrefs citation_node += docutils.nodes.label( '', citation.formatted_entry.label, support_smartquotes=False) citation_node += self.backend.paragraph( citation.formatted_entry) citation_node['docname'] = bib_key.docname node_text_transform(citation_node) nodes.append(citation_node) if bibliography.list_ == "enumerated": env.temp_data['bibtex_enum_count'] += 1 if citations: final_node = domain.bibliography_header.deepcopy() final_node += nodes bibnode.replace_self(final_node) else: bibnode.replace_self(docutils.nodes.target()) sphinxcontrib-bibtex-2.4.1/test/000077500000000000000000000000001411661013000166335ustar00rootroot00000000000000sphinxcontrib-bibtex-2.4.1/test/__init__.py000066400000000000000000000000001411661013000207320ustar00rootroot00000000000000sphinxcontrib-bibtex-2.4.1/test/common.py000066400000000000000000000061031411661013000204750ustar00rootroot00000000000000"""Some common helper functions for the test suite.""" import re import sphinx RE_ID = r'[a-z][-?a-z0-9]*' RE_NUM = r'\d+' RE_LABEL = r'[^<]+' RE_TEXT = r'.*' RE_DOCNAME = r'[^:]+' RE_TITLE = r'[^"]*' def html_citation_refs(refid=RE_ID, label=RE_LABEL, title=RE_TITLE): return re.compile( r'' r'(?P'.format(refid=refid, label=label, title=title)) def html_citations(id_=RE_ID, label=RE_LABEL, text=RE_TEXT): return re.compile( r'
' r'' r'(?:)?' r'(?P)?' r'' r'(?:\(' r'1' r',2' r'(,3)?' r'(,\d+)*' # no named group for additional backrefs r'\))?' r'
\n' r'

(?P{text})

\n
'.format( id_=id_, label=label, text=text, backref_id=RE_ID)) def html_footnote_refs(refid=RE_ID): return re.compile( r'' r'(?P'.format(refid=refid, id_=RE_ID, label=RE_NUM)) def html_footnotes(id_=RE_ID, text=RE_TEXT): return re.compile( r'
' r'' r'(?:)?' r'(?P)?' r'' r'(?:\(' r'1' r',2' r'(,3)?' r'(,\d+)*' # no named group for additional backrefs r'\))?' r'
\n' r'

(?P{text})

\n
'.format( id_=id_, backref_id=RE_ID, label=RE_NUM, text=text)) def latex_citations(docname=RE_DOCNAME, id_=RE_ID, label=RE_LABEL, text=RE_TEXT): if sphinx.version_info < (3, 5): return re.compile( r'\\bibitem\[(?P