Commits

Anonymous committed f9fb7f2

first commit

Comments (0)

Files changed (15)

 
 youtube:
    Chris Pickel <sfiera@gmail.com>
+
+clearquest:
+   Robin Jarry <robin.jarry@gmail.com>
+
 - traclinks: create TracLinks_ to a Trac_ instance from within Sphinx
 - youtube: embed videos from YouTube_
 - zopeext: provide an ``autointerface`` directive for using Zope interfaces.
+- clearquest: create tables from ClearQuest_ queries.
 
 .. _aafigure: https://launchpad.net/aafigure
 
 
 .. _YouTube: http://www.youtube.com/
 
+.. _ClearQuest: http://www-01.ibm.com/software/awdtools/clearquest/
+
 For contributors
 ================
 

clearquest/.project

+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>sphinxcontrib-clearquest</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.python.pydev.PyDevBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.python.pydev.pythonNature</nature>
+	</natures>
+</projectDescription>

clearquest/.pydevproject

+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<?eclipse-pydev version="1.0"?>
+
+<pydev_project>
+<pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">C:\integ\Python25\python.exe</pydev_property>
+<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 2.5</pydev_property>
+<pydev_pathproperty name="org.python.pydev.PROJECT_SOURCE_PATH">
+<path>/sphinxcontrib-clearquest</path>
+</pydev_pathproperty>
+</pydev_project>

clearquest/AUTHORS

+Robin Jarry <robin.jarry@gmail.com>

clearquest/LICENSE

+Copyright (c) 2009 by the contributors (see AUTHORS file).
+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.

clearquest/MANIFEST.in

+include README
+include LICENSE
+include CHANGES.*

clearquest/README

+.. -*- restructuredtext -*-
+
+=============================
+Sphinx "ClearQuest" extension 
+=============================
+
+A sphinx extension that adds a ``clearquest`` directive for converting 
+ClearQuest__ requests to reStructuredText tables.
+
+__ http://www-01.ibm.com/software/awdtools/clearquest/
+
+Syntax
+------
+
+The syntax of the directive is as follows: ::
+
+    .. clearquest:: <full name/of the clearquest query> (mandatory)
+        :username: <your username> (optional)
+        :password: <your password> (optional)
+        :db_name: <the name of the db> (optional)
+        :db_set: <the name of the db set> (optional)
+        :params: <parameters to pass to the query> (optional)
+
+The connection credentials can either be provided as directive options or 
+in a ``clearquest`` section in the ``~/.sphinxcontrib`` file which is a 
+standard ``.ini`` configuration file. ::
+
+	[clearquest]
+	username = john
+	password = doe
+	db_name = prod
+	db_set = cqsrv
+
+The parameters to pass to the query must respect the following syntax: ::
+
+    <param1_name>=<param1_value>,<param2_name>=<param2_value>, ....
+
+You can provide them in any order as long as you don't forget one. 
+The query call will fail if you do.
+
+Required python libraries
+-------------------------
+
+* sphinx: http://sphinx.pocoo.org/
+* PyWin32: http://sourceforge.net/projects/pywin32/

clearquest/setup.cfg

+[egg_info]
+;tag_build = dev
+;tag_date = true
+
+[aliases]
+release = egg_info -RDb ''

clearquest/setup.py

+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+from setuptools import setup, find_packages
+
+long_desc = open('README', 'r').read()
+
+requires = ['Sphinx>=0.6', 'pywin32']
+
+setup(
+    name='sphinxcontrib-clearquest',
+    version='0.1',
+    url='http://bitbucket.org/birkenfeld/sphinx-contrib',
+    download_url='http://pypi.python.org/pypi/sphinxcontrib-clearquest',
+    license='BSD',
+    author='Robin Jarry',
+    author_email='robin.jarry@gmail.com',
+    description='Sphinx "clearquest" extension',
+    long_description=long_desc,
+    zip_safe=False,
+    classifiers=[
+        'Development Status :: 4 - Beta',
+        'Environment :: Console',
+        'Environment :: Win32 (MS Windows)',
+        'Intended Audience :: Developers',
+        'License :: OSI Approved :: BSD License',
+        'Operating System :: Microsoft :: Windows',
+        'Programming Language :: Python',
+        'Topic :: Documentation',
+        'Topic :: Utilities',
+    ],
+    keywords=['clearquest', 'sphinx'],
+    platforms='Windows',
+    packages=find_packages(),
+    include_package_data=True,
+    install_requires=requires,
+    namespace_packages=['sphinxcontrib'],
+)

clearquest/sphinxcontrib/__init__.py

+# -*- coding: utf-8 -*-
+"""
+    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__)
+

clearquest/sphinxcontrib/clearquest/__init__.py

+# Copyright (c) 2009 by the contributors (see AUTHORS file).
+# 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.
+
+import sphinx
+from sphinxcontrib.clearquest.directive import ClearQuest
+
+
+def setup(app):
+    """
+    Extension setup, called by Sphinx
+    """
+    try:
+        version = tuple(map(int, sphinx.__version__.split('.')))
+    except:
+        version = (1, 0)
+    # Sphinx 0.5 support
+    if version < (0, 5):
+        app.add_directive('clearquest', ClearQuest, 0, (0, 0, 0))
+    else:
+        app.add_directive('clearquest', ClearQuest)

clearquest/sphinxcontrib/clearquest/connection.py

+# Copyright (c) 2009 by the contributors (see AUTHORS file).
+# 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.
+
+import win32com.client as COM
+
+
+PRIVATE_SESSION = 2
+
+class ClearQuestConnection():
+
+    def __init__(self, username, password, db_name, db_set):
+        self.username = str(username)
+        self.password = str(password)
+        self.db_name = str(db_name)
+        self.db_set = str(db_set)
+        self.session = None
+    
+    def run_query(self, queryName, parameters):
+        """
+        Runs a ClearQuest query and returns the result as a list of lists.
+        
+        example:
+
+        [ ['column_1',  'column_2',  'column_3'],
+          ['value_1_1', 'value_1_2', 'value_1_3'],
+          ['value_2_1', 'value_2_2', 'value_2_3'],
+          ['value_3_1', 'value_3_2', 'value_3_3'],
+          ['value_4_1', 'value_4_2', 'value_4_3'], ]
+          
+        If the query returns nothing, only one row containing dashes is returned.
+        
+        """
+        if self.session is None:
+            self.open_session()
+        
+        workspace = self.session.GetWorkSpace
+        query = workspace.GetQueryDef(queryName)
+        resultSet = self.session.BuildResultSet(query)
+        numberOfParams = resultSet.GetNumberOfParams
+        
+        if numberOfParams:
+            errors = []
+            
+            for i in range(1, numberOfParams + 1):
+                param_name = resultSet.GetParamLabel(i)
+                try:
+                    param_value = parameters[param_name]
+                except:
+                    errors.append("'%s'" % param_name)
+                resultSet.AddParamValue(i, param_value)
+            
+            if errors:
+                params = ", ".join(errors) 
+                raise ValueError("Missing parameters %s to query '%s'" % (params, queryName))
+            
+        resultSet.Execute()
+        
+        status = resultSet.MoveNext
+        
+        # this is silly, but first column is reserved
+        nbcol = resultSet.GetNumberOfColumns - 1
+        
+        records = []
+        columns = [ fieldDef.Label for fieldDef in query.QueryFieldDefs ][1:]
+        
+        if status != 1:
+            # No results from ClearQuest query, we fill one line with dashes
+            records.append(list("-" * len(columns)))
+            
+        while status == 1:
+            records.append([ resultSet.GetColumnValue(i) for i in range(2, nbcol + 2) ])
+            status = resultSet.MoveNext
+            
+        return columns, records
+    
+    def open_session(self):
+        self.session = COM.dynamic.Dispatch("CLEARQUEST.SESSION")
+        self.session.UserLogon(self.username, self.password, self.db_name, 
+                               PRIVATE_SESSION, self.db_set)
+
+
+

clearquest/sphinxcontrib/clearquest/directive.py

+# Copyright (c) 2009 by the contributors (see AUTHORS file).
+# 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.
+
+import re
+import ConfigParser
+from os import path
+
+from docutils.parsers.rst.directives.tables import Table
+from docutils.parsers.rst import directives, DirectiveError
+from docutils import statemachine, nodes, frontend
+from sphinxcontrib.clearquest.connection import ClearQuestConnection
+from sphinx.util import console
+from docutils.utils import Reporter
+
+
+SUBST_REF_REX = re.compile(r'\|(.+?)\|', re.DOTALL)
+
+#------------------------------------------------------------------------------
+class CQReporter(Reporter):
+    """
+    Subclass of docutils.util.Reporter with default values
+    """
+    def __init__(self):
+        settings = frontend.OptionParser().get_default_values()
+        settings.report_level = 1
+        Reporter.__init__(
+            self, 
+            source='sphinxcontrib.clearquest', 
+            report_level=settings.report_level, 
+            halt_level=settings.halt_level, 
+            stream=settings.warning_stream, 
+            debug=settings.debug, 
+            encoding=settings.error_encoding, 
+            error_handler=settings.error_encoding_error_handler
+        )
+
+#------------------------------------------------------------------------------
+class ClearQuest(Table):
+    """
+    
+    
+    
+    
+    """
+    
+    option_spec = {
+        'username': directives.unchanged,
+        'password': directives.unchanged,
+        'db_name': directives.unchanged,
+        'db_set': directives.unchanged,
+        'params': directives.unchanged
+    }
+
+    required_arguments = 1
+    optional_arguments = 0
+    final_argument_whitespace = True
+    has_content = False
+    
+    reporter = CQReporter()
+    
+    connection = None
+    
+    def run(self):
+        try:
+            self.resolve_substitutions_refs()
+            queryName = self.arguments[0]
+            queryParams = self.extract_query_params()
+            
+            if ClearQuest.connection is None:
+                creds = self.get_credentials()
+                if None in creds.values():
+                    missing = [ name for name, value in creds.items() if value is None ]
+                    ClearQuest.reporter.warning(console.red( #@UndefinedVariable
+                        'Missing credentials "%s". ' % '", "'.join(missing) + 
+                        'Looked in ~/.sphinxcontrib and in directive options.' 
+                    ))
+                ClearQuest.reporter.info('Opening ClearQuest session...')
+                ClearQuest.connection = ClearQuestConnection(**creds) 
+            
+            ClearQuest.reporter.info('Executing ClearQuest query "%s"...' % queryName)
+            columns, records = ClearQuest.connection.run_query(queryName, queryParams)
+            
+            col_widths = self.get_column_widths(header=columns, content=records)
+            table_head = [ self.create_row(columns) ]
+            table_body = [ self.create_row(line) for line in records ]
+        
+        except Exception, detail:
+            if isinstance(detail, DirectiveError):
+                message = detail.msg
+            else:
+                message = str(detail)
+            error = ClearQuest.reporter.error(
+                'Error with query data in "%s" directive:\n%s' % (self.name, message), 
+                nodes.literal_block(self.block_text, self.block_text), 
+                line=self.lineno
+            )
+            return [error]
+        
+        table = (col_widths, table_head, table_body)
+        table_node = self.state.build_table(table, self.content_offset)
+        table_node['classes'] += self.options.get('class', [])
+        
+        return [table_node]
+
+    def create_row(self, line):
+        row = []
+        for cell_text in line:
+            row.append( (0, 0, 0, statemachine.StringList(cell_text.splitlines())) )
+        return row
+
+    def get_column_widths(self, header, content):
+        widths = [0] * len(header)
+        
+        for i in range(len(header)):
+            if len(header[i]) > widths[i]:
+                widths[i] = len(header[i])
+                
+        for row in content:
+            for i in range(len(row)):
+                if len(row[i]) > widths[i]:
+                    widths[i] = len(row[i])
+                    
+        return widths
+
+    def extract_query_params(self):
+        params_dict = {}
+        params = self.options.get("params")
+        if params:
+            for p in params.split(","):
+                p_name, p_value = p.split("=")
+                params_dict[p_name.strip()] = p_value.strip()
+        return params_dict
+
+    def resolve_substitutions_refs(self):
+        def _subst_ref_match(match):
+            return self.state.document.substitution_defs[match.group(1)].astext()
+        
+        for opt_name in self.options.keys():
+            opt_val = unicode(self.options[opt_name])
+            opt_val, _ = SUBST_REF_REX.subn(_subst_ref_match, opt_val)
+            self.options[opt_name] = opt_val
+
+
+    def get_credentials(self):
+        creds = {
+            'username': None,
+            'password': None,
+            'db_name': None,
+            'db_set': None,
+        }
+        # first, we try to read connection credentials from ~/.sphinxcontrib 
+        config = ConfigParser.RawConfigParser()
+        config.read(path.normpath(path.expanduser('~/.sphinxcontrib')))
+        if config.has_section('clearquest'):
+            for name in creds.keys():
+                if config.has_option('clearquest', name):
+                    creds[name] = config.get('clearquest', name)
+        
+        # then, we override the credentials if they are given in the directive
+        for name in creds.keys():
+            if self.options.has_key(name) and self.options[name] is not None:
+                creds[name] = self.options[name]
+        
+        return creds
+
+
+
+        

clearquest/tox.ini

+## configuration for tox <http://codespeak.net/tox/>
+
+## tox automates running certain tasks within virtualenvs.  The following
+## tox configuration outlines a basic setup for running unit tests and
+## building sphinx docs in separate virtual environments.  Give it a try!
+
+[tox]
+envlist=python,doc
+
+# test running
+[testenv:python]
+deps=
+    ## if you use nose for test running
+    # nose
+    ## if you use py.test for test running
+    # pytest
+commands=
+    ## run tests with py.test
+    # py.test []
+    ## run tests with nose
+    # nose
+
+[testenv:doc]
+deps=
+    sphinx
+    # add all Sphinx extensions and other dependencies required to build your docs
+commands=
+    ## test links
+    # sphinx-build -W -b linkcheck -d {envtmpdir}/doctrees doc {envtmpdir}/linkcheck
+    ## test html output
+    # sphinx-build -W -b html -d {envtmpdir}/doctrees doc {envtmpdir}/html
+