Beispiel #1
0
def make_requirement(sr: Sequence[SubmissionRequirements],
                     descriptors: Sequence[InputDescriptors]) -> Requirement:
    if not sr:
        sr = []
    if not descriptors:
        descriptors = []
    if len(sr) == 0:
        requirement = Requirement(
            count=len(descriptors),
            input_descriptors=descriptors,
        )
        return requirement
    requirement = Requirement(
        count=len(sr),
        nested_req=[],
    )
    for tmp_sub_req in sr:
        try:
            requirement.nested_req.append(
                to_requirement(tmp_sub_req, descriptors))
        except Exception as err:
            print(
                f"Error creating requirement inside to_requirement function, {err}"
            )

    return requirement
    def export_rss(self, req, requirement):
        db = self.env.get_db_cnx()
        model = Requirement(self)
        changes = []
        change_summary = {}

        description = wiki_to_html(requirement['description'], self.env, req, db)
        req.hdf['requirement.description.formatted'] = unicode(description)

        for change in model.grouped_changelog_entries(requirement, db):
            changes.append(change)
            # compute a change summary
            change_summary = {}
            # wikify comment
            if 'comment' in change:
                comment = change['comment']
                change['comment'] = unicode(wiki_to_html(
                        comment, self.env, req, db, absurls=True))
                change_summary['added'] = ['comment']
            for field, values in change['fields'].iteritems():
                if field == 'description':
                    change_summary.setdefault('changed', []).append(field)
                else:
                    chg = 'changed'
                    if not values['old']:
                        chg = 'set'
                    elif not values['new']:
                        chg = 'deleted'
                    change_summary.setdefault(chg, []).append(field)
            change['title'] = '; '.join(['%s %s' % (', '.join(v), k) for k, v \
                                             in change_summary.iteritems()])
        req.hdf['requirement.changes'] = changes
        return (req.hdf.render('requirement_rss.cs'), 'application/rss+xml')
    def test_job_transmission(self):
        self.awake_single()
        # campaignをセット
        campaign = Campaign(author="cxxx0",
                            requirement=Requirement(values=["zero", "random"],
                                                    trigger={"timer": 1}),
                            trigger={"timer": 5},
                            place="All",
                            purpose="test_purpose",
                            destination="mongodb://localhost:27017/")
        clients["cxxx0"].post('/commander/campaigns',
                              data=json.dumps(campaign.to_dict()),
                              content_type='application/json')
        time.sleep(1.5)  # heartbeatを待つ; 0.7 + 0.4 + alpha

        # missionを確認
        mission = Mission(author="lxxx0",
                          requirement=Requirement(values=["zero", "random"],
                                                  trigger={"timer": 1}),
                          trigger={"timer": 5},
                          place="All",
                          purpose=campaign.get_id())
        self.assertIn(mission, self.models["lxxx0"].missions.values())

        # orderを確認
        order = Order(author="sxxx0",
                      values=["zero", "random"],
                      trigger={"timer": 1},
                      purpose=mission.get_id())
        self.assertIn(order, self.models["sxxx0"].orders.values())
Beispiel #4
0
    def process_request(self, req):
        req.perm.assert_permission('REQUIREMENT_VIEW')
        
        if req.perm.has_permission('REQUIREMENT_CREATE'):
            req.hdf['report.add_requirement_href'] = req.href.newrequirement()

        req.hdf['report.edit_fphyp_href'] = req.href('editdict', 'fp')

        db = self.env.get_db_cnx()

        report = req.args.get('report', '')

        # only for use in reports showing (nearly) all requirements
        if (report == '1' or report == '2' or report == '3'):
            # flag the report to use the validation button
            req.hdf['report.is_all_reqs_report'] = 1

            myreq = Requirement(self.env)
            req.hdf['report.currently_validated'] = \
                myreq.get_current_reqs_validated()
            validation_time = myreq.get_most_recent_validation()
            if validation_time is not None:
                req.hdf['report.latest_validation'] = \
                    format_datetime(validation_time)
            else:
                req.hdf['report.latest_validation'] = '(None)'

            # get the value from the validation button if it exists:
            if req.method == 'POST':
                validate = req.args.get('ValidateSubmit', '')
                if validate == 'Validate':
                    # set this flag...
                    # ... and validate the current set of requirements:
                    if myreq.validate_requirements():
                        req.hdf['report.validate'] = 2
                        req.hdf['report.latest_validation'] = format_datetime()
                    else:
                        req.hdf['report.validate'] = 1
                        
                    
        if report is not '':
            add_link(req, 'up', req.href('requirements', 'report'))

        resp = self._render_view(req, db, report)
        if not resp:
           return None
        template, content_type = resp
        if content_type:
           return resp

        add_stylesheet(req, 'hw/css/req_report.css')
        return 'req_report.cs', None
Beispiel #5
0
def to_requirement(sr: SubmissionRequirements,
                   descriptors: Sequence[InputDescriptors]) -> Requirement:
    input_descriptors = []
    nested = []
    total_count = 0

    if sr._from:
        if sr._from != "":
            for tmp_descriptor in descriptors:
                if contains(tmp_descriptor.groups, sr._from):
                    input_descriptors.append(tmp_descriptor)
            total_count = len(input_descriptors)
            if total_count == 0:
                raise Exception(f"No descriptors for from: {sr._from}")
    else:
        for tmp_sub_req in sr.from_nested:
            try:
                # recursion logic
                tmp_req = to_requirement(tmp_sub_req, descriptors)
                nested.append(tmp_req)
            except Exception as err:
                print(
                    f"Error creating requirement from nested submission_requirements, {err}"
                )
        total_count = len(nested)
    count = sr.count
    if sr.rule == "all":
        count = total_count

    requirement = Requirement(count=count,
                              maximum=sr.maximum,
                              minimum=sr.minimum,
                              input_descriptors=input_descriptors,
                              nested_req=nested)
    return requirement
    def test_get_campaigns_single(self):
        # add a campaigns
        campaign = Campaign(author='cxxx0',
                            destination='mongoserv',
                            place='S101',
                            purpose='A great app',
                            requirement=Requirement(values=["zero", "random"],
                                                    trigger={"timer": 10}),
                            trigger={"timer": 30})
        self.app.post('/commander/campaigns',
                      data=json.dumps(campaign.to_dict()),
                      content_type='application/json')

        # get subordinates
        response = self.app.get('/commander/campaigns')
        self.assertEqual(response.status_code, 200)
        actual = json.loads(response.data.decode("utf-8"))

        # assert
        expected = {
            "_status": {
                'success': True,
                'msg': "status is ok"
            },
            'campaigns': [campaign.to_dict()]
        }
        self.assertEqual(actual, expected)
    def test_add_campaign(self):
        # 各種パラメータの詳細が決まっていないため、暫定値を採用。
        # 最終的には、API自体に無効な入力パラメータをハネる機能を搭載したうえで
        # TODO: 無効値を確認する用のテストを作成すべき
        campaign = Campaign(author='cxxx0',
                            destination='mongoserv',
                            place='S101',
                            purpose='A great app',
                            requirement=Requirement(values=["zero", "random"],
                                                    trigger={"timer": 10}),
                            trigger={"timer": 30})
        response = self.app.post('/commander/campaigns',
                                 data=json.dumps(campaign.to_dict()),
                                 content_type='application/json')
        self.assertEqual(response.status_code, 200)
        actual = json.loads(response.data.decode("utf-8"))

        expected = {
            "_status": {
                'success': True,
                'msg': "status is ok"
            },
            "accepted": campaign.to_dict()
        }
        self.assertEqual(actual, expected)
Beispiel #8
0
def create_requirement(type):
	"""Create and return requirement"""
	requirement = Requirement(type=type)
	db.session.add(requirement)
	db.session.commit()

	return requirement 
Beispiel #9
0
    def test_get_missions_multi(self):
        # add some missions
        mission_base = Mission(author='lxxx0',
                               place='on desk',
                               purpose='A great app',
                               requirement=Requirement(
                                   values=["zero", "random"],
                                   trigger={"timer": 10}),
                               trigger={"timer": 30})
        mission_list = []
        for purpose in ['on chair', 'front of door', 'on desk', 'living room']:
            m = copy.deepcopy(mission_base)
            m.purpose = purpose
            mission_list.append(m)

        for m in mission_list:
            self.leader_obj.accept_mission(m)

        # get missions
        response = self.app.get('/leader/missions')
        self.assertEqual(response.status_code, 200)
        actual = loads(response.data.decode("utf-8"))
        actual_list = actual['missions']

        # assert status
        expected_status = {'success': True, 'msg': "status is ok"}
        self.assertEqual(actual['_status'], expected_status)

        # assert items
        expected_list = [c.to_dict() for c in mission_list]
        self.assertEqual(len(actual_list), len(expected_list))
        for exp in expected_list:
            if exp not in actual_list:
                self.fail('{0} is not found.'.format(exp))
        pass
Beispiel #10
0
    def _do_modify(self, req, db):
        self._do_arg_checks(req)
        component = req.args.get('component')
        fp = Fp(self.env, name=req.args.get('fp'))
        object = Object(self.env, name=req.args.get('object'))

        requirement = Requirement(self.env, component, fp['id'], object['id'], 
                                 db)

        status = requirement['status']
        requirement.populate(req.args)
        requirement['fp'] = fp['id']
        requirement['object'] = object['id']
        requirement['status'] = status

        now = int(time.time())
        cnum = req.args.get('cnum')
        replyto = req.args.get('replyto')
        internal_cnum = cnum
        if cnum and replyto:
            internal_cnum = '%s.%s' % (replyto, cnum)
    
        if (status != 'disabled' and req.args.get('status') != 'on') \
            or \
           (status == 'disabled' and req.args.get('status') == 'on'):

            req.perm.assert_permission('REQUIREMENT_DISENABLE')
            
            if req.args.get('status') == 'on':
                requirement['status'] = 'enabled'
            else:
                requirement['status'] = 'disabled'
            
        if requirement.save_changes(get_reporter_id(req, 'author'),
                                    req.args.get('comment'), when=now, db=db,
                                    cnum=internal_cnum):
            db.commit()

            # Notify
            try:
                rn = RequirementNotifyEmail(self.env)
                rn.notify(requirement, newrequirement=False)
            except Exception, e:
                self.log.exception("Failure sending notification on creation "
                                   "of requirement <%s %s>: %s" % 
                                   (fp['name'], object['name'], e))
Beispiel #11
0
    def _do_create(self, req, db=None):
        if not req.args.get('component'):
            raise TracError('Requirements must contain a component.')
        
        if not req.args.get('fp'):
            raise TracError('Requirements must contain a functional primitive.')
        
        if not req.args.get('object'):
            raise TracError('Requirements must contain an object.')

        requirement = Requirement(self.env, db=db)
        requirement.populate(req.args)
        try:
            # if a known hyponym was used, get corresponding fp.
            temp_hyp = Hyponym(self.env, name=req.args.get('fp'), db=db)
            temp_fp = Fp(self.env, id=temp_hyp['fp'], db=db)
        except TracError:
            try:
                #or, if a known fp was used, get instance of Fp
                temp_fp = Fp(self.env, name=req.args.get('fp'), db=db)
            except TracError:
                #run check funtion for enabled adding fp
                #if unknown fp used, insert it into the database
                if(Fp(self.env).check_on_fly_fp() == "enabled"):
                    temp_fp = Fp(self.env, db=db)
                    temp_fp['name'] = req.args.get('fp')
                    temp_fp.insert(db=db)
                else:
                    raise TracError("On the fly creation of Fps disabled")
        requirement.values['fp'] = temp_fp['id']
        try:
            temp_object = Object(self.env, name=req.args.get('object'), db=db)
        except TracError:
        #run check for function enabling obj
            if(Object(self.env).check_on_fly_obj() == "enabled"): 
                temp_object = Object(self.env, db=db)
                temp_object['name'] = req.args.get('object')
                temp_object.insert(db=db)
            else:
                raise TracError("On the fly creation of objects disabled")
        requirement.values['object'] = temp_object['id']
        requirement.values['creator'] = get_reporter_id(req, 'creator')
        requirement.insert(db=db)

        # Notify
        try:
            rn = RequirementNotifyEmail(self.env)
            rn.notify(requirement, newrequirement=True)
        except Exception, e:
            self.log.exception("Failure sending notification on creation of "
                               "requirement <%s %s>: %s" % 
                               (temp_fp['name'], temp_object['name'], e))
Beispiel #12
0
    def process_request(self, req):
        template = 'dashboard.cs'
        add_stylesheet(req, 'hw/css/dashboard.css')

        reports = [('Requirements by Component', 'report/1'), 
                       ('Requirements with Associated Tickets', 'report/5'),
                       ('Most/least Changed Requirements','view/3' ),
                       ('Requirements by Milestone', 'report/7'),
                       ('Disabled Requirements by Component', 'report/8')]

        req.hdf['report_href'] = req.href('requirements', 'report')
        req.hdf['rlist'] = reports
        req.hdf['requirement_href'] = req.href.requirements()

        #Valdation Dashboard Module Data
        tmpreq = Requirement(self.env)
        val_time = tmpreq.get_most_recent_validation()
        if val_time != None:
            req.hdf['recent_val_date'] = format_datetime(val_time)
        else:
            req.hdf['recent_val_date'] = 1
        req.hdf['current_val'] = tmpreq.get_current_reqs_validated()
        req.hdf['show_val_report'] = tmpreq.get_changed_reqs_since_validation()
        req.hdf['req_ood_href'] = req.href('requirements', 'report', '11')
        req.hdf['req_changed_href'] = req.href.requirements('report', '12')
    
        #dashboard header links
        req.hdf['editdict.href_fp'] = req.href('editdict', 'fp')
        req.hdf['requirement.add_requirement_href'] = req.href.newrequirement()
        req.hdf['trac.href.editdict'] = req.href('editdict', 'fp')

        #dashboard graph links
        req.hdf['graph_path'] = req.href.requirements() + '/graph'

        add_link(req, 'top', req.href('requirements', 'report'))
        return (template, None)
Beispiel #13
0
    def process_request(self, req):
        req.perm.assert_permission('REQUIREMENT_CREATE')
        template = 'newrequirement.cs';
        
        # No need to preview a tiny form like this
        if req.method == 'POST' and not req.args.has_key('preview'):
            self._do_create(req)
            
        requirement = Requirement(self.env)
        req.hdf['components'] = requirement.get_components() 
        req.hdf['trac.href.newrequirement'] = req.href.newrequirement()
        req.hdf['trac.href.auto_complete'] = req.href.newrequirement('ajax')

            
        req.hdf['title'] = 'New Requirement'

        # Provide FORM_TOKEN for Ajax POST request
        req.hdf['form_token'] = req.form_token
        

        add_stylesheet(req, 'hw/css/requirement.css')
        add_script(req, 'hw/javascript/prototype.js')
        add_script(req, 'hw/javascript/scriptaculous.js')
        return (template, None)
Beispiel #14
0
    def test_get_campaigns_multi(self):
        # add some campaigns
        campaign_base = Campaign(author='cxxx0',
                                 destination='mongoserv',
                                 place='S101',
                                 purpose='A great app',
                                 requirement=Requirement(
                                     values=["zero", "random"],
                                     trigger={"timer": 10}),
                                 trigger={"timer": 30})
        campaign_list = []
        for place in ['S101', 'S102', 'S103', 'S104']:
            c = copy.deepcopy(campaign_base)
            c.place = place
            campaign_list.append(c)
        for c in campaign_list:
            self.app.post('/commander/campaigns',
                          data=json.dumps(c.to_dict()),
                          content_type='application/json')

        # get campaigns
        response = self.app.get('/commander/campaigns')
        self.assertEqual(response.status_code, 200)
        actual = json.loads(response.data.decode("utf-8"))
        actual_list = actual['campaigns']

        # assert status
        expected_status = {'success': True, 'msg': "status is ok"}
        self.assertEqual(actual['_status'], expected_status)

        # assert items
        expected_list = [c.to_dict() for c in campaign_list]
        self.assertEqual(len(actual_list), len(expected_list))
        for exp in expected_list:
            if exp not in actual_list:
                self.fail('{0} is not found.'.format(exp))
        pass
Beispiel #15
0
    def test_get_missions_single(self):
        # add a mission
        mission = Mission(author='lxxx0',
                          place='on desk',
                          purpose='A great app',
                          requirement=Requirement(values=["zero", "random"],
                                                  trigger={"timer": 10}),
                          trigger={"timer": 30})
        self.leader_obj.accept_mission(mission)

        # get subordinates
        response = self.app.get('/leader/missions')
        self.assertEqual(response.status_code, 200)
        actual = loads(response.data.decode("utf-8"))

        # assert
        expected = {
            "_status": {
                'success': True,
                'msg': "status is ok"
            },
            'missions': [mission.to_dict()]
        }
        self.assertEqual(actual, expected)
Beispiel #16
0
    def process_request(self, req):
        # initialize cache component
        self.cache = DataCache(self.env)

        # Grab arguments
        if re.match(r'/requirements/graph/\w+/?$',req.path_info) is not None:
            m = re.match(r'/requirements/graph/(\w+)/?$', req.path_info)
            (graph,) = m.groups()

            cacheddata = self.cache.get_data(None, None, None, graph)
            if cacheddata:
                data = pickle.loads(cacheddata)
            else:
                # Determine which image generator to call
                canvas = None

                # Initialize requirement (to grab metric data)
                self.requirement = Requirement(self.env)

                # Dashboard Graphs
                if graph[0:12] == 'dash_overall':
                    canvas = self.dash_overall()
                elif graph[0:19] == 'component_req_count':
                    canvas = self.component_req_count()     
                elif graph[0:8] == 'dash_pie':
                    canvas = self.dash_pie()

                # Other Graphs
                elif graph[0:7] == 'entropy':
                    canvas = self.entropy_graph()

                # Extract the image into a string
                data = self._image_data(canvas)

                self.cache.set_data(None, None, None, graph, pickle.dumps(data))
 
        else:
            m = re.match(r'/requirement/graph/(\w+)-(\w+)-(\w+)/(\w+)/?$', req.path_info)
            (component, fp, object, graph) = m.groups()

            cacheddata = self.cache.get_data(component, fp, object, graph)
            if cacheddata:
                data = pickle.loads(cacheddata)
            else:
                # Initialize requirement (to grab metric data)
                self.requirement = Requirement(self.env, component, 
                                              Fp(self.env, name=fp)['id'], 
                                              Object(self.env, name=object)['id'])

                # Determine which image generator to call
                # *** Requirement specific graphs ***
                canvas = None
                if graph[0:3] == 'mls':
                    (mls, width) = graph.split('_')
                    data = self.most_least_cited( int( width ) )
                else:
                    if graph == 'test':
                        canvas = self.test()
                    elif graph[0:17] == 'changes_over_time':
                        ( garbage, garbage, garbage, secs_in_unit ) = graph.split('_')
                        canvas = self.changes_over_time(int(secs_in_unit))
                    elif graph[0:17] == 'tickets_over_time':
                        canvas = self.tickets_over_time()
                    # Extract the image into a string
                    data = self._image_data(canvas)

                self.cache.set_data(component, fp, object, graph, pickle.dumps(data))

        # Send reponse headers & the image string
        req.send_header('content-type', 'image/png')
        req.end_headers()
        req.write(data)

        # Return nothing, as we have done all the work
        return None
Beispiel #17
0
    def test_missoin_do(self):
        def post_report(url, data=None, json=None, etag=None, **kwargs):
            res = requests.Response()
            res.status_code = 200
            res_dict = {
                "_status": {
                    "msg": "ok",
                    "success": True
                },
                "accepted": json
            }
            res._content = dumps(res_dict).encode()
            return res, None

        self.leader_obj.superior_ep = "test://cxxx0/commander/"
        soldier = SoldierInfo(id="sxxx0",
                              name="sol-test",
                              place="left",
                              weapons=[],
                              orders=[])
        self.leader_obj.accept_subordinate(soldier)

        mission = Mission(author="sxxx0",
                          requirement=Requirement(values=["zero", "random"],
                                                  trigger={"timer": 0.4}),
                          trigger={"timer": 0.7},
                          place="All",
                          purpose="some purpose hash")

        work_1 = Work(time=datetime.utcnow().isoformat(),
                      purpose=mission.get_id(),
                      values=[0, 0.584249])
        work_2 = Work(time=datetime.utcnow().isoformat(),
                      purpose=mission.get_id(),
                      values=[0, 0.238491])
        work_3 = Work(
            time=datetime.utcnow().isoformat(),
            purpose="0" + mission.get_id()[:-1],  # 上2つとずらす
            values=[0, 0.045066])
        self.leader_obj.accept_work("sxxx0", work_1)
        self.leader_obj.accept_work("sxxx0", work_2)
        self.leader_obj.accept_work("sxxx0", work_3)

        with patch("utils.rest.post", side_effect=post_report) as m:
            self.leader_obj.accept_mission(mission)
            time.sleep(1)
            self.assertEqual(m.call_count, 1)
            self.assertEqual(
                m.call_args[0][0],
                "test://cxxx0/commander/subordinates/lxxx0/report")

            # reportのチェック
            actual = m.call_args[1]["json"]
            self.assertEqual(set(actual.keys()),
                             {"time", "place", "purpose", "values"})
            self.assertEqual(actual["purpose"], "some purpose hash")
            self.assertEqual(len(actual["values"]), 2)

            # report.valuesのチェック
            work_in_1 = work_1.to_dict()
            del work_in_1["purpose"]
            work_in_1["place"] = "left"
            work_in_2 = work_2.to_dict()
            del work_in_2["purpose"]
            work_in_2["place"] = "left"
            self.assertIn(work_in_1, actual["values"])
            self.assertIn(work_in_2, actual["values"])

        self.leader_obj.superior_ep = ""  # shutdownでDELETEを送信するのを阻止
Beispiel #18
0
class RequirementGraphComponent(Component):
    implements(IRequestHandler)

    # Don't let trac.web.main.process_request use a template on us
    use_template = False

    # Reserve room for a Requirement instance
    requirement = None
 
    # IRequestHandler methods
    def match_request(self, req):
        """
        Match /requirement/graph/component-fp-object/graph_name
        """
        if re.match(r'/requirement/graph/\w+-\w+-\w+/\w+/?$', req.path_info) is not None:
            return True
        elif re.match(r'/requirements/graph/\w+/?$', req.path_info) is not None:
            return True
        else:
            return False

    def process_request(self, req):
        # initialize cache component
        self.cache = DataCache(self.env)

        # Grab arguments
        if re.match(r'/requirements/graph/\w+/?$',req.path_info) is not None:
            m = re.match(r'/requirements/graph/(\w+)/?$', req.path_info)
            (graph,) = m.groups()

            cacheddata = self.cache.get_data(None, None, None, graph)
            if cacheddata:
                data = pickle.loads(cacheddata)
            else:
                # Determine which image generator to call
                canvas = None

                # Initialize requirement (to grab metric data)
                self.requirement = Requirement(self.env)

                # Dashboard Graphs
                if graph[0:12] == 'dash_overall':
                    canvas = self.dash_overall()
                elif graph[0:19] == 'component_req_count':
                    canvas = self.component_req_count()     
                elif graph[0:8] == 'dash_pie':
                    canvas = self.dash_pie()

                # Other Graphs
                elif graph[0:7] == 'entropy':
                    canvas = self.entropy_graph()

                # Extract the image into a string
                data = self._image_data(canvas)

                self.cache.set_data(None, None, None, graph, pickle.dumps(data))
 
        else:
            m = re.match(r'/requirement/graph/(\w+)-(\w+)-(\w+)/(\w+)/?$', req.path_info)
            (component, fp, object, graph) = m.groups()

            cacheddata = self.cache.get_data(component, fp, object, graph)
            if cacheddata:
                data = pickle.loads(cacheddata)
            else:
                # Initialize requirement (to grab metric data)
                self.requirement = Requirement(self.env, component, 
                                              Fp(self.env, name=fp)['id'], 
                                              Object(self.env, name=object)['id'])

                # Determine which image generator to call
                # *** Requirement specific graphs ***
                canvas = None
                if graph[0:3] == 'mls':
                    (mls, width) = graph.split('_')
                    data = self.most_least_cited( int( width ) )
                else:
                    if graph == 'test':
                        canvas = self.test()
                    elif graph[0:17] == 'changes_over_time':
                        ( garbage, garbage, garbage, secs_in_unit ) = graph.split('_')
                        canvas = self.changes_over_time(int(secs_in_unit))
                    elif graph[0:17] == 'tickets_over_time':
                        canvas = self.tickets_over_time()
                    # Extract the image into a string
                    data = self._image_data(canvas)

                self.cache.set_data(component, fp, object, graph, pickle.dumps(data))

        # Send reponse headers & the image string
        req.send_header('content-type', 'image/png')
        req.end_headers()
        req.write(data)

        # Return nothing, as we have done all the work
        return None

    def test(self):
        # Grab a blank, 100x100 image and the color palette
        fig = self._new_image((2,2))
        canvas = FigureCanvasAgg(fig)

        plot = fig.add_subplot(111)
        
        # Return our image
        return canvas

    def entropy_graph(self):
        """Creates a graph of entropy over time for requirements

        This returns an image with each requirement's entropy over
        time shown over the course of the project. If a project is old,
        or there are a lot of requirements, this can be a time consuming 
        process.
        """
        # Image generation prelude.
        fig = self._new_image((4,4))
        canvas = FigureCanvasAgg(fig)
        ax = fig.add_axes([0.1, 0.2, 0.85, 0.75])
        
        # Set up our time range from oldest time to now/newest.
        metric = RequirementMetric(Requirement(self.env))
        start_time = metric.model.get_timestamp_first_entity()
        end_time = metric.model.get_timestamp_latest_req_reqchange_milestone()
        current_time = int(time.time())
        if current_time > end_time:
            end_time = current_time
        
        #create the list of timestamps and make labels.
        times = []
        timestamp = end_time
        # We'll use two week increments for now to reduce 
        # delay while loading. 
        seconds_in_unit = (60 * 60 * 24 * 7 * 2)
        while timestamp > start_time:
            times.append(timestamp)
            timestamp -= seconds_in_unit        
        times.reverse()
        labels = [time.strftime("%b %d '%y",time.gmtime(timestamp)) \
                  for timestamp in times]

        # Create the coordinates lists for graphing
        coords = {}
        i = 0
        for timestamp in times:
            i = i + 1
            if timestamp > current_time:
                break;
            entropy_data = metric.entropy(timestamp)
            if entropy_data:
                _,_,_, req_entropies, _, _ = entropy_data
                for key in req_entropies.keys():
                    if not coords.has_key(key):
                        coords[key] = [(i, req_entropies[key])]
                    else:
                        coords[key].append((i, req_entropies[key]))

        biggest = []
        # Now we can actually graph them all
        for req in coords.keys():
            x = [x[0] for x in coords[req]]
            y = [y[1] for y in coords[req]]
            biggest.append(max(y))
            ax.plot(x,y,'k-')

        # Add the milestone markers.
        milestones = Requirement(self.env).get_milestones()
        x = []
        for (_, due) in milestones:
            if due == 0:
                continue
            x.append( float(due - times[0]) / float( seconds_in_unit))
        height = int(float(max(biggest)) + 1.5) 
        ax.vlines(x, 0, height,colors='r')
        # Label and shape the graph

        ax.set_xticks(range(0, len(times), 1))
        ax.set_xticklabels(labels)
        ax.set_xlim(0, len(times))
        setp(ax.get_xticklabels(),'rotation', 80, fontsize=6)
        ax.set_xlabel('Time in two-week increments', fontsize=6)
        
        ax.set_yticks(arange(0,height, 1))
        ax.set_ylim(0, height)
        setp(ax.get_yticklabels(), fontsize=6)
        ax.set_ylabel("Entropy", fontsize=6)

        return canvas

    def tickets_over_time(self):
        fig = self._new_image((3,3))
        canvas = FigureCanvasAgg(fig)
        when = now = int(time.time())
        month=['Jan','Feb','Mar','Apr','May','Jun',
        'Jul','Aug','Sep','Oct','Nov','Dec']
        numMonth=datetime.date.today().month
        dates={}        

        #rotates months to puts the current month 
        #as the last month in the array
        # FIXME: there has to be a simpler/clearer/faster
        # way to do this. (modulus and offsets?)
        for j in range(0,12):
            dates[j+1]=month[j]
        current=dates[numMonth]

        while(month[11]!=current):
            tempMonth=month[0]
            for i in range(0,11):
                month[i]=month[i+1]
            month[11]=tempMonth

        valEnh=[0,0,0,0,0,0,0,0,0,0,0,0]
        valDef=[0,0,0,0,0,0,0,0,0,0,0,0]
        valTas=[0,0,0,0,0,0,0,0,0,0,0,0]
       
        for i in range(11, -1, -1):
            metrics = self.requirement.get_tickets_over_time_metrics(when)
            for metric in metrics:
                type, count = metric
                if type == 'task':
                    valTas[i] = count
                elif type == 'defect':
                    valDef[i] = count
                elif type == 'enhancement':
                    valEnh[i] = count
                
            when = when - (3600 * 24 * 30)
        
        maxVal = max([max(valEnh), max(valDef), max(valTas)]) #the maximum value
        if maxVal == 0:
            # If there are no tickets ever associated, return blank
            # image instead of empty graph.
            return canvas
        # If we have usable data (tickets reference this requirement)
        # then we will graph them by month.
        ax=fig.add_subplot(111)
        num = 12 #the total number of values
        ind = arange(num)  # the x locations for the groups
        if maxVal > 20: # sets how often the y-axis increments
            inc = maxVal / 10
        else:
            inc=1
        width=.2 # sets the width of the bars
        
        maxY = maxVal + 5
        
        p1 = ax.bar(ind,valEnh, width=width, align='center',color='b')
        p2 = ax.bar(ind+width,valTas, width=width, align='center',color='g')
        p3 = ax.bar(ind+2*width,valDef, width=width, align='center',color='r')
        ax.set_xticks(ind+((3/2)*width))
        ax.set_xticklabels(month)
        ax.set_xlim(-width,len(ind))
        setp(ax.get_xticklabels(),'rotation', 45, fontsize=8)
        ax.set_yticks(arange(0,maxY,(inc)))
        ax.set_ylim(0,maxY)
        # Return 
        return canvas


    def component_req_count(self):
        """Show graph of how many requirements each component has.

        This returns a canvas drawn with matplotlib's backend graphics
        tools for display on the requirements dashboard. This graph
        list all components so they can be compared by their number
        of associated (active) requirements. This is one way of 
        describing a components relative 'size' and 'importance' in 
        relation to the other components.
        """
        cr_list = Requirement(self.env).get_component_req_count()
        count = len(cr_list)

        #heres a trick to cycle colors. Can add more base colors later.
        base_colors = ['b', 'g', 'r', 'c', 'm']
        colors = [base_colors[x % 5] for x in range(count)]

        fig = self._new_image((5,4))
        canvas = FigureCanvasAgg(fig)
        ax = fig.add_axes([0.08, 0.35, 0.9, 0.6])
        
        #extract the labels and values from cr_list
        labels = [x[0] for x in cr_list]
        y = [y[1] for y in cr_list]
        
        #establish height of y axis
        if max(y) == 0:
            height = 5
        elif max(y) % 5 == 0:
            height = max(y)
        else:
            height = max(y) + 5 - (max(y) % 5)

        
        #relative width of each bar
        width = 1 
        
        #scale vertically
        if height >= 20:
            inc = height/10
        else:
            inc = 1
        
        #position labels appropriately for horizontal scaling
        if count > 20:
            label_offset = 0
            if count > 30:
                rotation = 80
        else:
            label_offset = .5*width
            rotation = 60

        #set the horizontal points
        x = arange(0,count * width, width)

        #draw the graph
        p1 = ax.bar(x, y, width=width, color=colors)

        #set the x axis labels
        ax.set_xticks(x + label_offset)
        ax.set_xticklabels(labels)
        ax.set_xlim(0,count)
        setp(ax.get_xticklabels(), 'rotation',rotation,fontsize=6)

        #set the y axis labels
        ax.set_yticks(arange(0,height + 1, (inc)))
        ax.set_ylim(0,height)

        #we're done!
        return canvas


    def changes_over_time(self, seconds_in_unit=60):
        fig = self._new_image((3,3))
        canvas = FigureCanvasAgg(fig)

        (time_created, times_changed) = self.requirement.get_changes_metrics()
        
        ax = fig.add_subplot(111)
        
        # Obtain the timestamp of the first entity every created and treat
        # that as the projects start time since there is no available project
        # start time.
        proj_start_time = self.requirement.get_timestamp_first_entity()
        
        # Obtain the largest timestamp of either a milestone, requirement,
        # or a requirement change.
        most_recent_time = self.requirement.get_timestamp_latest_req_reqchange_milestone()
        
        # Obtain the current time.
        current_time = int(time.time())
        
        if (current_time > most_recent_time):
            most_recent_time = current_time
        
        # Obtain all the milestones and their associated due dates in
        # seconds since epoch.
        milestones = self.requirement.get_milestones()
        tot_horiz_units = int((most_recent_time - proj_start_time) / seconds_in_unit)
       
        # Initialize base variables
        height=10
        startY=0
        startX=time_created
        
        # Obtain the amount of time between each change made to the
        # requirement, and place them in an array
        valid_change_offsets = []
        prev_time = time_created
        for cur_time in times_changed:
            if (cur_time != prev_time):
                cur_horiz_unit_offset = int(((cur_time - prev_time) / seconds_in_unit))
                valid_change_offsets.append(cur_horiz_unit_offset)
                prev_time = cur_time
        
        # Append the amount of time between the last change and
        # the current time to the array
        cur_horiz_unit_offset = int(((current_time - prev_time) / seconds_in_unit))
        valid_change_offsets.append(cur_horiz_unit_offset)

        # Set the point where the requirement will begin graphing
        cur_x_pos = int((time_created - proj_start_time) / seconds_in_unit)
        
        height=1
        startX=0
        startY=0
        tot_horiz_units = ((most_recent_time - proj_start_time) / seconds_in_unit)
        
        #setup a blank template for y-axis increments
        graphSegments=[]
        for unit in range(0,tot_horiz_units):
            graphSegments.append(0)
	
        # Graph the requirement
        for cur_x_offset in valid_change_offsets:
            ax.broken_barh([ (cur_x_pos, cur_x_offset)] , (startY, height), facecolors='blue')
            cur_x_pos += cur_x_offset
            startY += height
            
        # Graph the milestones
        for (garbage, milestone_due) in milestones:
            if milestone_due == 0:
                continue
            milestone_x_pos = int((milestone_due - proj_start_time) / seconds_in_unit)
            ax.axvline(milestone_x_pos, color='r')
        last_date=milestone_due
	
	if last_date == 0:
            last_date = current_time
        
        # Set the limits and ticks of the graph
        x_tick_lines=[]
        for i in range(0, (tot_horiz_units + 1)):
            x_tick_lines.append(i)
        ax.set_xticks(x_tick_lines)
        ax.set(xticklabels=[])
        ax.set_yticks(arange(0,(startY+height),height))
        
        # Return our image
        return canvas
        
    def most_least_cited( self, width ):
        """This is the only function using gd, so we handle it more 
        directly for now.

        """
        image = gd.image((10*width, 10))
        image.filledRectangle((0,0),(10*width-1, 10), image.colorAllocate((255,0,0)))
        buffer = cStringIO.StringIO()
        image.writePng(buffer)
        data = buffer.getvalue()
        buffer.close()

        return data

    def dash_overall(self, seconds_in_unit=604800):
        fig = self._new_image((5,5))
        canvas = FigureCanvasAgg(fig)
        ax = fig.add_subplot(111)

        # Obtain the timestamp of the first entity every created and treat
        # that as the projects start time since there is no available project
        # start time.
        proj_start_time = self.requirement.get_timestamp_first_entity()
        start_time = proj_start_time 
        # Obtain the largest timestamp of either a milestone, requirement,
        # or a requirement change.
        most_recent_time = self.requirement.get_timestamp_latest_req_reqchange_milestone()
        
        # Obtain the current time.
        current_time = int(time.time())
        if (current_time > most_recent_time):
            most_recent_time = current_time
        #This is the bargraph portion
        #Initialize variables
        width = 1
        val = []       
        xTime = current_time
        endTime = proj_start_time #current_time - (31536000)
        
        #Get data
        while(xTime >= endTime):
            val.append(self.requirement.get_num_changes(endTime,endTime+seconds_in_unit))
            endTime+=seconds_in_unit
       

        ind = arange(len(val))  # the x locations for the groups
        
        #Create bargraph
        graphBar = ax.bar(ind,val,width=width, color='y')
        
        #This is the line graph portion
        #   this shows the number of active requirements
        #Initialize Variables
        #Get data
        #get the total number of requirements
        #       at each given time
        checktime=proj_start_time
        yValues=[]
        while checktime <= current_time+seconds_in_unit:
            yValues.append(self.requirement.get_num_req(checktime))
            checktime+=seconds_in_unit
        xValues=[]
        for _ in range(0,len(yValues)):
            xValues.append(_) 
        
        #Create Line graph
        lineGraph=ax.plot(xValues,yValues)                

        #create the list of timestamps and make labels.
        times = []
        timestamp = current_time
        # We'll use two week increments for now to reduce 
        # delay while loading. 
        while timestamp > start_time:
            times.append(timestamp)
            timestamp -= seconds_in_unit        
        times.reverse()
        labels = [time.strftime("%b %d '%y",time.gmtime(timestamp)) \
                  for timestamp in times]



        maxY=max(max(val),max(yValues))
        if maxY < 20:
            maxY+=5
        else:
            maxY=int(maxY*1.5)
        
        #This is the triangles portion
        #   this is the validation points
        #Initialize Variables
        #Get data
        valTimes=[]
        valTimes=self.requirement.get_val_times()
        valHeight=[]
        temp=[]

        if len(valTimes) is not 0:
            for elem in valTimes:
                valHeight.append(maxY*0.9)
                temp.append(int((elem - proj_start_time) / seconds_in_unit))
            valTimes=temp
            #Create triangles graph
            #use a scatterplot maybe and make each point for the graph be a triangle
            validationGraph=ax.scatter(valTimes,valHeight,color='g', marker='^', linewidth=5)


        #This is the milestones portion
        #Initialize Variables
        
        #Get data
        

        # Obtain all the milestones and their associated due dates in
        # seconds since epoch.
        milestones = self.requirement.get_milestones()
        tot_horiz_units = ((most_recent_time - proj_start_time) / seconds_in_unit)
        
        #Create line for milestones graph
        for (garbage, milestone_due) in milestones:
            if milestone_due == 0:
                continue
            milestone_x_pos = int((milestone_due - proj_start_time) / seconds_in_unit)
            #axvline(x=milestone_x_pos, xymin=0,ymax=100, color='r')
            milestoneBar = ax.bar(milestone_x_pos+0.5,maxY,width=(0),
                                    color='r', edgecolor='r')
        ax.set_xticklabels(labels)
        ax.set_xlim(0, len(times))
        setp(ax.get_xticklabels(),'rotation', 80, fontsize=6)
        
 
        #format the graph
        #ax.set_xlim(proj_start_time,most_recent_time)
        ax.set_ylim(0,maxY)
        #return the graph
        return canvas

    def dash_pie(self):
        fig = self._new_image((4,4))
        canvas = FigureCanvasAgg(fig)

        ax = fig.add_axes([0.1, 0.1, 0.8, 0.8])

        fracs = []

        vals = Requirement(self.env).get_type_req_tickets()
        
        total = 0
        for val in vals:
            total += val

        labels = []
        if total == 0:
            labels = ['None']
            fracs = [1]
        else:
            if vals[0] != 0:
                labels.append('Open')
                fracs.append(float(vals[0]) / float(total))
            if vals[1] != 0:
                labels.append('Closed')
                fracs.append(float(vals[1]) / float(total))
            if vals[2] != 0:
                labels.append('None')
                fracs.append(float(vals[2]) / float(total))

        labels = tuple(labels)

        ax.pie(fracs, labels=labels, autopct='%1.1f%%')

        return canvas

    def _new_image(self, (width,height)):
        # Return the blank figure
        return Figure(figsize=(width,height)) 
Beispiel #19
0
    def process_request(self, req):
        template = 'requirement.cs';
        db = self.env.get_db_cnx()

        if req.method == 'POST' and 'creator' in req.args and \
                not req.perm.has_permission('REQUIREMENT_MODIFY'):
            del req.args['creator']
        
        if req.method == 'POST': 
            self._do_modify(req, db)
        else:
            (component, fp, object) = self._get_requirement_parts(req)
            fp = Fp(self.env, name=fp)
            object = Object(self.env, name=object)
            requirement = Requirement(self.env, component, fp['id'], 
                                     object['id'], db)
            req.hdf['components'] = requirement.get_components() 
            req.hdf['requirement'] = requirement.values
            req.hdf['fp'] = fp['name']
            req.hdf['object'] = object['name']
            req.hdf['requirement.created'] = format_datetime(requirement.time_created)
            req.hdf['requirement.created_delta'] = pretty_timedelta(requirement.time_created)
            if requirement.time_changed != requirement.time_created:
                req.hdf['requirement'] = {
                    'lastmod': format_datetime(requirement.time_changed),
                    'lastmod_delta': pretty_timedelta(requirement.time_changed)
                }

            for field in RequirementSystem(self.env).get_requirement_fields():
                if field['type'] in ('radio', 'select'):
                    value = requirement.values.get(field['name'])
                    options = field['options']
                    if value and not value in options:
                        options.append(value)
                    field['options'] = options
                name = field['name']
                del field['name']
                if name in ('component', 'fp', 'object', 'status', 'creator', 'description'):
                    field['skip'] = True
                req.hdf['requirement.fields.' + name] = field

            req.hdf['requirement.description.formatted'] = wiki_to_html(
                requirement['description'], self.env, req, db)

            replyto = req.args.get('replyto')
            req.hdf['requirement'] = {
                'href': req.href.requirement('%s-%s-%s' % (requirement.component,
                                                           fp['name'],
                                                           object['name'])),
                'replyto': replyto
            }
            def quote_original(author, original, link):
                if not 'comment' in req.args: # i.e. the comment was not yet edited
                    req.hdf['requirement.comment'] = '\n'.join(
                        ['Replying to [%s %s]:' % (link, author)] +
                        ['> %s' % line for line in original.splitlines()] + [''])

            if replyto == 'description':
                quote_original(requirement['creator'], requirement['description'],
                               'requirement:%s-%s-%s' % (requirement.component,
                                                         fp['name'],
                                                         object['name']))

            replies = {}
            changes = []
            cnum = 0
            description_lastmod = description_author = None
            for change in self.grouped_changelog_entries(requirement, db):
                changes.append(change)
                # wikify comment
                comment = ''
                if 'comment' in change:
                    comment = change['comment']
                    change['comment'] = wiki_to_html(comment, self.env, req, db)

                cnum = change['cnum']
                # keep track of replies threading
                if 'replyto' in change:
                    replies.setdefault(change['replyto'], []).append(cnum)
                # eventually cite the replied to comment
                if replyto == str(cnum):
                    quote_original(change['author'], comment,
                                   'reqcomment:%s' % replyto)

                if 'description' in change['fields']:
                    change['fields']['description'] = ''
                    description_lastmod = change['date']
                    description_author = change['author']

            req.hdf['requirement'] = {
                'changes': changes,
                'replies': replies,
                'cnum': cnum + 1
                }

            if description_lastmod:
                req.hdf['requirement.description'] = {'lastmod': description_lastmod,
                                                      'author': description_author}

        req.hdf['title'] = 'Requirements'
        req.hdf['graph_path'] = req.href.requirement() + '/graph/'

        actions = RequirementSystem(self.env).get_available_actions(requirement, req.perm)
        for action in actions:
            req.hdf['requirement.actions.' + action] = '1'

        add_stylesheet(req, 'common/css/code.css')
        add_stylesheet(req, 'hw/css/requirement.css')
        return (template, None)