Project: restructuredtext-lint

reStructuredText linter

Project Details

Latest version
1.4.0
Home Page
https://github.com/twolfson/restructuredtext-lint
PyPI Page
https://pypi.org/project/restructuredtext-lint/

Project Popularity

PageRank
0.0026856873635110402
Number of downloads
222579

restructuredtext-lint

.. image:: https://travis-ci.org/twolfson/restructuredtext-lint.png?branch=master :target: https://travis-ci.org/twolfson/restructuredtext-lint :alt: Build Status

reStructuredText_ linter_

This was created out of frustration with PyPI; it sucks finding out your reST is invalid after uploading it. It is being developed in junction with a Sublime Text_ linter.

.. _reStructuredText: http://docutils.sourceforge.net/rst.html .. linter: http://en.wikipedia.org/wiki/Lint%28software%29 .. reST: reStructuredText .. _PyPI: http://pypi.python.org/ .. _Sublime Text: http://sublimetext.com/

Getting Started

Install the module with: pip install restructuredtext_lint

.. code:: python

import restructuredtext_lint
errors = restructuredtext_lint.lint("""
Hello World
=======
""")

# `errors` will be list of system messages
# [<system_message: <paragraph...><literal_block...>>]
errors[0].message  # Title underline too short.

CLI Utility ^^^^^^^^^^^ For your convenience, we present a CLI utility rst-lint (also available as restructuredtext-lint).

.. code:: console

$ rst-lint --help
usage: rst-lint [-h] [--version] [--format {text,json}] [--encoding ENCODING]
                [--level {debug,info,warning,error,severe}]
                [--rst-prolog RST_PROLOG]
                path [path ...]

Lint reStructuredText files. Returns 0 if all files pass linting, 1 for an
internal error, and 2 if linting failed.

positional arguments:
  path                  File/folder to lint

optional arguments:
  -h, --help            show this help message and exit
  --version             show program's version number and exit
  --format {text,json}  Format of the output (default: "text")
  --encoding ENCODING   Encoding of the input file (e.g. "utf-8")
  --level {debug,info,warning,error,severe}
                        Minimum error level to report (default: "warning")
  --rst-prolog RST_PROLOG
                        reStructuredText content to prepend to all files
                        (useful for substitutions)

$ rst-lint README.rst
WARNING README.rst:2 Title underline too short.

Other tools ^^^^^^^^^^^ restructuredtext-lint is also integrated in other tools. A list can be found and updated in our wiki

https://github.com/twolfson/restructuredtext-lint/wiki/Integration-in-other-tools

PyPI issues ^^^^^^^^^^^ While a document may lint cleanly locally, there can be issues when submitted it to PyPI_. Here are some common problems:

  • Usage of non-builtin lexers (e.g. bibtex) will pass locally but not be recognized/parsable on PyPI_

    • This is due to PyPI_ not having a non-builtin lexer installed
    • Please avoid non-builtin lexers to avoid complications
    • For more information, see #27_
  • Relative hyperlinks will not work (e.g. ./UNLICENSE)

    • According to Stack Overflow, hyperlinks must use a scheme (e.g. http, https) and that scheme must be whitelisted

      • http://stackoverflow.com/a/16594755
    • Please use absolute hyperlinks (e.g. https://github.com/twolfson/restructuredtext-lint/blob/master/UNLICENSE)

.. _#27: https://github.com/twolfson/restructuredtext-lint/issues/27

Documentation

restructuredtext-lint exposes a lint and lint_file function

restructuredtext_lint.lint(content, filepath=None, rst_prolog=None) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Lint reStructuredText_ and return errors

  • content String - reStructuredText_ to be linted
  • filepath String - Optional path to file, this will be returned as the source
  • rst_prolog String - Optional content to prepend to content, line numbers will be offset to ignore this

Returns:

  • errors List - List of errors

    • Each error is a class from docutils_ with the following attrs

      • line Integer|None - Line where the error occurred

        • On rare occasions, this will be None (e.g. anonymous link mismatch)
      • source String - filepath provided in parameters

      • level Integer - Level of the warning

        • Levels represent 'info': 1, 'warning': 2, 'error': 3, 'severe': 4
      • type String - Noun describing the error level

        • Levels can be 'INFO', 'WARNING', 'ERROR', or 'SEVERE'
      • message String - Error message

      • full_message String - Error message and source lines where the error occurred

    • It should be noted that level, type, message, and full_message are custom attrs added onto the original system_message

.. _docutils: http://docutils.sourceforge.net/

restructuredtext_lint.lint_file(filepath, encoding=None, *args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Lint a reStructuredText_ file and return errors

  • filepath String - Path to file for linting

  • encoding String - Encoding to read file in as

    • When None is provided, it will use OS default as provided by locale.getpreferredencoding_
    • The list of supported encodings can be found at http://docs.python.org/2/library/codecs.html#standard-encodings
  • *args - Additional arguments to be passed to lint

  • **kwargs - Additional keyword arguments to be passed to lint

.. _locale.getpreferredencoding: http://docs.python.org/2/library/locale.html#locale.getpreferredencoding

Returns: Same structure as restructuredtext_lint.lint

Extension

Under the hood, we leverage docutils_ for parsing reStructuredText documents. docutils_ supports adding new directives and roles via register_directive and register_role.

Sphinx ^^^^^^ Unfortunately due to customizations in Sphinx's parser_ we cannot include all of its directives/roles (see #29). However, we can include some of them as one-offs. Here is an example of adding a directive from Sphinx.

.. _Sphinx: http://sphinx-doc.org/ .. Sphinx's parser: Sphinx .. _#29: https://github.com/twolfson/restructuredtext-lint/issues/29#issuecomment-243456787

https://github.com/sphinx-doc/sphinx/blob/1.3/sphinx/directives/code.py

sphinx.rst

.. code:: rst

Hello
=====
World

.. highlight:: python

    Hello World!

sphinx.py

.. code:: python

# Load in our dependencies
from docutils.parsers.rst.directives import register_directive
from sphinx.directives.code import Highlight
import restructuredtext_lint

# Load our new directive
register_directive('highlight', Highlight)

# Lint our README
errors = restructuredtext_lint.lint_file('docs/sphinx/README.rst')
print errors[0].message # Error in "highlight" directive: no content permitted.

Examples

Here is an example of all invalid properties

.. code:: python

rst = """
Some content.

Hello World
=======
Some more content!
"""
errors = restructuredtext_lint.lint(rst, 'myfile.py')
errors[0].line  # 5
errors[0].source  # myfile.py
errors[0].level  # 2
errors[0].type  # WARNING
errors[0].message  # Title underline too short.
errors[0].full_message  # Title underline too short.
                        #
                        # Hello World
                        # =======

Contributing

In lieu of a formal styleguide, take care to maintain the existing coding style. Add unit tests for any new or changed functionality. Test via nosetests.

Donating

Support this project and others by twolfson_ via donations_.

http://twolfson.com/support-me

.. _others by twolfson: http://twolfson.com/projects .. _donations: http://twolfson.com/support-me

Unlicense

As of Nov 22 2013, Todd Wolfson has released this repository and its contents to the public domain.

It has been released under the UNLICENSE_.

.. _UNLICENSE: https://github.com/twolfson/restructuredtext-lint/blob/master/UNLICENSE