Ignore:
Timestamp:
17 Nov 2012, 22:43:58 (12 years ago)
Author:
uli
Message:

Try to rip out all UI-related stuff from w.k.reports. Put it into views.

Location:
main/waeup.kofa/trunk/src/waeup/kofa
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • main/waeup.kofa/trunk/src/waeup/kofa/browser/reports.py

    r9667 r9672  
    4848            self.context.delete_report_entry(entry)
    4949            self.flash('Report discarded: %s' % job_id)
    50         self.entries = self.context.get_report_jobs_description()
     50        self.entries = self._generate_entries(user_id=None)
     51        #self.entries = self.context.get_report_jobs_description()
    5152        if job_id and DOWNLOAD:
    5253            self.redirect(self._report_url(job_id))
    5354            return
    5455        return
     56
     57    def _generate_entries(self, user_id=None):
     58        entries = []
     59        for entry in self.context.get_running_report_jobs(user_id=user_id):
     60            job_id, gen_name, user = entry
     61            job = getUtility(IJobManager).get(job_id)
     62            descr = '%r, %r' % (job.args, job.kwargs)
     63            new_entry = (job_id, descr, job.status, job.finished, job.finished and not job.failed, not job.finished, job.begin_after, user)
     64            entries.append(new_entry)
     65        return entries
    5566
    5667
  • main/waeup.kofa/trunk/src/waeup/kofa/reports.py

    r9670 r9672  
    2222from persistent.list import PersistentList
    2323from zope import schema
    24 from zope.component import (
    25     getUtility, getUtilitiesFor, queryUtility)
     24from zope.component import getUtility, getUtilitiesFor
    2625from zope.component.hooks import setSite
    2726from zope.interface import implementer
     
    2928from waeup.kofa.async import AsyncJob
    3029from waeup.kofa.interfaces import (
    31     IJobManager, JOB_STATUS_MAP, IKofaPluggable, IKofaObject, IKofaUtils)
     30    IJobManager, JOB_STATUS_MAP, IKofaPluggable, IKofaObject)
    3231from waeup.kofa.interfaces import MessageFactory as _
    3332from waeup.kofa.utils.helpers import now
    34 
    35 #: A status map that reflects the really interesting types of status
    36 #: for reports.
    37 #:
    38 #: For reports we want to know whether a job was finished
    39 #: and/or whether it failed. All the other possible states ('new',
    40 #: etc.) are not really interesting in that regard.
    41 STATUS_MAP = {
    42     'unknown': _('unknown'),
    43     'running': _('running'),
    44     'finished': _('finished'),
    45     'failed': _('FAILED'),
    46     }
    4733
    4834class IReport(Interface):
     
    5844        """not when any output was created.""")
    5945
    60     title = schema.TextLine(
    61         title = u"A human readable short description for a report.",
    62         default = u'Untitled',
    63         )
    64 
    65     description = schema.Text(
    66         title = u"A human readable text describing a report.",
    67         default = u'No description'
    68         )
    69 
    7046    def create_pdf():
    7147        """Generate a PDF copy.
     
    9369        title = u"`True` iff the job finished and didn't provide a report.",
    9470        default = None,
    95         )
    96 
    97     description = schema.TextLine(
    98         title = u"""Textual representation of arguments and keywords.""",
    99         default = u"",
    100         )
    101 
    102     report_status = schema.TextLine(
    103         title = u"""Translated status string.""",
    104         default = STATUS_MAP['unknown'],
    10571        )
    10672
     
    150116        """
    151117
    152     def get_report_jobs_description(user_id=None):
    153         """Get running/completed report jobs for `user_id` as list of tuples.
    154 
    155         The results contain enough information to render a status page
    156         or similar. Each tuple holds::
    157 
    158           (``<job_id>, <description>, <status_translated>,
    159           <discardable>, <downloadable>, <starttime>, <user_name>``)
    160 
    161         in that order, with
    162 
    163         ``<job_id>``
    164             The job id of the represented job. A string.
    165 
    166         ``<description>``
    167             A human readable description of the report run.
    168 
    169         ``<status_translated>``
    170             The status of report jobs' status (translated)
    171 
    172         ``<discardable>``
    173             Boolean indicating whether the job can be discarded.
    174             Only completed jobs can be discarded.
    175 
    176         ``<downloadable>``
    177             Boolean indicating whether the job result can be
    178             downloaded. This is only true if the job finished and
    179             didn't raised exceptions.
    180 
    181         ``<starttime>``
    182             String indicating when the job was started.
    183 
    184         ``<user_name>``
    185             Name of user that started the job.
    186 
    187         If ``user_id`` is ``None``, all jobs are returned.
    188         """
    189 
    190118    def delete_report_entry(entry):
    191119        """Delete the report job denoted by `entry`.
     
    233161    def title(self):
    234162        return _(u'A report')
    235 
    236     @property
    237     def description(self):
    238         return _(u'A dummy report')
    239163
    240164    def __init__(self, args=[], kwargs={}):
     
    245169    def create_pdf(self):
    246170        raise NotImplementedError()
    247 
    248     def __repr__(self):
    249         return 'Report(args=%r, kwargs=%r)' % (self.args, self.kwargs)
    250 
    251171
    252172@implementer(IReportGenerator)
     
    324244            return True
    325245        return False
    326 
    327     @property
    328     def report_status(self):
    329         """The status of a report as translated string.
    330         """
    331         if not self.finished:
    332             return STATUS_MAP['running']
    333         if self.failed:
    334             return STATUS_MAP['failed']
    335         return STATUS_MAP['finished']
    336 
    337     @property
    338     def description(self):
    339         """A description gives a representation of the report to generate.
    340 
    341         The description contains the name of the report generator
    342         (trying to fetch the `name` attribute of the requested report
    343         generator) and the arguments and keywords passed in.
    344 
    345         Please note that this method is expensive!
    346         """
    347         args = self.kwargs.get('args', [])
    348         kw = self.kwargs.get('kw', dict())
    349         args = ', '.join(["%r" % x for x in args])
    350         kw = ', '.join(['%s' % val for val in kw.values()])
    351         if len(args) and len(kw):
    352             str_repr = args + ', ' + kw
    353         else:
    354             str_repr = args + kw
    355         str_repr = '(' + str_repr + ')'
    356         try:
    357             generator = getUtility(
    358                 IReportGenerator, name=self._generator_name)
    359             name = generator.title
    360         except:
    361             name = _('Unregistered Report Generator')
    362         return name + ' ' + str_repr
    363246
    364247@implementer(IReportJobContainer)
     
    439322        return result
    440323
    441     def get_report_jobs_description(self, user_id=None):
    442         """Get running/completed report jobs fur `user_id` as list of tuples.
    443 
    444         The results contain enough information to render a status page
    445         or similar. Each tuple holds::
    446 
    447           (``<job_id>, <description>, <status_translated>,
    448           <discardable>, <downloadable>, <starttime>, <user_name>``)
    449 
    450         in that order, with
    451 
    452         ``<job_id>``
    453             The job id of the represented job. A string.
    454 
    455         ``<description>``
    456             A human readable description of the report run.
    457 
    458         ``<status_translated>``
    459             The status of report jobs' status (translated)
    460 
    461         ``<discardable>``
    462             Boolean indicating whether the job can be discarded.
    463             Only completed jobs can be discarded.
    464 
    465         ``<downloadable>``
    466             Boolean indicating whether the job result can be
    467             downloaded. This is only true if the job finished and
    468             didn't raised exceptions.
    469 
    470         ``<starttime>``
    471             String indicating when the job was started.
    472 
    473         ``<user_name>``
    474             Name of user that started the job.
    475 
    476         If ``user_id`` is ``None``, all jobs are returned.
    477         """
    478         entries = self.get_running_report_jobs(user_id)
    479         result = []
    480         for (job_id, gen_name, user_name) in entries:
    481             manager = getUtility(IJobManager)
    482             job = manager.get(job_id)
    483             status = job.report_status
    484             discardable = job.finished
    485             downloadable = job.finished and not job.failed
    486             running = not (downloadable or discardable)
    487             starttime = getattr(job, 'begin_after', None)
    488             if starttime:
    489                 starttime = starttime.astimezone(getUtility(IKofaUtils).tzinfo)
    490                 starttime = starttime.strftime("%Y-%m-%d %H:%M:%S %Z")
    491             if not hasattr(job, 'description'):
    492                 continue
    493             result.append((job_id, job.description, status,
    494                            discardable, downloadable, running,
    495                            starttime, user_name),)
    496         return result
    497 
    498324    def delete_report_entry(self, entry):
    499325        """Delete the report job denoted by `entry`.
  • main/waeup.kofa/trunk/src/waeup/kofa/students/reports.py

    r9670 r9672  
    128128        self.data = get_students_by(session, mode)
    129129
    130     def __repr__(self):
    131         """Creates an executable representation of a StudentsReport object.
    132         """
    133         return 'StudentsReport(%r, %r, author=%r)' % (
    134             self.args[0], self.mode, self.author)
    135 
    136     #def __str__(self):
    137     #    """A nice human readable representation of a StudentsReport.
    138 
    139     #    Includes infos about session, mode and creation datetime.
    140     #    """
    141     #    return 'Students Report [session=%s, mode=%s] of %s ' % (
    142     #        self.session, self.mode, self._creation_dt_string)
    143 
    144130    @property
    145131    def title(self):
     
    169155    title = _('Students')
    170156    grok.name('students_by')
    171 
    172     @property
    173     def description(self):
    174         return self.title
    175157
    176158    def generate(self, site, session=None, mode=None, author=None):
  • main/waeup.kofa/trunk/src/waeup/kofa/students/tests/test_reports.py

    r9671 r9672  
    2020        verifyObject(IStudentsReport, obj)
    2121        return
    22 
    23     def test_repr(self):
    24         # exec(students_report.__repr__()) <=> students_report
    25         obj1 = StudentsReport(2010, 'Undergraduate Full-Time', author='Bob')
    26         self.assertEqual(
    27             obj1.__repr__(),
    28             "StudentsReport(2010, 'Undergraduate Full-Time', author='Bob')")
    29         obj_from_str = eval(obj1.__repr__())
    30         self.assertEqual(obj_from_str.session, '2010/2011')
    31         self.assertEqual(obj_from_str.mode, 'Undergraduate Full-Time')
    32         self.assertEqual(obj_from_str.author, 'Bob')
    33         return
    34 
    35     #def test_str(self):
    36     #    # StudentsReport provide a nice string representation
    37     #    obj = StudentsReport(2010, 'Undergraduate Full-Time', author='Bob')
    38     #    self.assertEqual(
    39     #        obj.__str__()[:65],
    40     #        'Students Report '
    41     #        '[session=2010/2011, mode=Undergraduate Full-Time]')
    42     #    return
    4322
    4423    def test_title(self):
  • main/waeup.kofa/trunk/src/waeup/kofa/tests/test_reports.py

    r9670 r9672  
    211211        return
    212212
    213     def test_description(self):
    214         # IReportJobs provide a description of the started job
    215         self.register_generator('report1')
    216         args, kw = ['a', 'b'], dict(a=1, b=2)
    217         job = AsyncReportJob(self.root_folder, 'report1', args=args, kw=kw)
    218         self.assertEqual(
    219             job.description,
    220             "Report 1 ('a', 'b', 1, 2)")
    221         # w/o args nor kwargs
    222         job = AsyncReportJob(self.root_folder, 'report1')
    223         self.assertEqual(
    224             job.description,
    225             'Report 1 ()')
    226         # with args only
    227         job = AsyncReportJob(self.root_folder, 'report1', args=args)
    228         self.assertEqual(
    229             job.description, "Report 1 ('a', 'b')")
    230         # with keywords only
    231         job = AsyncReportJob(self.root_folder, 'report1', kw=kw)
    232         self.assertEqual(
    233             job.description, "Report 1 (1, 2)")
    234         return
    235 
    236     def test_description_invalid_generator(self):
    237         # We can get a description even with an invalid generator
    238         job = AsyncReportJob(self.root_folder, 'NOT EXISTENT')
    239         self.assertEqual(
    240             job.description, u'Unregistered Report Generator ()')
    241         # with args set (no kws)
    242         job = AsyncReportJob(
    243             self.root_folder, 'NOT EXISTENT', args=['a', 'b'])
    244         self.assertEqual(
    245             job.description, u"Unregistered Report Generator ('a', 'b')")
    246         # with kw set (no args)
    247         job = AsyncReportJob(
    248             self.root_folder, 'NOT_EXISTENT', kw=dict(a=1, b=2))
    249         self.assertEqual(
    250             job.description, u'Unregistered Report Generator (1, 2)')
    251         # with args and kws set
    252         job = AsyncReportJob(
    253             self.root_folder, 'NOT_EXISTENT', args=['a'], kw=dict(b=2))
    254         self.assertEqual(
    255             job.description, u"Unregistered Report Generator ('a', 2)")
    256         return
    257 
    258     def test_report_status(self):
    259         # We can get a report status apart from the job status
    260         job = AsyncReportJob(self.root_folder, 'report1')
    261         self.assertEqual(job.report_status, u'running')
    262         return
    263 
    264     def test_report_status_failed(self):
    265         # A failed job is reflected in report_status
    266         job = AsyncReportJob(self.root_folder, None) # no report generator
    267         setSite(self.root_folder)
    268         self.assertTrue(job.failed is None)
    269         manager = getUtility(IJobManager)
    270         manager.put(job)
    271         wait_for_result(job)
    272         self.assertEqual(job.report_status, u'FAILED')
    273         return
    274 
    275     def test_report_status_finished(self):
    276         # A finished report is reflected in report_status
    277         job = AsyncReportJob(self.root_folder, 'report1')
    278         setSite(self.root_folder)
    279         manager = getUtility(IJobManager)
    280         manager.put(job)
    281         wait_for_result(job)
    282         self.assertEqual(job.report_status, u'finished')
    283         return
    284 
    285213class FakeJobWithResult(FakeJob):
    286214
     
    383311            [('new', u'new', u'Report 1'),
    384312             ('completed', u'completed', u'Report 1')]
    385             )
    386         return
    387 
    388     def test_get_report_job_description(self):
    389         # we can get the descriptions of jobs...
    390         container = ReportJobContainer()
    391         container.start_report_job('report1', 'alice')
    392         container.start_report_job('report1', 'bob')
    393         result = container.get_report_jobs_description(user_id='bob')
    394         # we'll get the job id, a description and the status
    395         self.assertEqual(
    396             result,
    397             [('2', 'Report 1 ()', u'running', False, False, True, None, 'bob'),]
    398313            )
    399314        return
Note: See TracChangeset for help on using the changeset viewer.