def __read(self, tname, input_handler, commit, file_info, req_set): '''Read in the topic and create all the tags.''' self.__tags = TxtRecord.from_string(file_info.get_content(), tname, input_handler.get_txt_io_config()) for tag in self.__tags: # If the topic has subtopics, read them also in. if tag.get_tag() == "SubTopic": lfile_info = input_handler.get_file_info_with_type( commit, "topics", tag.get_content() + ".tic") ntopic = Topic(self.__topicset, self._config, input_handler, commit, lfile_info, req_set) # The topic itself is already added in the constrcutor of Topic. # Therefore there is no need to add it here (again). # self.__topicset.add_node(ntopic) self.__topicset.create_edge(self, ntopic) elif tag.get_tag() == "Name": if self.__topic_name != None: # TODO: Multiple Names assert (False) self.__topic_name = tag.get_content() elif tag.get_tag() == "IncludeRequirements": if tag.get_content() != "full": raise RMTException( 113, "IncludeRequirements value not " "supported [%s]" % tag.get_content(), self.get_name()) self.__requirements = req_set.restrict_to_topics(tname) tracer.debug( "Found [%d] requirements for topic [%s]." % (self.__requirements.get_requirements_cnt(), tname)) # Check for the existence of the name if self.__topic_name == None: raise RMTException(62, "Mandatory tag 'Name' not given in topic", self.get_name())
def __read(self, tname, input_handler, commit, file_info, req_set): '''Read in the topic and create all the tags.''' Encoding.check_unicode(tname) self.__tags = TxtRecord.from_string(file_info.get_content(), tname, input_handler.get_txt_io_config()) for tag in self.__tags: # If the topic has subtopics, read them also in. if tag.get_tag() == "SubTopic": lfile_info = input_handler.get_file_info_with_type( commit, "topics", tag.get_content() + ".tic") ntopic = Topic(self.__digraph, self._config, input_handler, commit, lfile_info, req_set) self.__digraph.add_node(ntopic) Digraph.create_edge(self, ntopic) elif tag.get_tag() == "Name": if self.__topic_name is not None: # There can (currently) be only one name assert False self.__topic_name = tag.get_content() elif tag.get_tag() == "IncludeRequirements": if tag.get_content() != "full": raise RMTException( 113, "IncludeRequirements value not " "supported [%s]" % tag.get_content(), self.name) self.__requirements = req_set.restrict_to_topics(tname) tracer.debug("Found [%d] requirements for topic [%s]", self.__requirements.get_requirements_cnt(), tname) # Check for the existence of the name if self.__topic_name is None: raise RMTException(62, "Mandatory tag 'Name' not given in topic", self.name)
def create_requirement_status(config, rid, l): for rs in [RequirementStatusNotDone, RequirementStatusAssigned, RequirementStatusFinished]: if l.startswith(rs.tval): return rs(config, rid, l) raise RMTException(91, "%s: Status tag invalid '%s'" % (rid, l))
def generate(self, config, rid, txt): """Generate a RequirementsStatus object based on the parameters""" txt_split = txt.split(':') try: return self.__plugin_manager[txt_split[0]].plugin(config, rid, txt) except KeyError: raise RMTException(91, "%s: Status tag invalid '%s'" % (rid, txt))
def find_wt(self, name): '''Get the node with the given name. Throw if not available.''' res = self.find(name) if res == None: raise RMTException(23, "node with name '%s' not available" % name) return res
def get_named_node(self, name): """Mostly the same as before, but throws if the node can not be found.""" res = self.get_named_node_no_throw(name) if res is None: raise RMTException(23, "node with name '%s' not available" % name) return res
def __create_local_ce3s(self): '''Create the local Constraint Execution Environments and evaluate the given statements. This method does two things: - evaluating the constraints in the CE3 - Resetting the 'Constraints' entry in the requirement (instead of the TextRecord a map of name to constraint object is stored).''' tracer.debug("Called.") for req_name, req in self.__requirements.items(): # In each case store a (maybe empty) CE3 in the set. ce3 = CE3() cstrnts = req.get_value("Constraints") if cstrnts is not None: sval = json.loads(cstrnts.get_content()) ctr_dict = {} for ctr in sval: ctr_name = self.get_ctr_name(ctr) if ctr_name not in self.__constraints: raise RMTException(88, "Constraint [%s] does not " "exists" % ctr_name) rcs = self.__constraints.get(ctr_name) ce3.eval(rcs, ctr_name, ctr) ctr_dict[ctr_name] = rcs req.set_value("Constraints", ctr_dict) # Store the fresh create CE3 into the ce3set self.__ce3set.insert(req_name, ce3) tracer.debug("Finished. Number of constraints [%d]", self.__ce3set.length())
def parse_date(rid, ds): try: return datetime.datetime.strptime(ds, "%Y-%m-%d").date() except ValueError: raise RMTException( 8, "%s: invalid date specified (must be " "YYYY-MM-DD) was '%s'" % (rid, ds))
def execute(self, executor, func_prefix): '''Execute the parts which are needed for TopicsContinuum.''' tracer.debug("Calling pre [%s]", self.name) FuncCall.pcall(executor, func_prefix + "topic_pre", self) tracer.debug("Calling sub [%s]", self.name) for tag in self.__tags: rtag = tag.get_tag() if rtag == "Name": FuncCall.pcall(executor, func_prefix + "topic_name", tag.get_content()) continue if rtag == "SubTopic": subtopic = self.__digraph.find(tag.get_content()) assert subtopic is not None FuncCall.pcall(executor, func_prefix + "topic_sub_pre", subtopic) subtopic.execute(executor, func_prefix) FuncCall.pcall(executor, func_prefix + "topic_sub_post", subtopic) continue if rtag == "IncludeRequirements": self.__requirements.execute(executor, func_prefix) continue if rtag == "Text": FuncCall.pcall(executor, func_prefix + "topic_text", tag.get_content()) continue raise RMTException(114, "Unknown tag in topic [%s]" % rtag, self.name) tracer.debug("Calling post [%s]", self.name) FuncCall.pcall(executor, func_prefix + "topic_post", self) tracer.debug("Finished [%s]", self.name)
def convert_to_dict(self): self.ldict = {} for i in self: tag = i.get_tag() if tag in self.ldict: raise RMTException(81, "Tag '%s' multiple defined" % tag) self.ldict[i.get_tag()] = i
def __get_reqs_impl_detail(self, topic_set): '''Return the implementation details of the requirements.''' prios_impl = [] prios_detail = [] prios_selected = [] prios_assigned = [] prios_finished = [] req_set = topic_set.get_requirement_set() for reqid in req_set.get_all_requirement_ids(): tr = req_set.get_requirement(reqid) try: status = tr.get_status() if isinstance(status, RequirementStatusNotDone): rclass = tr.values["Class"] if isinstance(rclass, ClassTypeImplementable): prios_impl.append([tr.get_prio(), tr.get_id()]) elif isinstance(rclass, ClassTypeSelected): prios_selected.append([tr.get_prio(), tr.get_id()]) else: prios_detail.append([tr.get_prio(), tr.get_id()]) elif isinstance(status, RequirementStatusAssigned): prios_assigned.append(tr) elif isinstance(status, RequirementStatusFinished): prios_finished.append(tr) except KeyError as ke: raise RMTException(35, "%s: KeyError: %s" % (tr.get_id(), ke)) return prios_impl, prios_detail, prios_selected, \ prios_assigned, prios_finished
def add_node(self, node_a): """Adds a new node to the graph""" # Check if the node with the same name already exists. for node_idx in self.nodes: if node_idx.name == node_a.name: raise RMTException( 39, "Node with name '%s' already exists" % node_a.name) self.nodes.append(node_a)
def __check_for_circles(self): '''This does check if there is a directed circle (e.g. an strongly connected component) in the modules graph.''' scc = strongly_connected_components(self) if check_for_strongly_connected_components(scc): raise RMTException( 26, "There is a strongly connected " "component in the modules graph '%s'" % scc)
def find(self, n): c = 0 for i in self.cs: if n in i: return c, i c += 1 # Node not found raise RMTException(68, "Node [%s] not found" % n)
def convert_to_dict(self): """Convert the (internal) list of entries into a dict""" self.ldict = {} for i in self: tag = i.get_tag() if tag in self.ldict: raise RMTException(81, "Tag '%s' multiple defined" % tag) self.ldict[i.get_tag()] = i
def parse_date(rid, date_str): """Parse the given date as YYYY-MM-DD""" try: return datetime.datetime.strptime(date_str, "%Y-%m-%d").date() except ValueError: raise RMTException( 8, "%s: invalid date specified (must be " "YYYY-MM-DD) was '%s'" % (rid, date_str))
def rewrite(self, rid, req): """This tag is mandatory - but might be empty""" if self.get_tag() not in req: return "Factor", 0.0 # Compute the priority. This is done by adding the simple # priorities and afterwars build the average from this. tag = req[self.get_tag()] lop = tag.get_content().split() # The (computed) priority priority_sum = 0.0 num_stakeholders = 0 # A list to check if each stakeholder votes maximal one time. priority_done = [] for line in lop: split_line = line.split(":", 1) if len(split_line) != 2 or not split_line[1]: raise RMTException( 12, "%s: faulty priority declaration '%s'" % (rid, line)) # p[0] is the stakeholder # p[1] is the given priority if split_line[0] not in self.get_config().get_value( 'requirements.stakeholders'): raise RMTException( 13, "%s: stakeholder '%s' not known" % (rid, split_line[0])) if split_line[0] in priority_done: raise RMTException( 14, "%s: stakeholder '%s' voted more " "than once" % (rid, split_line[0])) # Convert it to a float - so it's easier to compare. prio_f = float(split_line[1]) # Check if in valid range [0..10] if prio_f < 0 or prio_f > 10: raise RMTException( 15, "%s: invalid priority '%f' - must " "be between 0 and 10" % (rid, prio_f)) # Compute new sum... priority_sum += prio_f / 10 # ... and increase the stakeholders count. num_stakeholders += 1 # Flag stakeholder that he voted already priority_done.append(split_line[0]) del req[self.get_tag()] return "Factor", priority_sum / float(num_stakeholders)
def __init_overwrite(self, config, type_str): '''Overwrite the existing default parameters with parameters from the configuration.''' self.__max_line_length = config.get_integer('max_input_line_length', 80) if self.__max_line_length < 0: raise RMTException( 72, "max_input_line_length for type [%s] is " "negative [%s]" % (type_str, self.__max_line_length))
def __init__(self, _config, rid, txt): txt_split = txt.split(":") if len(txt_split) != 3: raise RMTException(93, "%s: Assigned values invalid '%s'" % (rid, txt)) assert txt_split[0] == self.tval RequirementStatusBaseExt.__init__(self, txt_split[1], parse_date(rid, txt_split[2]))
def __get_tree_direct(self, base_tree, directory): '''Return the tree of the given directory. This does not walk down the directory structure. It just checks the current hierarchy.''' for tree in base_tree.trees: if tree.name == directory: return tree raise RMTException(108, "directory entry [%s] not found in tree " "[%s]." % (directory, base_tree.name))
def get_value(self, key): '''Returns the value of the given key. If key is not found a RMTException is thrown.''' try: return self.get_raw(key) except CfgEx, cex: raise RMTException(96, "Mandatory configuration parameter " "[%s] not found. (Root cause: [%s])" % (key, cex))
def __init__(self, _config, rid, t): ts = t.split(":") if len(ts)!=3: raise RMTException(93, "%s: Assigned values invalid '%s'" % (rid, t)) assert(ts[0]==self.tval) self.person = ts[1] self.date = parse_date(rid, ts[2])
def create_class_type(rid, l): if l == "implementable": return ClassTypeImplementable() if l == "detailable": return ClassTypeDetailable() if l == "selected": return ClassTypeSelected() raise RMTException(95, "%s:class type invalid '%s'" % (rid, l))
def test_positive_01(self): "Checks the __str__ method: no file, no line" rmte = RMTException(77, "ExceptMsg") assert (rmte.get_id() == 77) assert (rmte.get_msg() == "ExceptMsg") assert (rmte.get_efile() == None) assert (rmte.get_eline() == None) assert (rmte.__str__() == '[ 77]: ExceptMsg')
def rmttest_positive_01(self): "Checks the __str__ method: no file, no line" rmte = RMTException(77, "ExceptMsg") self.assertEqual(77, rmte.get_id()) self.assertEqual("ExceptMsg", rmte.get_msg()) self.assertIsNone(rmte.get_efile()) self.assertIsNone(rmte.get_eline()) self.assertEqual('[ 77]: ExceptMsg', rmte.__str__())
def test_positive_03(self): "Checks the __str__ method: with file, with line" rmte = RMTException(77, "ExceptMsg", "MyFile", 678) assert (rmte.get_id() == 77) assert (rmte.get_msg() == "ExceptMsg") assert (rmte.get_efile() == "MyFile") assert (rmte.get_eline() == 678) assert (rmte.__str__() == '[ 77]:MyFile:678: ExceptMsg')
def create_class_type(rid, type_desc): """Creates the class typed based on the type description""" if type_desc == "implementable": return ClassTypeImplementable() if type_desc == "detailable": return ClassTypeDetailable() if type_desc == "selected": return ClassTypeSelected() raise RMTException(95, "%s:class type invalid '%s'" % (rid, type_desc))
def check_mandatory_tag(self, rid, req, eid): '''Call this from the 'rewrite()' method, if the tag is mandatory. Note: this function only checks the availability of the tag but does not perform any other check. Returns 'True' if the tag is available and 'False' if the tag is not available.''' # The given tag is mandatory if self.__tag not in req: raise RMTException(eid, "Does not contain the " "tag '%s'" % self.__tag, rid)
def rmttest_positive_03(self): "Checks the __str__ method: with file, with line" rmte = RMTException(77, "ExceptMsg", "MyFile", 678) self.assertEqual(77, rmte.get_id()) self.assertEqual("ExceptMsg", rmte.get_msg()) self.assertEqual("MyFile", rmte.get_efile()) self.assertEqual(678, rmte.get_eline()) self.assertEqual('[ 77]:MyFile:678: ExceptMsg', rmte.__str__())
def __check_if_dir_is_in_repo(self, directory): '''Checks if all the directories are the in repository. The absolute path is computed if the path is relative and then compared to the repository base directory.''' tracer.debug("called: directory [%s]" % directory) if self.__repo_base_dir == None: self.__setup_repo(directory) if not directory.startswith(self.__repo_base_dir): raise RMTException(28, "directory [%s] not in repository" % directory)