def __init__(self, self_cfg, import_dest): tracer.info("called") self.useable = False self._cfg = dict(self.default_config) self._cfg.update(self_cfg) self._dest = dict() self._entries = None self._topics = None import_dest_cfg = Cfg(import_dest) try: req_dirs = import_dest_cfg.get_rvalue("requirements_dirs") if req_dirs[0] and os.path.isdir(req_dirs[0]): self.useable = True self._dest["requirements_dirs"] = req_dirs[0] except RMTException: self.useable = False try: topics_dirs = import_dest_cfg.get_rvalue("topics_dirs") if topics_dirs[0] and os.path.isdir(topics_dirs[0]): self.useable = True self._dest["topics_dirs"] = topics_dirs[0] except RMTException: self.useable = False self._wb = None tracer.debug("Finished.")
def __init__(self, config): cfg = Cfg(config) Interface.__init__(self, cfg) tracer.info("called") self.__topic_root_node = cfg.get_rvalue("topic_root_node") self.__dirs = {} self.__setup_directories(cfg)
def __init__(self, config): tracer.info("called") cfg = Cfg(config) FileInterface.__init__(self, cfg) self.__start_vers = cfg.get_rvalue("start_vers") self.__end_vers = cfg.get_rvalue("end_vers") self.__topic_root_node = cfg.get_rvalue("topic_root_node") tracer.debug("start version [%s] end version [%s] " "topic root node [%s]", self.__start_vers, self.__end_vers, self.__topic_root_node) # When the directory is not absolute, convert it to an # absolute path that it can be compared to the outcome of the # git.Repo. self.__dirs = {} self.__repo_base_dir = None self.__repo = None self.__dirs = self._setup_directories(cfg)
def __init__(self, config): tracer.info("called") cfg = Cfg(config) Interface.__init__(self, cfg) self.__start_vers = cfg.get_rvalue("start_vers") self.__end_vers = cfg.get_rvalue("end_vers") self.__topic_root_node = cfg.get_rvalue("topic_root_node") tracer.debug( "start version [%s] end version [%s] " "topic root node [%s]" % (self.__start_vers, self.__end_vers, self.__topic_root_node)) # When the directory is not absolute, convert it to an # absolute path that it can be compared to the outcome of the # git.Repo. self.__dirs = {} self.__repo_base_dir = None self.__repo = None self.__setup_directories(cfg)
class html(ExecutorTopicContinuum, CreateMakeDependencies): def __init__(self, oconfig): '''Create a graph output object.''' tracer.debug("Called: html ouput module constructed.") self._config = Cfg(oconfig) CreateMakeDependencies.__init__(self) self.__fd_stack = [] self.__topic_name_set = [] # Take care about the openess of the ul. self.__ul_open_stack = [] self.__output_directory = self._config.get_rvalue('output_directory') self.html_header_filename = self._config.get_rvalue('header') self.html_footer_filename = self._config.get_rvalue('footer') self.read_html_arts() def __ouput_html_topic_mkdirs(self): '''If not already there, create the directory.''' try: os.makedirs(self.__output_directory) except OSError, ose: # It's ok if already there pass
class StdOutputParams: '''Handles the standard output parameters and sets the values in the self object provided.''' def __init__(self, config): '''Constructs the standard output parameters based on the provided config.''' self._output_filename = None self._start_date = None self._end_date = None self._config = Cfg(config) self.__parse() def __parse_output_filename(self): '''Sets the output filename.''' self._output_filename = self._config.get_rvalue('output_filename') @staticmethod def __parse_date(cfg, name, default_value): '''If name is in params, the value is converted to a date and returned. If name is not in params, the default_value is returned.''' pname = cfg.get_value_wo_throw(name) if pname == None: return default_value return parse_date(name, pname) def __parse_start_and_end_date(self): '''Extracts the start and the end date from the params.''' today = datetime.date.today() yesterday = today - datetime.timedelta(1) self._start_date = self.__parse_date( self._config, 'start_date', yesterday) tracer.debug("Start date [%s]" % self._start_date) self._end_date = self.__parse_date(self._config, 'end_date', today) tracer.debug("End date [%s]" % self._end_date) def __parse(self): '''Parses the standard parameters.''' self.__parse_output_filename() self.__parse_start_and_end_date()
class StdOutputParams(object): '''Handles the standard output parameters and sets the values in the self object provided.''' def __init__(self, config): '''Constructs the standard output parameters based on the provided config.''' self._output_filename = None self._start_date = None self._end_date = None self._config = Cfg(config) self.__parse() def __parse_output_filename(self): '''Sets the output filename.''' self._output_filename = self._config.get_rvalue('output_filename') @staticmethod def __parse_date(cfg, name, default_value): '''If name is in params, the value is converted to a date and returned. If name is not in params, the default_value is returned.''' pname = cfg.get_value_wo_throw(name) if pname is None: return default_value return parse_date(name, pname) def __parse_start_and_end_date(self): '''Extracts the start and the end date from the params.''' today = datetime.date.today() yesterday = today - datetime.timedelta(1) self._start_date = self.__parse_date(self._config, 'start_date', yesterday) tracer.debug("Start date [%s]", self._start_date) self._end_date = self.__parse_date(self._config, 'end_date', today) tracer.debug("End date [%s]", self._end_date) def __parse(self): '''Parses the standard parameters.''' self.__parse_output_filename() self.__parse_start_and_end_date()
class Html(ExecutorTopicContinuum, CreateMakeDependencies): """HTML output module""" def __init__(self, oconfig): '''Create a graph output object.''' tracer.debug("Called: html ouput module constructed.") self._config = Cfg(oconfig) CreateMakeDependencies.__init__(self) self.__fd_stack = [] self.__topic_name_set = [] # Take care about the openess of the ul. self.__ul_open_stack = [] self.__output_directory = self._config.get_rvalue('output_directory') self.__markup = Markup("html") self.__tc_name = None self.__topic_set = None self.html_header_filename = self._config.get_rvalue('header') self.html_footer_filename = self._config.get_rvalue('footer') self.read_html_arts() def __ouput_html_topic_mkdirs(self): '''If not already there, create the directory.''' try: os.makedirs(self.__output_directory) except OSError: # It's ok if already there pass def topic_continuum_sort(self, vcs_commit_ids, topic_sets): '''Because graph2 can only one topic continuum, the latest (newest) is used.''' return [topic_sets[vcs_commit_ids[-1].get_commit()]] def topic_set_pre(self, _topics_set): '''Do all the file and directory preparation.''' self.__ouput_html_topic_mkdirs() def __output_html_topic_write_header(self, out_fd): '''Write the html header.''' out_fd.write(self.html_header) def topic_pre(self, topic): '''Output one topic. This method is called once for each topic and subtopic.''' tracer.debug("Called: topic name [%s]", topic.name) filename = os.path.join(self.__output_directory, topic.name + ".html") out_fd = io.open(filename, "w", encoding="utf-8") self.__output_html_topic_write_header(out_fd) self.__fd_stack.append(out_fd) self.__ul_open_stack.append(False) # self.output_html_topic_output_content(fd, topic) def topic_post(self, topic): '''Write out the footer and do clean ups.''' out_fd = self.__fd_stack.pop() self.__ul_open_stack.pop() self.output_html_topic_write_footer(out_fd) out_fd.close() tracer.debug("Finished: topic name [%s]", topic.name) def topic_name(self, name): '''Set the name.''' out_fd = self.__fd_stack[-1] level = len(self.__fd_stack) out_fd.write(u"<h%d>%s</h%d>\n" % (level, name, level)) def topic_text(self, text): '''Called when there is text to be outputted.''' out_fd = self.__fd_stack[-1] out_fd.write(u'<p><span class="fltext">%s</span></p>\n' % self.__markup.replace(text)) def topic_sub_pre(self, subtopic): '''Prepares a new subtopic output.''' out_fd = self.__fd_stack[-1] if not self.__ul_open_stack[-1]: out_fd.write(u'<span class="subtopiclist"><ul>') self.__ul_open_stack[-1] = True out_fd.write(u'<li><a href="%s.html">%s</a></li>\n' % (subtopic.get_id(), subtopic.get_topic_name())) def topic_sub_post(self, _subtopic): '''Write the header for subtopic.''' if self.__ul_open_stack[-1]: out_fd = self.__fd_stack[-1] out_fd.write(u"</ul></span>") self.__ul_open_stack[-1] = False def requirement_set_sort(self, list_to_sort): '''Sort by id.''' return sorted(list_to_sort, key=lambda r: r.get_id()) def requirement(self, req): '''Output one requirement.''' out_fd = self.__fd_stack[-1] level = len(self.__fd_stack) out_fd.write(u"\n<!-- REQ '%s' -->\n" % req.get_id()) out_fd.write(u'<h%d><a id="%s">%s</a></h%d>\n' % (level + 1, req.get_id(), req.get_value("Name").get_content(), level + 1)) out_fd.write(u"<dl>") out_fd.write( u'<dt><span class="dlt_description">Description</span>' '</dt><dd><span class="dlv_description">%s</span></dd>' % self.__markup.replace(req.get_value("Description").get_content())) if req.is_value_available("Rationale") \ and req.get_value("Rationale") is not None: out_fd.write( u'<dt><span class="dlt_rationale">Rationale</span>' '</dt><dd><span class="dlv_rationale">%s</span></dd>' % self.__markup.replace_par( req.get_value("Rationale").get_content())) if req.is_value_available("Note") \ and req.get_value("Note") is not None: out_fd.write(u'<dt><span class="dlt_note">Note</span></dt>' '<dd><span class="dlv_note">%s</span></dd>' % req.get_value("Note").get_content()) # Only output the depends on when there are fields for output. if req.incoming: # Create links to the corresponding labels. out_fd.write(u'<dt><span class="dlt_depends_on">Depends on:' '</span></dt><dd><span class="dlv_depends_on">') is_first = True for iid in sorted(req.incoming, key=lambda r: r.get_id()): if not is_first: out_fd.write(u", ") is_first = False out_fd.write( u'<a href="%s.html#%s">%s</a>' % (iid.get_value("Topic"), iid.get_id(), iid.get_id())) out_fd.write(u"</span></dd>") if req.outgoing: # Create links to the corresponding dependency nodes. out_fd.write(u'<dt><span class="dlt_dependent">Dependent' '</span></dt><dd><span class="dlv_dependent">') is_first = True for iid in sorted(req.outgoing, key=lambda r: r.get_id()): if not is_first: out_fd.write(u", ") is_first = False out_fd.write( u'<a href="%s.html#%s">%s</a>' % (iid.get_value("Topic"), iid.get_id(), iid.get_id())) out_fd.write(u"</span></dd>") status = req.get_value("Status").get_output_string() clstr = req.get_value("Class").get_output_string() out_fd.write( u'<dt><span class="dlt_id">Id</span></dt>' '<dd><span class="dlv_id">%s</span></dd>' '<dt><span class="dlt_priority">Priority</span></dt>' '<dd><span class="dlv_priority">%4.2f</span></dd>' '<dt><span class="dlt_owner">Owner</span></dt>' '<dd><span class="dlv_owner">%s</span></dd>' '<dt><span class="dlt_invented_on">Invented on</span></dt>' '<dd><span class="dlv_invented_on">%s</span></dd>' '<dt><span class="dlt_invented_by">Invented by</span></dt>' '<dd><span class="dlv_invented_by">%s</span></dd>' '<dt><span class="dlt_status">Status</span></dt>' '<dd><span class="dlv_status">%s</span></dd>' '<dt><span class="dlt_class">Class</span></dt>' '<dd><span class="dlv_class">%s</span></dd>' % (req.get_id(), req.get_value("Priority") * 10, req.get_value("Owner"), req.get_value("Invented on").strftime("%Y-%m-%d"), req.get_value("Invented by"), status, clstr)) out_fd.write(u"</dl>") # Mark the end of the requirment - then it is possible to add # some ruler here out_fd.write(u'<div class="requirment_end"> </div>') def cmad_topic_continuum_pre(self, topics_continuum): '''Save the name.''' self.__tc_name = topics_continuum.get_name() def cmad_topic_set_pre(self, topic_set): '''Save the name.''' self.__topic_set = topic_set def cmad_topic_set_post(self, _topic_set): '''Output symbol with all the HTMLs artifacts inside.''' self._cmad_file.write(u"OUTPUT_HTML=") for topic_name in self.__topic_name_set: self._cmad_file.write( u"%s.html " % os.path.join(self.__output_directory, topic_name)) self._cmad_file.write(u"\n") def cmad_topic_pre(self, topic): '''Create makefile dependencies for given topic.''' self.__topic_name_set.append(topic.name) self._cmad_file.write( u"%s.html: %s %s ${%s}\n%s" % (os.path.join(self.__output_directory, topic.name), self.html_header_filename, self.html_footer_filename, self.__topic_set.create_makefile_name( self.__tc_name, topic.name), self._get_call_rmtoo_line())) def cmad_requirement(self, requirement): '''Called on requirement level.''' self._cmad_file.write(u"REQS+=%s\n" % requirement.get_file_path()) def cmad(self, reqscont, ofile): """Create Makefile Dependencies Basic idea: each HTML file is dependend of the approriate topic file plus the header and the footer. Each html file depends on it's topic file """ # Dependencies of every single topic html page for topic in self.topic_set.nodes: ofile.write(u"%s.html: %s %s ${%s}\n\t${CALL_RMTOO}\n" % (os.path.join(self.output_dir, topic.name), self.html_header_filename, self.html_footer_filename, self.topic_set.create_makefile_name(topic.name))) # All HTML files ofile.write("OUTPUT_HTML=") for topic in self.topic_set.nodes: ofile.write(u"%s.html " % os.path.join(self.output_dir, topic.name)) ofile.write(u"\n") def read_html_arts(self): if self.html_header_filename is not None: with io.open(self.html_header_filename, "r", encoding="utf-8") as fd: self.html_header = fd.read() if self.html_footer_filename is not None: with io.open(self.html_footer_filename, "r", encoding="utf-8") as fd: self.html_footer = fd.read() # The real output # Note that currently the 'reqscont' is not used in case of topics # based output. def output(self, reqscont): # Currently just pass this to the RequirementSet self.output_reqset(reqscont.continuum_latest()) def output_reqset(self, reqset): # Call the topic to write out everything self.output_html_topic(self.topic_set.get_master()) def output_html_topic_output_content(self, fd, topic): # Subtopics go in a ul ul_open = False for t in topic.get_tags(): tag = t.get_tag() val = t.get_content() if tag != "SubTopic" and ul_open: fd.write(u"</ul></span>") ul_open = False if tag == "Name": # The Name itself depends on the level. fd.write(u"<h%d>%s</h%d>\n" % (topic.level + 1, val, topic.level + 1)) continue if tag == "SubTopic": if not ul_open: fd.write(u'<span class="subtopiclist"><ul>') ul_open = True rtopic = topic.find_outgoing(val) # A link to the other file. fd.write(u'<li><a href="%s.html">%s</a></li>\n' % (val, rtopic.get_name())) self.output_html_topic(rtopic) continue if tag == "Text": fd.write(u'<p><span class="fltext">%s</span></p>\n' % self.__markup.replace(val)) continue if tag == "IncludeRequirements": self.output_requirements(fd, topic) continue if ul_open: fd.write(u"</ul></span>") def output_html_topic_write_footer(self, fd): fd.write(self.html_footer) def output_requirements(self, fd, topic): # Output must be sorted - to be comparable for req in sorted(topic.reqs, key=lambda r: r.get_id()): self.output_requirement(fd, req, topic.level + 1)
class Html(ExecutorTopicContinuum, CreateMakeDependencies): """HTML output module""" def __init__(self, oconfig): '''Create a graph output object.''' tracer.debug("Called: html ouput module constructed.") self._config = Cfg(oconfig) CreateMakeDependencies.__init__(self) self.__fd_stack = [] self.__topic_name_set = [] # Take care about the openess of the ul. self.__ul_open_stack = [] self.__output_directory = self._config.get_rvalue('output_directory') self.__markup = Markup("html") self.__tc_name = None self.__topic_set = None self.html_header_filename = self._config.get_rvalue('header') self.html_footer_filename = self._config.get_rvalue('footer') self.read_html_arts() def __ouput_html_topic_mkdirs(self): '''If not already there, create the directory.''' try: os.makedirs(self.__output_directory) except OSError: # It's ok if already there pass def topic_continuum_sort(self, vcs_commit_ids, topic_sets): '''Because graph2 can only one topic continuum, the latest (newest) is used.''' return [topic_sets[vcs_commit_ids[-1].get_commit()]] def topic_set_pre(self, _topics_set): '''Do all the file and directory preparation.''' self.__ouput_html_topic_mkdirs() def __output_html_topic_write_header(self, out_fd): '''Write the html header.''' out_fd.write(self.html_header) def topic_pre(self, topic): '''Output one topic. This method is called once for each topic and subtopic.''' tracer.debug("Called: topic name [%s]", topic.name) filename = os.path.join(self.__output_directory, topic.name + ".html") out_fd = io.open(filename, "w", encoding="utf-8") self.__output_html_topic_write_header(out_fd) self.__fd_stack.append(out_fd) self.__ul_open_stack.append(False) # self.output_html_topic_output_content(fd, topic) def topic_post(self, topic): '''Write out the footer and do clean ups.''' out_fd = self.__fd_stack.pop() self.__ul_open_stack.pop() self.output_html_topic_write_footer(out_fd) out_fd.close() tracer.debug("Finished: topic name [%s]", topic.name) def topic_name(self, name): '''Set the name.''' out_fd = self.__fd_stack[-1] level = len(self.__fd_stack) out_fd.write(u"<h%d>%s</h%d>\n" % (level, name, level)) def topic_text(self, text): '''Called when there is text to be outputted.''' out_fd = self.__fd_stack[-1] out_fd.write(u'<p><span class="fltext">%s</span></p>\n' % self.__markup.replace(text)) def topic_sub_pre(self, subtopic): '''Prepares a new subtopic output.''' out_fd = self.__fd_stack[-1] if not self.__ul_open_stack[-1]: out_fd.write(u'<span class="subtopiclist"><ul>') self.__ul_open_stack[-1] = True out_fd.write(u'<li><a href="%s.html">%s</a></li>\n' % (subtopic.get_id(), subtopic.get_topic_name())) def topic_sub_post(self, _subtopic): '''Write the header for subtopic.''' if self.__ul_open_stack[-1]: out_fd = self.__fd_stack[-1] out_fd.write(u"</ul></span>") self.__ul_open_stack[-1] = False def requirement_set_sort(self, list_to_sort): '''Sort by id.''' return sorted(list_to_sort, key=lambda r: r.get_id()) def requirement(self, req): '''Output one requirement.''' out_fd = self.__fd_stack[-1] level = len(self.__fd_stack) out_fd.write(u"\n<!-- REQ '%s' -->\n" % req.get_id()) out_fd.write(u'<h%d><a id="%s">%s</a></h%d>\n' % (level + 1, req.get_id(), req.get_value("Name").get_content(), level + 1)) out_fd.write(u"<dl>") out_fd.write(u'<dt><span class="dlt_description">Description</span>' '</dt><dd><span class="dlv_description">%s</span></dd>' % self.__markup.replace(req.get_value("Description") .get_content())) if req.is_value_available("Rationale") \ and req.get_value("Rationale") is not None: out_fd.write( u'<dt><span class="dlt_rationale">Rationale</span>' '</dt><dd><span class="dlv_rationale">%s</span></dd>' % self.__markup.replace_par(req.get_value("Rationale"). get_content())) if req.is_value_available("Note") \ and req.get_value("Note") is not None: out_fd.write(u'<dt><span class="dlt_note">Note</span></dt>' '<dd><span class="dlv_note">%s</span></dd>' % req.get_value("Note").get_content()) # Only output the depends on when there are fields for output. if req.incoming: # Create links to the corresponding labels. out_fd.write(u'<dt><span class="dlt_depends_on">Depends on:' '</span></dt><dd><span class="dlv_depends_on">') is_first = True for iid in sorted(req.incoming, key=lambda r: r.get_id()): if not is_first: out_fd.write(u", ") is_first = False out_fd.write( u'<a href="%s.html#%s">%s</a>' % (iid.get_value("Topic"), iid.get_id(), iid.get_id())) out_fd.write(u"</span></dd>") if req.outgoing: # Create links to the corresponding dependency nodes. out_fd.write(u'<dt><span class="dlt_dependent">Dependent' '</span></dt><dd><span class="dlv_dependent">') is_first = True for iid in sorted(req.outgoing, key=lambda r: r.get_id()): if not is_first: out_fd.write(u", ") is_first = False out_fd.write( u'<a href="%s.html#%s">%s</a>' % (iid.get_value("Topic"), iid.get_id(), iid.get_id())) out_fd.write(u"</span></dd>") status = req.get_value("Status").get_output_string() clstr = req.get_value("Class").get_output_string() out_fd.write( u'<dt><span class="dlt_id">Id</span></dt>' '<dd><span class="dlv_id">%s</span></dd>' '<dt><span class="dlt_priority">Priority</span></dt>' '<dd><span class="dlv_priority">%4.2f</span></dd>' '<dt><span class="dlt_owner">Owner</span></dt>' '<dd><span class="dlv_owner">%s</span></dd>' '<dt><span class="dlt_invented_on">Invented on</span></dt>' '<dd><span class="dlv_invented_on">%s</span></dd>' '<dt><span class="dlt_invented_by">Invented by</span></dt>' '<dd><span class="dlv_invented_by">%s</span></dd>' '<dt><span class="dlt_status">Status</span></dt>' '<dd><span class="dlv_status">%s</span></dd>' '<dt><span class="dlt_class">Class</span></dt>' '<dd><span class="dlv_class">%s</span></dd>' % (req.get_id(), req.get_value("Priority") * 10, req.get_value("Owner"), req.get_value("Invented on").strftime("%Y-%m-%d"), req.get_value("Invented by"), status, clstr)) out_fd.write(u"</dl>") # Mark the end of the requirment - then it is possible to add # some ruler here out_fd.write(u'<div class="requirment_end"> </div>') def cmad_topic_continuum_pre(self, topics_continuum): '''Save the name.''' self.__tc_name = topics_continuum.get_name() def cmad_topic_set_pre(self, topic_set): '''Save the name.''' self.__topic_set = topic_set def cmad_topic_set_post(self, _topic_set): '''Output symbol with all the HTMLs artifacts inside.''' self._cmad_file.write(u"OUTPUT_HTML=") for topic_name in self.__topic_name_set: self._cmad_file.write(u"%s.html " % os.path.join( self.__output_directory, topic_name)) self._cmad_file.write(u"\n") def cmad_topic_pre(self, topic): '''Create makefile dependencies for given topic.''' self.__topic_name_set.append(topic.name) self._cmad_file.write( u"%s.html: %s %s ${%s}\n%s" % (os.path.join(self.__output_directory, topic.name), self.html_header_filename, self.html_footer_filename, self.__topic_set.create_makefile_name(self.__tc_name, topic.name), self._get_call_rmtoo_line())) def cmad_requirement(self, requirement): '''Called on requirement level.''' self._cmad_file.write(u"REQS+=%s\n" % requirement.get_file_path()) def cmad(self, reqscont, ofile): """Create Makefile Dependencies Basic idea: each HTML file is dependend of the approriate topic file plus the header and the footer. Each html file depends on it's topic file """ # Dependencies of every single topic html page for topic in self.topic_set.nodes: ofile.write(u"%s.html: %s %s ${%s}\n\t${CALL_RMTOO}\n" % (os.path.join(self.output_dir, topic.name), self.html_header_filename, self.html_footer_filename, self.topic_set.create_makefile_name(topic.name))) # All HTML files ofile.write("OUTPUT_HTML=") for topic in self.topic_set.nodes: ofile.write(u"%s.html " % os.path.join( self.output_dir, topic.name)) ofile.write(u"\n") def read_html_arts(self): if self.html_header_filename is not None: with io.open(self.html_header_filename, "r", encoding="utf-8") as fd: self.html_header = fd.read() if self.html_footer_filename is not None: with io.open(self.html_footer_filename, "r", encoding="utf-8") as fd: self.html_footer = fd.read() # The real output # Note that currently the 'reqscont' is not used in case of topics # based output. def output(self, reqscont): # Currently just pass this to the RequirementSet self.output_reqset(reqscont.continuum_latest()) def output_reqset(self, reqset): # Call the topic to write out everything self.output_html_topic(self.topic_set.get_master()) def output_html_topic_output_content(self, fd, topic): # Subtopics go in a ul ul_open = False for t in topic.get_tags(): tag = t.get_tag() val = t.get_content() if tag != "SubTopic" and ul_open: fd.write(u"</ul></span>") ul_open = False if tag == "Name": # The Name itself depends on the level. fd.write(u"<h%d>%s</h%d>\n" % (topic.level + 1, val, topic.level + 1)) continue if tag == "SubTopic": if not ul_open: fd.write(u'<span class="subtopiclist"><ul>') ul_open = True rtopic = topic.find_outgoing(val) # A link to the other file. fd.write(u'<li><a href="%s.html">%s</a></li>\n' % (val, rtopic.get_name())) self.output_html_topic(rtopic) continue if tag == "Text": fd.write(u'<p><span class="fltext">%s</span></p>\n' % self.__markup.replace(val)) continue if tag == "IncludeRequirements": self.output_requirements(fd, topic) continue if ul_open: fd.write(u"</ul></span>") def output_html_topic_write_footer(self, fd): fd.write(self.html_footer) def output_requirements(self, fd, topic): # Output must be sorted - to be comparable for req in sorted(topic.reqs, key=lambda r: r.get_id()): self.output_requirement(fd, req, topic.level + 1)