diff --git a/doc/en/plugins_index/plugins_index.py b/doc/en/plugins_index/plugins_index.py index f1cc8a465..83cd33e6b 100644 --- a/doc/en/plugins_index/plugins_index.py +++ b/doc/en/plugins_index/plugins_index.py @@ -1,9 +1,10 @@ -''' -Script to generate the file `plugins_index.txt` with information about pytest plugins taken directly -from a live PyPI server. +""" +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. -''' +This will evolve to include test compatibility (pythons and pytest versions) +information also. +""" from collections import namedtuple import datetime from distutils.version import LooseVersion @@ -15,107 +16,108 @@ import xmlrpclib import pytest -#=================================================================================================== -# iter_plugins -#=================================================================================================== + 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}): + """ + for plug_data in client.search({'name': search}): yield plug_data['name'], plug_data['version'] -#=================================================================================================== -# 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. - ''' + """ + 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] yield name, str(loose_version) - - -#=================================================================================================== -# obtain_plugins_table -#=================================================================================================== -def obtain_plugins_table(plugins, client): - ''' - Returns information to populate a table of plugins, their versions, authors, etc. + + +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. + 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 = [] ColumnData = namedtuple('ColumnData', 'text link') - headers = ['Name', 'Author', 'Downloads', 'Python 2.7', 'Python 3.3', 'Summary'] + headers = ['Name', 'Author', 'Downloads', 'Python 2.7', 'Python 3.3', + 'Summary'] pytest_version = pytest.__version__ print '*** pytest-{0} ***'.format(pytest_version) plugins = list(plugins) for index, (package_name, version) in enumerate(plugins): print package_name, version, '...', - + release_data = client.release_data(package_name, version) download_count = release_data['downloads']['last_month'] - image_url = '.. image:: http://pytest-plugs.herokuapp.com/status/{name}-{version}'.format(name=package_name, - version=version) + url = '.. image:: {site}/status/{name}-{version}' + image_url = url.format( + site='http://pytest-plugs.herokuapp.com', + name=package_name, + version=version) image_url += '?py={py}&pytest={pytest}' row = ( - ColumnData(package_name + '-' + version, release_data['release_url']), + ColumnData(package_name + '-' + version, + release_data['release_url']), ColumnData(release_data['author'], release_data['author_email']), ColumnData(str(download_count), None), - ColumnData(image_url.format(py='py27', pytest=pytest_version), None), - ColumnData(image_url.format(py='py33', pytest=pytest_version), None), + ColumnData(image_url.format(py='py27', pytest=pytest_version), + None), + ColumnData(image_url.format(py='py33', pytest=pytest_version), + None), ColumnData(release_data['summary'], None), ) assert len(row) == len(headers) rows.append(row) - - print 'OK (%d%%)' % ((index + 1) * 100 / len(plugins)) - - return headers, rows + + print 'OK (%d%%)' % ((index + 1) * 100 / len(plugins)) + + return headers, rows -#=================================================================================================== -# generate_plugins_index_from_table -#=================================================================================================== 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 + """ + # 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 + 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) - + with file(filename, 'w') as f: # write welcome print >> f, '.. _plugins_index:' @@ -123,17 +125,18 @@ def generate_plugins_index_from_table(filename, headers, rows): print >> f, 'List of Third-Party Plugins' print >> f, '===========================' print >> f - + # table print >> f, get_row_limiter('=') for i, header in enumerate(headers): print >> f, '{0:^{fill}}'.format(header, fill=column_lengths[i]), print >> f print >> f, get_row_limiter('=') - + for column_texts in table_texts: for i, row_text in enumerate(column_texts): - print >> f, '{0:^{fill}}'.format(row_text, fill=column_lengths[i]), + print >> f, '{0:^{fill}}'.format(row_text, + fill=column_lengths[i]), print >> f print >> f print >> f, get_row_limiter('=') @@ -141,54 +144,50 @@ def generate_plugins_index_from_table(filename, headers, rows): print >> f, '*(Downloads are given from last month only)*' print >> f print >> f, '*(Updated on %s)*' % _get_today_as_str() - -#=================================================================================================== -# _get_today_as_str -#=================================================================================================== + def _get_today_as_str(): - ''' + """ internal. only exists so we can patch it in testing. - ''' + """ return datetime.date.today().strftime('%Y-%m-%d') -#=================================================================================================== -# generate_plugins_index -#=================================================================================================== def generate_plugins_index(client, filename): - ''' - Generates an RST file with a table of the latest pytest plugins found in PyPI. + """ + 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(filename, headers, rows) - -#=================================================================================================== -# main -#=================================================================================================== + def main(argv): + """ + Script entry point. Configures an option parser and calls the appropriate + internal function. + """ filename = os.path.join(os.path.dirname(__file__), 'plugins_index.txt') url = 'http://pypi.python.org/pypi' - - parser = OptionParser(description='Generates a restructured document of pytest plugins from PyPI') - parser.add_option('-f', '--filename', default=filename, help='output filename [default: %default]') - parser.add_option('-u', '--url', default=url, help='url of PyPI server to obtain data from [default: %default]') + + parser = OptionParser( + description='Generates a restructured document of pytest plugins from PyPI') + parser.add_option('-f', '--filename', default=filename, + help='output filename [default: %default]') + parser.add_option('-u', '--url', default=url, + help='url of PyPI server to obtain data from [default: %default]') (options, _) = parser.parse_args(argv[1:]) client = xmlrpclib.ServerProxy(options.url) generate_plugins_index(client, options.filename) - + print print '%s Updated.' % options.filename return 0 -#=================================================================================================== -# main -#=================================================================================================== if __name__ == '__main__': sys.exit(main(sys.argv)) diff --git a/doc/en/plugins_index/test_plugins_index.py b/doc/en/plugins_index/test_plugins_index.py index 54d09b7eb..ef71b1e90 100644 --- a/doc/en/plugins_index/test_plugins_index.py +++ b/doc/en/plugins_index/test_plugins_index.py @@ -4,64 +4,67 @@ import xmlrpclib import pytest -#=================================================================================================== -# test_plugins_index -#=================================================================================================== - -@pytest.mark.xfail(reason="issue405 fails, not py33 ready, not a core pytest test") +@pytest.mark.xfail( + reason="issue405 fails, not py33 ready, not a core pytest test") def test_plugins_index(tmpdir, monkeypatch): - ''' - Blackbox testing for plugins_index script. Calls main() generating a file and compares produced - output to expected. + """ + Blackbox testing for plugins_index script. Calls main() generating a file + and compares produced output to expected. - .. note:: if the test fails, a file named `test_plugins_index.obtained.rst` will be generated in - the same directory as this test file. Ensure the contents are correct and overwrite + .. note:: if the test fails, a file named + `test_plugins_index.obtained.rst` will be generated in the same directory + as this test file. Ensure the contents are correct and overwrite `test_plugins_index.expected.rst` with that file. - ''' + """ import plugins_index # dummy interface to xmlrpclib.ServerProxy class DummyProxy(object): expected_url = 'http://dummy.pypi' + def __init__(self, url): assert url == self.expected_url def search(self, query): - assert query == {'name' : 'pytest-'} + assert query == {'name': 'pytest-'} return [ - {'name': 'pytest-plugin1', 'version' : '0.8'}, - {'name': 'pytest-plugin1', 'version' : '1.0'}, - {'name': 'pytest-plugin2', 'version' : '1.2'}, + {'name': 'pytest-plugin1', 'version': '0.8'}, + {'name': 'pytest-plugin1', 'version': '1.0'}, + {'name': 'pytest-plugin2', 'version': '1.2'}, ] def release_data(self, package_name, version): results = { - ('pytest-plugin1', '1.0') : { - 'package_url' : 'http://plugin1', - 'release_url' : 'http://plugin1/1.0', - 'author' : 'someone', - 'author_email' : 'someone@py.com', - 'summary' : 'some plugin', - 'downloads': {'last_day': 1, 'last_month': 4, 'last_week': 2}, + ('pytest-plugin1', '1.0'): { + 'package_url': 'http://plugin1', + 'release_url': 'http://plugin1/1.0', + 'author': 'someone', + 'author_email': 'someone@py.com', + 'summary': 'some plugin', + 'downloads': {'last_day': 1, 'last_month': 4, + 'last_week': 2}, }, - ('pytest-plugin2', '1.2') : { - 'package_url' : 'http://plugin2', - 'release_url' : 'http://plugin2/1.2', - 'author' : 'other', - 'author_email' : 'other@py.com', - 'summary' : 'some other plugin', - 'downloads': {'last_day': 10, 'last_month': 40, 'last_week': 20}, + ('pytest-plugin2', '1.2'): { + 'package_url': 'http://plugin2', + 'release_url': 'http://plugin2/1.2', + 'author': 'other', + 'author_email': 'other@py.com', + 'summary': 'some other plugin', + 'downloads': {'last_day': 10, 'last_month': 40, + 'last_week': 20}, }, } return results[(package_name, version)] monkeypatch.setattr(xmlrpclib, 'ServerProxy', DummyProxy, 'foo') - monkeypatch.setattr(plugins_index, '_get_today_as_str', lambda: '2013-10-20') + monkeypatch.setattr(plugins_index, '_get_today_as_str', + lambda: '2013-10-20') output_file = str(tmpdir.join('output.rst')) - assert plugins_index.main(['', '-f', output_file, '-u', DummyProxy.expected_url]) == 0 + assert plugins_index.main( + ['', '-f', output_file, '-u', DummyProxy.expected_url]) == 0 with file(output_file, 'rU') as f: obtained_output = f.read() @@ -79,13 +82,15 @@ def get_expected_output(): """ :return: string with expected rst output from the plugins_index.py script. """ - expected_filename = os.path.join(os.path.dirname(__file__), 'test_plugins_index.expected.rst') + expected_filename = os.path.join(os.path.dirname(__file__), + 'test_plugins_index.expected.rst') expected_output = open(expected_filename, 'rU').read() - return expected_output.replace('pytest=2.X.Y', 'pytest={0}'.format(pytest.__version__)) + return expected_output.replace('pytest=2.X.Y', + 'pytest={0}'.format(pytest.__version__)) -#=================================================================================================== +#=============================================================================== # main -#=================================================================================================== +#=============================================================================== if __name__ == '__main__': pytest.main()