Author: gjm Date: Sun Apr 1 00:32:25 2012 New Revision: 1307959 URL: http://svn.apache.org/viewvc?rev=1307959&view=rev Log: Dashboard code import: BH_Dashboard: TicketReportWidget test cases 100% ok in Trac=0.11 PS: As a side-effect XmlRpcPlugin added as testing dependency and used in test case code Modified: incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/api.py incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/tests/__init__.py incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/tests/test_report.py incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/widgets/report.py incubator/bloodhound/trunk/bloodhound_dashboard/setup.py Modified: incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/api.py URL: http://svn.apache.org/viewvc/incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/api.py?rev=1307959&r1=1307958&r2=1307959&view=diff ============================================================================== --- incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/api.py (original) +++ incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/api.py Sun Apr 1 00:32:25 2012 @@ -82,6 +82,10 @@ class DashboardSystem(Component): if param_spec.get('required'): raise InvalidWidgetArgument(p, "Required parameter expected") + elif param_spec.get('default') is not None : + return param_spec['default'] + else: + return None return (get_and_check(param) for param in params) # Maybe it is better to move these to a separate file Modified: incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/tests/__init__.py URL: http://svn.apache.org/viewvc/incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/tests/__init__.py?rev=1307959&r1=1307958&r2=1307959&view=diff ============================================================================== --- incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/tests/__init__.py (original) +++ incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/tests/__init__.py Sun Apr 1 00:32:25 2012 @@ -256,7 +256,7 @@ class DocTestTracLoader(DocTestLoader): db = self.env.get_db_cnx() cursor = db.cursor() for table in db_default.schema: - if trac_version < (0, 13) : # FIXME: Should it be (0, 12) + if trac_version < (0, 13) : # FIXME: Should it be (0, 12) ? cursor.execute("DELETE FROM " + table.name) else: cursor.execute("DROP TABLE " + table.name) @@ -343,6 +343,9 @@ class DocTestWidgetLoader(DocTestTracLoa except InvalidIdentifier: self.partial_setup() + # Load trac built-in components and RPC handlers by default + default_packages = ['trac'] + #------------------------------------------------------ # Helper functions used in test cases #------------------------------------------------------ Modified: incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/tests/test_report.py URL: http://svn.apache.org/viewvc/incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/tests/test_report.py?rev=1307959&r1=1307958&r2=1307959&view=diff ============================================================================== --- incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/tests/test_report.py (original) +++ incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/tests/test_report.py Sun Apr 1 00:32:25 2012 @@ -62,9 +62,10 @@ def test_suite(): l = MultiTestLoader( [defaultTestLoader, \ DocTestWidgetLoader(extraglobs=magic_vars, \ - enable=['trac.[a-uw-z]*', 'bhdashboard.*'], \ + enable=['trac.[a-uw-z]*', 'tracrpc.*', \ + 'bhdashboard.*'], \ default_data=True, \ - optionflags=ELLIPSIS | # REPORT_UDIFF | \ + optionflags=ELLIPSIS | REPORT_UDIFF | \ NORMALIZE_WHITESPACE) \ ]) @@ -148,16 +149,183 @@ __test__ = { 'type': }} """, '|TicketReport: Render My Tickets report' : r""" - >>> widget.render_widget('TicketReport', ctx, { + + # Add tickets + >>> from tracrpc.ticket import TicketRPC + >>> tcktrpc = TicketRPC(env) + >>> for td in ticket_data : + ... tcktrpc.create(auth_req, *td) + ... + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + + >>> if all(tcktrpc.get(auth_req, tid)[-1].get('status') == 'new' \ + ... for tid in xrange(1, 10)): + ... # RPC considers ticket workflow + ... prepare_ticket_workflow(tcktrpc, ticket_data, auth_req) + ... + + # Check everything is ok with tickets + >>> for tid in xrange(1, 10): + ... d = tcktrpc.get(auth_req, tid)[-1] + ... print tuple(d.get(attr) or '' for attr in TICKET_ATTRS) + (u'Ticket 1', u'Description 1', u'major', u'milestone1', + u'defect', u'murphy', u'accepted', u'component1', u'1.0') + (u'Ticket 2', u'Description 2', u'major', u'milestone4', + u'task', u'murphy', u'accepted', '', '') + (u'Ticket 3', u'Description 3', u'critical', u'milestone3', + u'enhancement', u'tester', u'new', '', u'2.0') + (u'Ticket 4', u'Description 4', u'minor', u'milestone3', + u'task', u'murphy', u'closed', u'component1', u'1.0') + (u'Ticket 5', u'Description 5', u'minor', u'milestone3', + u'task', u'murphy', u'new', '', u'2.0') + (u'Ticket 6', u'Description 6', u'minor', u'milestone1', + u'task', u'tester', u'assigned', u'component2', u'1.0') + (u'Ticket 7', u'Description 7', u'critical', '', u'enhancement', + u'murphy', u'closed', '', '') + (u'Ticket 8', u'Description 8', u'major', '', u'task', + u'murphy', u'closed', u'component1', '') + (u'Ticket 9', u'Description 9', u'minor', '', u'enhancement', + u'tester', u'closed', '', u'2.0') + + >>> pprint(widget.render_widget('TicketReport', ctx, { ... 'args' : {'id' : 7} - ... }) + ... })) ... + ('widget_grid.html', [], ) + + >>> pprint(widget.render_widget('TicketReport', auth_ctx, { + ... 'args' : {'id' : 7} + ... })) + ... + ('widget_grid.html', + [{u'__color__': u'3', + u'__group__': u'Accepted', + u'_changetime': ..., + u'_description': u'Description 1', + u'_reporter': u'murphy', + u'component': u'component1', + u'created': ..., + u'milestone': u'milestone1', + u'priority': u'major', + u'summary': u'Ticket 1', + u'ticket': 1, + u'type': u'defect', + u'version': u'1.0'}, + {u'__color__': u'3', + u'__group__': u'Accepted', + u'_changetime': ..., + u'_description': u'Description 2', + u'_reporter': u'murphy', + u'component': None, + u'created': ..., + u'milestone': u'milestone4', + u'priority': u'major', + u'summary': u'Ticket 2', + u'ticket': 2, + u'type': u'task', + u'version': None}, + {u'__color__': u'4', + u'__group__': u'Owned', + u'_changetime': ..., + u'_description': u'Description 5', + u'_reporter': u'murphy', + u'component': None, + u'created': ..., + u'milestone': u'milestone3', + u'priority': u'minor', + u'summary': u'Ticket 5', + u'ticket': 5, + u'type': u'task', + u'version': u'2.0'}], + ) """, '|TicketReport: Render a subset of My Tickets report' : r""" - >>> widget.render_widget('TicketReport', ctx, { - ... 'args' : {'id' : 7} - ... }) + + # Add tickets + >>> from tracrpc.ticket import TicketRPC + >>> tcktrpc = TicketRPC(env) + >>> for td in ticket_data : + ... tcktrpc.create(auth_req, *td) + ... + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + + >>> if all(tcktrpc.get(auth_req, tid)[-1].get('status') == 'new' \ + ... for tid in xrange(1, 10)): + ... # RPC considers ticket workflow + ... prepare_ticket_workflow(tcktrpc, ticket_data, auth_req) ... + + # Check everything is ok with tickets + >>> for tid in xrange(1, 10): + ... d = tcktrpc.get(auth_req, tid)[-1] + ... print tuple(d.get(attr) or '' for attr in TICKET_ATTRS) + (u'Ticket 1', u'Description 1', u'major', u'milestone1', + u'defect', u'murphy', u'accepted', u'component1', u'1.0') + (u'Ticket 2', u'Description 2', u'major', u'milestone4', + u'task', u'murphy', u'accepted', '', '') + (u'Ticket 3', u'Description 3', u'critical', u'milestone3', + u'enhancement', u'tester', u'new', '', u'2.0') + (u'Ticket 4', u'Description 4', u'minor', u'milestone3', + u'task', u'murphy', u'closed', u'component1', u'1.0') + (u'Ticket 5', u'Description 5', u'minor', u'milestone3', + u'task', u'murphy', u'new', '', u'2.0') + (u'Ticket 6', u'Description 6', u'minor', u'milestone1', + u'task', u'tester', u'assigned', u'component2', u'1.0') + (u'Ticket 7', u'Description 7', u'critical', '', u'enhancement', + u'murphy', u'closed', '', '') + (u'Ticket 8', u'Description 8', u'major', '', u'task', + u'murphy', u'closed', u'component1', '') + (u'Ticket 9', u'Description 9', u'minor', '', u'enhancement', + u'tester', u'closed', '', u'2.0') + + >>> pprint(widget.render_widget('TicketReport', auth_ctx, { + ... 'args' : {'id' : 7, 'limit' : 2} + ... })) + ... + ('widget_grid.html', + [{u'__color__': u'3', + u'__group__': u'Accepted', + u'_changetime': ..., + u'_description': u'Description 1', + u'_reporter': u'murphy', + u'component': u'component1', + u'created': ..., + u'milestone': u'milestone1', + u'priority': u'major', + u'summary': u'Ticket 1', + u'ticket': 1, + u'type': u'defect', + u'version': u'1.0'}, + {u'__color__': u'3', + u'__group__': u'Accepted', + u'_changetime': ..., + u'_description': u'Description 2', + u'_reporter': u'murphy', + u'component': None, + u'created': ..., + u'milestone': u'milestone4', + u'priority': u'major', + u'summary': u'Ticket 2', + u'ticket': 2, + u'type': u'task', + u'version': None}], + ) """, '|TicketReport: Invalid widget name' : r""" >>> widget.render_widget('OlkswSk', ctx, { @@ -187,7 +355,7 @@ __test__ = { InvalidWidgetArgument: Invalid argument `id`. Required parameter expected >>> widget.render_widget('TicketReport', ctx, { - ... 'args' : {} + ... 'args' : {'limit' : 4} ... }) ... Traceback (most recent call last): @@ -195,10 +363,71 @@ __test__ = { InvalidWidgetArgument: Invalid argument `id`. Required parameter expected """, '|TicketReport: Invalid widget parameter' : r""" - >>> widget.render_widget('TicketReport', ctx, { - ... 'args' : {'newjums' : 7, 'id' : 3} - ... }) + + # Add tickets + >>> from tracrpc.ticket import TicketRPC + >>> tcktrpc = TicketRPC(env) + >>> for td in ticket_data : + ... tcktrpc.create(auth_req, *td) + ... + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + + >>> if all(tcktrpc.get(auth_req, tid)[-1].get('status') == 'new' \ + ... for tid in xrange(1, 10)): + ... # RPC considers ticket workflow + ... prepare_ticket_workflow(tcktrpc, ticket_data, auth_req) + ... + + # Check everything is ok with tickets + >>> for tid in xrange(1, 10): + ... d = tcktrpc.get(auth_req, tid)[-1] + ... print tuple(d.get(attr) or '' for attr in TICKET_ATTRS) + (u'Ticket 1', u'Description 1', u'major', u'milestone1', + u'defect', u'murphy', u'accepted', u'component1', u'1.0') + (u'Ticket 2', u'Description 2', u'major', u'milestone4', + u'task', u'murphy', u'accepted', '', '') + (u'Ticket 3', u'Description 3', u'critical', u'milestone3', + u'enhancement', u'tester', u'new', '', u'2.0') + (u'Ticket 4', u'Description 4', u'minor', u'milestone3', + u'task', u'murphy', u'closed', u'component1', u'1.0') + (u'Ticket 5', u'Description 5', u'minor', u'milestone3', + u'task', u'murphy', u'new', '', u'2.0') + (u'Ticket 6', u'Description 6', u'minor', u'milestone1', + u'task', u'tester', u'assigned', u'component2', u'1.0') + (u'Ticket 7', u'Description 7', u'critical', '', u'enhancement', + u'murphy', u'closed', '', '') + (u'Ticket 8', u'Description 8', u'major', '', u'task', + u'murphy', u'closed', u'component1', '') + (u'Ticket 9', u'Description 9', u'minor', '', u'enhancement', + u'tester', u'closed', '', u'2.0') + + >>> pprint(widget.render_widget('TicketReport', auth_ctx, { + ... 'args' : {'newjums' : 7, 'id' : 7, 'limit' : 1} + ... })) ... + ('widget_grid.html', + [{u'__color__': u'3', + u'__group__': u'Accepted', + u'_changetime': ..., + u'_description': u'Description 1', + u'_reporter': u'murphy', + u'component': u'component1', + u'created': ..., + u'milestone': u'milestone1', + u'priority': u'major', + u'summary': u'Ticket 1', + u'ticket': 1, + u'type': u'defect', + u'version': u'1.0'}], + ) """, '|TicketReport: Invalid report definition' : r""" >>> raise NotImplementedError() Modified: incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/widgets/report.py URL: http://svn.apache.org/viewvc/incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/widgets/report.py?rev=1307959&r1=1307958&r2=1307959&view=diff ============================================================================== --- incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/widgets/report.py (original) +++ incubator/bloodhound/trunk/bloodhound_dashboard/bhdashboard/widgets/report.py Sun Apr 1 00:32:25 2012 @@ -25,7 +25,7 @@ Widgets displaying report data. """ from datetime import datetime, date, time -from itertools import imap +from itertools import imap, islice from trac.core import implements, TracError from trac.ticket.report import ReportModule @@ -64,7 +64,7 @@ class TicketReportWidget(WidgetBase): rptid, limit = self.bind_params(name, options, 'id', 'limit') metadata = self.get(req, rptid) # TODO: Should metadata also contain columns definition ? - data = list(self.execute(req, rptid)) + data = list(self.execute(req, rptid, limit)) except TracError, exc: if metadata is not None : exc.title = metadata.get('title', 'TracReports') @@ -72,7 +72,7 @@ class TicketReportWidget(WidgetBase): exc.title = 'TracReports' raise else: - return 'widget_grid', data, context + return 'widget_grid.html', data, context render_widget = pretty_wrapper(render_widget, check_widget_name) @@ -127,7 +127,11 @@ class TicketReportWidget(WidgetBase): kwargs = dict(limit=limit) except AttributeError: # Legacy exec (<=0.10) - exec_proc = repmdl.execute_report + if limit > 0: + exec_proc = lambda *args, **kwargs: \ + islice(repmdl.execute_report(*args, **kwargs), limit) + else: + exec_proc = repmdl.execute_report kwargs = {} return exec_proc(req, db, id, sql, args, **kwargs)[:2] except Exception, e: Modified: incubator/bloodhound/trunk/bloodhound_dashboard/setup.py URL: http://svn.apache.org/viewvc/incubator/bloodhound/trunk/bloodhound_dashboard/setup.py?rev=1307959&r1=1307958&r2=1307959&view=diff ============================================================================== --- incubator/bloodhound/trunk/bloodhound_dashboard/setup.py (original) +++ incubator/bloodhound/trunk/bloodhound_dashboard/setup.py Sun Apr 1 00:32:25 2012 @@ -113,7 +113,7 @@ setup( version=latest, description=DESC.split('\n', 1)[0], requires = ['trac'], - tests_require = ['dutest>=0.2.4'], + tests_require = ['dutest>=0.2.4', 'TracXMLRPC'], install_requires = [ 'setuptools>=0.6b1', 'Trac>=0.11',