From 414922d08e1cd9a61200d0b0485156136070c8e8 Mon Sep 17 00:00:00 2001 From: Ian Cordasco Date: Sun, 8 May 2016 14:02:40 -0500 Subject: [PATCH] Add documentation around the cli --- docs/source/index.rst | 1 + docs/source/internal/cli.rst | 26 ++++++++++++ flake8/main/cli.py | 78 +++++++++++++++++++++++++++++++++--- tox.ini | 1 + 4 files changed, 101 insertions(+), 5 deletions(-) create mode 100644 docs/source/internal/cli.rst diff --git a/docs/source/index.rst b/docs/source/index.rst index c8a4f35..4d35951 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -27,6 +27,7 @@ Developer Guide .. toctree:: :maxdepth: 2 + internal/cli internal/formatters internal/option_handling internal/plugin_handling diff --git a/docs/source/internal/cli.rst b/docs/source/internal/cli.rst new file mode 100644 index 0000000..fc696bc --- /dev/null +++ b/docs/source/internal/cli.rst @@ -0,0 +1,26 @@ +Command Line Interface +====================== + +The command line interface of Flake8 is modeled as an application via +:class:`~flake8.main.cli.Application`. When a user runs ``flake8`` at their +command line, :func:`~flake8.main.cli.main` is run which handles +management of the application. + +User input is parsed *twice* to accomodate logging and verbosity options +passed by the user as early as possible so as much logging can be produced as +possible. + +The default flake8 options are registered by +:func:`~flake8.main.cli.register_default_options`. Trying to register these +options in plugins will result in errors. + + +API Documentation +----------------- + +.. autofunction:: flake8.main.cli.main + +.. autoclass:: flake8.main.cli.Application + :members: + +.. autofunction:: flake8.main.cli.register_default_options diff --git a/flake8/main/cli.py b/flake8/main/cli.py index 1208bfc..7c9c39f 100644 --- a/flake8/main/cli.py +++ b/flake8/main/cli.py @@ -15,7 +15,32 @@ LOG = logging.getLogger(__name__) def register_default_options(option_manager): - """Register the default options on our OptionManager.""" + """Register the default options on our OptionManager. + + The default options include: + + - ``-v``/``--verbose`` + - ``-q``/``--quiet`` + - ``--count`` + - ``--diff`` + - ``--exclude`` + - ``--filename`` + - ``--format`` + - ``--hang-closing`` + - ``--ignore`` + - ``--max-line-length`` + - ``--select`` + - ``--disable-noqa`` + - ``--show-source`` + - ``--statistics`` + - ``--enabled-extensions`` + - ``--exit-zero`` + - ``-j``/``--jobs`` + - ``--output-file`` + - ``--append-config`` + - ``--config`` + - ``--isolated`` + """ add_option = option_manager.add_option # pep8 options @@ -175,8 +200,12 @@ class Application(object): :param str version: The version of the program/application we're executing. """ + #: The name of the program being run self.program = program + #: The version of the program being run self.version = version + #: The instance of :class:`flake8.options.manager.OptionManager` used + #: to parse and handle the options and arguments passed by the user self.option_manager = manager.OptionManager( prog='flake8', version=flake8.__version__ ) @@ -187,16 +216,31 @@ class Application(object): flake8.configure_logging(preliminary_opts.verbose, preliminary_opts.output_file) + #: The instance of :class:`flake8.plugins.manager.Checkers` self.check_plugins = None + #: The instance of :class:`flake8.plugins.manager.Listeners` self.listening_plugins = None + #: The instance of :class:`flake8.plugins.manager.ReportFormatters` self.formatting_plugins = None + #: The user-selected formatter from :attr:`formatting_plugins` self.formatter = None + #: The :class:`flake8.plugins.notifier.Notifier` for listening plugins self.listener_trie = None + #: The :class:`flake8.style_guide.StyleGuide` built from the user's + #: options self.guide = None + #: The :class:`flake8.checker.Manager` that will handle running all of + #: the checks selected by the user. self.file_checker_manager = None + #: The user-supplied options parsed into an instance of + #: :class:`optparse.Values` self.options = None + #: The left over arguments that were not parsed by + #: :attr:`option_manager` self.args = None + #: The number of errors, warnings, and other messages after running + #: flake8 self.result_count = 0 def exit(self): @@ -214,7 +258,14 @@ class Application(object): def find_plugins(self): # type: () -> NoneType - """Find and load the plugins for this application.""" + """Find and load the plugins for this application. + + If :attr:`check_plugins`, :attr:`listening_plugins`, or + :attr:`formatting_plugins` are ``None`` then this method will update + them with the appropriate plugin manager instance. Given the expense + of finding plugins (via :mod:`pkg_resources`) we want this to be + idempotent and so only update those attributes if they are ``None``. + """ if self.check_plugins is None: self.check_plugins = plugin_manager.Checkers() @@ -280,7 +331,12 @@ class Application(object): def run_checks(self): # type: () -> NoneType - """Run the actual checks with the FileChecker Manager.""" + """Run the actual checks with the FileChecker Manager. + + This method encapsulates the logic to make a + :class:`~flake8.checker.Manger` instance run the checks it is + managing. + """ self.file_checker_manager.start() self.file_checker_manager.run() LOG.info('Finished running') @@ -288,11 +344,16 @@ class Application(object): def report_errors(self): # type: () -> NoneType - """Report all the errors found by flake8 3.0.""" + """Report all the errors found by flake8 3.0. + + This also updates the :attr:`result_count` attribute with the total + number of errors, warnings, and other messages found. + """ LOG.info('Reporting errors') self.result_count = self.file_checker_manager.report() def _run(self, argv): + # type: (Union[NoneType, List[str]]) -> NoneType self.find_plugins() self.register_plugin_options() self.parse_configuration_and_cli(argv) @@ -321,7 +382,14 @@ class Application(object): def main(argv=None): # type: (Union[NoneType, List[str]]) -> NoneType - """Main entry-point for the flake8 command-line tool.""" + """Main entry-point for the flake8 command-line tool. + + This handles the creation of an instance of :class:`Application`, runs it, + and then exits the application. + + :param list argv: + The arguments to be passed to the application for parsing. + """ app = Application() app.run(argv) app.exit() diff --git a/tox.ini b/tox.ini index cd56e86..d93448f 100644 --- a/tox.ini +++ b/tox.ini @@ -76,6 +76,7 @@ commands = [testenv:docs] deps = sphinx>=1.3.0 + sphinx_rtd_theme commands = sphinx-build -E -W -c docs/source/ -b html docs/source/ docs/build/html