From d92322a574e49c0aec393beaeda1d41adb23eca5 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Fri, 11 Oct 2013 19:47:40 -0300 Subject: [PATCH] added plugins_index documentation and generated plugins_index file --HG-- branch : plugins-index --- doc/en/plugins_index.py | 113 ++++++++++++++++++++++++++------------- doc/en/plugins_index.txt | 61 +++++++++++++++++++++ 2 files changed, 138 insertions(+), 36 deletions(-) create mode 100644 doc/en/plugins_index.txt diff --git a/doc/en/plugins_index.py b/doc/en/plugins_index.py index 8a31a6d73..0e6caa1ec 100644 --- a/doc/en/plugins_index.py +++ b/doc/en/plugins_index.py @@ -1,4 +1,11 @@ +''' +Script to generate the file `plugins_index.txt` with information about pytest plugins taken directly +from a live pypi server. + +This will evolve to include test compatibility (pythons and pytest versions) information also. +''' from collections import namedtuple +import datetime from distutils.version import LooseVersion import itertools import os @@ -7,10 +14,16 @@ import xmlrpclib #=================================================================================================== -# iter_pypi_plugins +# iter_plugins #=================================================================================================== -def iter_pypi_plugins(client): - for plug_data in client.search({'name' : 'pytest-'}): +def iter_plugins(client, search='pytest-'): + ''' + Returns an iterator of (name, version) from pypi. + + :param client: xmlrpclib.ServerProxy + :param search: package names to search for + ''' + for plug_data in client.search({'name' : search}): yield plug_data['name'], plug_data['version'] @@ -18,6 +31,11 @@ def iter_pypi_plugins(client): # get_latest_versions #=================================================================================================== def get_latest_versions(plugins): + ''' + Returns an iterator of (name, version) from the given list of (name, version), but returning + only the latest version of the package. Uses distutils.LooseVersion to ensure compatibility + with PEP386. + ''' plugins = [(name, LooseVersion(version)) for (name, version) in plugins] for name, grouped_plugins in itertools.groupby(plugins, key=lambda x: x[0]): name, loose_version = list(grouped_plugins)[-1] @@ -28,19 +46,27 @@ def get_latest_versions(plugins): # obtain_plugins_table #=================================================================================================== def obtain_plugins_table(plugins, client): + ''' + Returns information to populate a table of plugins, their versions, authors, etc. + + The returned information is a list of columns of `ColumnData` namedtuples(text, link). Link + can be None if the text for that column should not be linked to anything. + + :param plugins: list of (name, version) + :param client: xmlrpclib.ServerProxy + + ''' rows = [] - RowData = namedtuple('RowData', 'text link') + ColumnData = namedtuple('ColumnData', 'text link') headers = ['Name', 'Version', 'Author', 'Summary'] - # pluginname and latest version, pypi link, maintainer/author, repository link, - # one-line description, test status py27/py33 for package_name, version in plugins: release_data = client.release_data(package_name, version) row = ( - RowData(package_name, release_data['package_url']), - RowData(version, release_data['release_url']), - RowData(release_data['author'], release_data['author_email']), - RowData(release_data['summary'], None), + ColumnData(package_name, release_data['package_url']), + ColumnData(version, release_data['release_url']), + ColumnData(release_data['author'], release_data['author_email']), + ColumnData(release_data['summary'], None), ) assert len(row) == len(headers) rows.append(row) @@ -51,56 +77,71 @@ def obtain_plugins_table(plugins, client): #=================================================================================================== # generate_plugins_index_from_table #=================================================================================================== -def generate_plugins_index_from_table(headers, rows, basename): +def generate_plugins_index_from_table(filename, headers, rows): + ''' + Generates a RST file with the table data given. + + :param filename: output filename + :param headers: see `obtain_plugins_table` + :param rows: see `obtain_plugins_table` + ''' + # creates a list of rows, each being a str containing appropriate column text and link + table_texts = [] + for row in rows: + column_texts = [] + for i, col_data in enumerate(row): + text = '`%s <%s>`_' % (col_data.text, col_data.link) if col_data.link else col_data.text + column_texts.append(text) + table_texts.append(column_texts) + # compute max length of each column so we can build the rst table + column_lengths = [len(x) for x in headers] + for column_texts in table_texts: + for i, row_text in enumerate(column_texts): + column_lengths[i] = max(column_lengths[i], len(row_text) + 2) + def get_row_limiter(char): return ' '.join(char * length for length in column_lengths) - def ref(s, link): - return s + '_' if link else s - - table_texts = [] - for row in rows: - row_texts = [] - for i, row_data in enumerate(row): - text = '`%s <%s>`_' % (row_data.text, row_data.link) if row_data.link else row_data.text - row_texts.append(text) - table_texts.append(row_texts) - - column_lengths = [len(x) for x in headers] - for row_texts in table_texts: - for i, row_text in enumerate(row_texts): - column_lengths[i] = max(column_lengths[i], len(row_text) + 2) - - with file(basename, 'w') as f: + with file(filename, 'w') as f: + # write welcome print >> f, '.. _plugins_index:' print >> f print >> f, 'List of Third-Party Plugins' print >> f, '===========================' print >> f - print >> f + + # table print >> f, get_row_limiter('=') for i, header in enumerate(headers): print >> f, '{:^{fill}}'.format(header, fill=column_lengths[i]), print >> f print >> f, get_row_limiter('=') - for row_texts in table_texts: - for i, row_text in enumerate(row_texts): + for column_texts in table_texts: + for i, row_text in enumerate(column_texts): print >> f, '{:^{fill}}'.format(row_text, fill=column_lengths[i]), print >> f print >> f print >> f, get_row_limiter('=') print >> f + + print >> f, '*(Last updated: %s)*' % datetime.date.today().strftime('%Y-%m-%d') #=================================================================================================== # generate_plugins_index #=================================================================================================== -def generate_plugins_index(client, basename): - plugins = get_latest_versions(iter_pypi_plugins(client)) +def generate_plugins_index(client, filename): + ''' + Generates an RST file with a table of the latest pytest plugins found in pypi. + + :param client: xmlrpclib.ServerProxy + :param filename: output filename + ''' + plugins = get_latest_versions(iter_plugins(client)) headers, rows = obtain_plugins_table(plugins, client) - generate_plugins_index_from_table(headers, rows, basename) + generate_plugins_index_from_table(filename, headers, rows) #=================================================================================================== @@ -108,8 +149,8 @@ def generate_plugins_index(client, basename): #=================================================================================================== def main(argv): client = xmlrpclib.ServerProxy('http://pypi.python.org/pypi') - basename = os.path.join(os.path.dirname(__file__), 'plugins_index.txt') - generate_plugins_index(client, basename) + filename = os.path.join(os.path.dirname(__file__), 'plugins_index.txt') + generate_plugins_index(client, filename) print 'OK' return 0 diff --git a/doc/en/plugins_index.txt b/doc/en/plugins_index.txt new file mode 100644 index 000000000..a73044839 --- /dev/null +++ b/doc/en/plugins_index.txt @@ -0,0 +1,61 @@ +.. _plugins_index: + +List of Third-Party Plugins +=========================== + +================================================================================== ============================================================================ ==================================================================================== ============================================================================================================================================= + Name Version Author Summary +================================================================================== ============================================================================ ==================================================================================== ============================================================================================================================================= + `pytest-bdd `_ `0.6.1 `_ `Oleg Pidsadnyi `_ BDD for pytest + `pytest-bdd-splinter `_ `0.5.2 `_ `Oleg Pidsadnyi `_ Splinter subplugin for Pytest BDD plugin + `pytest-bench `_ `0.1.0 `_ `Concordus Applications `_ Benchmark utility that plugs into pytest. + `pytest-blockage `_ `0.1 `_ `UNKNOWN `_ Disable network requests during a test run. + `pytest-browsermob-proxy `_ `0.1 `_ `Dave Hunt `_ BrowserMob proxy plugin for py.test. + `pytest-bugzilla `_ `0.2 `_ `Noufal Ibrahim `_ py.test bugzilla integration plugin + `pytest-cache `_ `1.0 `_ `Holger Krekel `_ pytest plugin with mechanisms for caching across test runs + `pytest-capturelog `_ `0.7 `_ `Meme Dough `_ py.test plugin to capture log messages + `pytest-codecheckers `_ `0.2 `_ `Ronny Pfannschmidt `_ pytest plugin to add source code sanity checks (pep8 and friends) + `pytest-contextfixture `_ `0.1.1 `_ `Andreas Pelme `_ Define pytest fixtures as context managers. + `pytest-couchdbkit `_ `0.5.1 `_ `RonnyPfannschmidt `_ py.test extension for per-test couchdb databases using couchdbkit + `pytest-cov `_ `1.6 `_ `Meme Dough `_ py.test plugin for coverage reporting with support for both centralised and distributed testing, including subprocesses and multiprocessing + `pytest-dbfixtures `_ `0.3.8.3 `_ `Clearcode - The A Room `_ dbfixtures plugin for py.test. + `pytest-django `_ `2.3.1 `_ `Andreas Pelme `_ A Django plugin for py.test. + `pytest-django-lite `_ `0.1.0 `_ `David Cramer `_ The bare minimum to integrate py.test with Django. + `pytest-figleaf `_ `1.0 `_ `holger krekel `_ py.test figleaf coverage plugin + `pytest-flakes `_ `0.2 `_ `Florian Schulze, Holger Krekel and Ronny Pfannschmidt `_ pytest plugin to check source code with pyflakes + `pytest-greendots `_ `0.2 `_ `UNKNOWN `_ Green progress dots + `pytest-growl `_ `0.1 `_ `Anthony Long `_ Growl notifications for pytest results. + `pytest-incremental `_ `0.3.0 `_ `Eduardo Naufel Schettino `_ an incremental test runner (pytest plugin) + `pytest-instafail `_ `0.1.0 `_ `Janne Vanhala `_ py.test plugin to show failures instantly + `pytest-ipdb `_ `0.1-prerelease `_ `Matthew de Verteuil `_ A py.test plug-in to enable drop to ipdb debugger on test failure. + `pytest-konira `_ `0.2 `_ `Alfredo Deza `_ Run Konira DSL tests with py.test + `pytest-localserver `_ `0.3 `_ `Sebastian Rahlf `_ py.test plugin to test server connections locally. + `pytest-marker-bugzilla `_ `0.06 `_ `Eric Sammons `_ py.test bugzilla integration plugin, using markers + `pytest-markfiltration `_ `0.8 `_ `adam goucher `_ UNKNOWN + `pytest-marks `_ `0.4 `_ `adam goucher `_ UNKNOWN + `pytest-monkeyplus `_ `1.1.0 `_ `Virgil Dupras `_ pytest's monkeypatch subclass with extra functionalities + `pytest-mozwebqa `_ `1.1.1 `_ `Dave Hunt `_ Mozilla WebQA plugin for py.test. + `pytest-oerp `_ `0.2.0 `_ `Leonardo Santagada `_ pytest plugin to test OpenERP modules + `pytest-osxnotify `_ `0.1.4 `_ `Daniel Bader `_ OS X notifications for py.test results. + `pytest-paste-config `_ `0.1 `_ `UNKNOWN `_ Allow setting the path to a paste config file + `pytest-pep8 `_ `1.0.5 `_ `Holger Krekel and Ronny Pfannschmidt `_ pytest plugin to check PEP8 requirements + `pytest-poo `_ `0.2 `_ `Andreas Pelme `_ Visualize your crappy tests + `pytest-pydev `_ `0.1 `_ `Sebastian Rahlf `_ py.test plugin to connect to a remote debug server with PyDev or PyCharm. + `pytest-qt `_ `1.0.2 `_ `Bruno Oliveira `_ pytest plugin that adds fixtures for testing Qt (PyQt and PySide) applications. + `pytest-quickcheck `_ `0.7 `_ `Tetsuya Morimoto `_ pytest plugin to generate random data inspired by QuickCheck + `pytest-rage `_ `0.1 `_ `Leonardo Santagada `_ pytest plugin to implement PEP712 + `pytest-random `_ `0.02 `_ `Leah Klearman `_ py.test plugin to randomize tests + `pytest-rerunfailures `_ `0.03 `_ `Leah Klearman `_ py.test plugin to re-run tests to eliminate flakey failures + `pytest-runfailed `_ `0.3 `_ `Dimitri Merejkowsky `_ implement a --failed option for pytest + `pytest-runner `_ `2.0 `_ `Jason R. Coombs `_ UNKNOWN + `pytest-sugar `_ `0.2.2 `_ `Teemu, Janne Vanhala `_ py.test plugin that adds instafail, ETA and neat graphics + `pytest-timeout `_ `0.3 `_ `Floris Bruynooghe `_ pytest plugin to abort tests after a timeout + `pytest-twisted `_ `1.4 `_ `Ralf Schmitt `_ A twisted plugin for py.test. + `pytest-xdist `_ `1.9 `_ `holger krekel and contributors `_ py.test xdist plugin for distributed testing and loop-on-failing modes + `pytest-xprocess `_ `0.8 `_ `Holger Krekel `_ pytest plugin to manage external processes across test runs + `pytest-yamlwsgi `_ `0.6 `_ `Ali Afshar `_ Run tests against wsgi apps defined in yaml + `pytest-zap `_ `0.1 `_ `Dave Hunt `_ OWASP ZAP plugin for py.test. + +================================================================================== ============================================================================ ==================================================================================== ============================================================================================================================================= + +*(Updated on 2013-10-11)*