def traverse_dom_for_pspictures(self, element): # <pspicture><code> if element.tag == "pspicture": if self.pspictureGeneratorVersion == "1.0": self.psPictureCount += 1 src = self.pspicture_path(element) mediaNode = utils.create_node("media") mediaNode.append(utils.create_node("image")) mediaNode.attrib["alt"] = "Image" mediaNode[0].attrib["src"] = src mediaNode.tail = element.tail element.getparent().replace(element, mediaNode) elif element.tag == "tikzpicture": if self.pspictureGeneratorVersion == "1.0": self.tikzPictureCount += 1 src = self.pspicture_path(element) mediaNode = utils.create_node("media") mediaNode.append(utils.create_node("image")) mediaNode.attrib["alt"] = "Image" mediaNode[0].attrib["src"] = src mediaNode.tail = element.tail element.getparent().replace(element, mediaNode) else: children = element.getchildren() for child in children: self.traverse_dom_for_pspictures(child)
def setUp(self): self.nodes = [ create_node( name="one", input_type="in", output_type="one_out", space={"param": Choice(choices=[True, False])}, with_execute=True, ), create_node( name="two", input_type="one_out", output_type="two_out", space={"param": Choice(choices=[True, False])}, with_execute=True, ), create_node( name="three", input_type="two_out", output_type="out", space={"param": Choice(choices=[True, False])}, with_execute=True, ), ] self.pipeline = Pipeline() for node in self.nodes: self.pipeline.add_node(node)
def traverse_dom_for_pspictures(self, element): # <pspicture><code> if element.tag == 'pspicture': if self.pspictureGeneratorVersion == '1.0': self.psPictureCount += 1 src = self.pspicture_path(element) mediaNode = utils.create_node('media') mediaNode.append(utils.create_node('image')) mediaNode.attrib['alt'] = 'Image' mediaNode[0].attrib['src'] = src mediaNode.tail = element.tail element.getparent().replace(element, mediaNode) elif element.tag == 'tikzpicture': if self.pspictureGeneratorVersion == '1.0': self.tikzPictureCount += 1 src = self.pspicture_path(element) mediaNode = utils.create_node('media') mediaNode.append(utils.create_node('image')) mediaNode.attrib['alt'] = 'Image' mediaNode[0].attrib['src'] = src mediaNode.tail = element.tail element.getparent().replace(element, mediaNode) else: children = element.getchildren() for child in children: self.traverse_dom_for_pspictures(child)
def test_equal_and_hash(): name = "test" node1 = create_node(name=name) node2 = create_node(name=name) node3 = create_node(name="other") assert node1 == node2 assert hash(node1) == hash(node2) assert node1 != node3 assert hash(node1) != hash(node3) assert node1 != name
def test_add_not_matching_node(self): node = create_node(name="not_matching", input_type="not_matching") self.assertRaises(ValueError, self.pipeline.add_node, node)
NODE_COUNT = 50 # Get the connection to Node4j g = connect() g.delete_all() # Create NODE_COUNT compute nodes with 2048 DISK_GB, 4096 MEMORY_MB, and 8 # VCPU. Each will also have 2PFs, one public and one private, and each PF will # provide 8 VFs. We will also make each successive compute node have fewer and # fewer resources available. for i in range(NODE_COUNT): tx = g.begin() ratio = i / NODE_COUNT c = create_node(tx, "ComputeNode", "cn", i) d = create_node(tx, "DISK_GB", "disk", i, total=2048, used=int((2048 * ratio))) tx.create(Relationship(c, "PROVIDES", d)) r = create_node(tx, "MEMORY_MB", "ram", i, total=4096, used=int((4096 * ratio))) tx.create(Relationship(c, "PROVIDES", r)) v = create_node(tx, "VCPU", "vcpu", i, total=8, used=int((8 * ratio)))
node_count += 1 source.on_next(node_count) return jsonify(response) source.pipe(ops.filter(lambda n: n == settings.N)).subscribe( lambda x: do_broadcast_ring()) while True: pass # non-bootstrap nodes else: if len(sys.argv) != 3: print('Bad usage') exit(1) def current_node(): return node ip = sys.argv[1] port = sys.argv[2] utils.startThreadedServer(app, ip, port) node = utils.create_node(ip, port) print('created node with id: ', node.id) while True: pass
def test_name(): try: _ = create_node().name raise AssertionError("No exception raised") except NotImplementedError: pass
def test_execute(): try: _ = create_node().execute(None) raise AssertionError("No exception raised") except NotImplementedError: pass
def test_parameter_space(): try: _ = create_node().parameter_space() raise AssertionError("No exception raised") except NotImplementedError: pass
def test_output_type(): try: _ = create_node().output_type raise AssertionError("No exception raised") except NotImplementedError: pass
def traverse_dom_for_cnxml(self, element): # traverse every element in tree, find matching environments, transform for child in element: self.traverse_dom_for_cnxml(child) childIndex = 0 while childIndex < len(element): child = element[childIndex] if child.tag in ["video", "simulation", "presentation", "box"]: child.tag = "todo-" + child.tag childIndex += 1 elif child.tag == "image": # <image> <arguments/> <src/> </image> mediaNode = utils.create_node("media") mediaNode.append(utils.create_node("image")) mediaNode.attrib["alt"] = "Image" urlNode = child.find("src") if urlNode is not None: mediaNode[0].attrib["src"] = urlNode.text.strip() else: mediaNode[0].attrib["src"] = "" mediaNode.tail = child.tail element[childIndex] = mediaNode childIndex += 1 elif child.tag == "figure": typeNode = child.find("type") if typeNode is not None: typ = typeNode.text.strip() child.attrib["type"] = typ typeNode.tag = "label" typeNode.text = {"figure": "Figure", "table": "Table"}[typ] childIndex += 1 elif child.tag == "caption": if (len(child) == 1) and (child[0].tag == "para"): utils.etree_replace_with_node_list(child, child[0], child[0]) childIndex += 1 elif child.tag == "activity": # <activity type="activity"><title/> <section><title/>...</section> </activity> child.tag = "example" child.append( utils.create_node( "label", text={ "g_experiment": "General experiment", "f_experiment": "Formal experiment", "i_experiment": "Informal experiment", "activity": "Activity", "Investigation": "Investigation", "groupdiscussion": "Group discussion", "casestudy": "Case study", "project": "Project", }[child.attrib["type"]], ) ) pos = 1 while pos < len(child): if child[pos].tag == "section": sectionNode = child[pos] assert sectionNode[0].tag == "title" del child[pos] child.insert(pos, utils.create_node("para")) child[pos].append(utils.create_node("emphasis", text=sectionNode[0].text.strip())) child[pos][-1].attrib["effect"] = "bold" pos += 1 sectionChildren = sectionNode.getchildren() for i in range(1, len(sectionChildren)): child.insert(pos, sectionChildren[i]) pos += 1 else: pos += 1 childIndex += 1 elif child.tag == "worked_example": # <worked_example> <title/> <question/> <answer> ... <workstep> <title/> ... </workstep> </answer> </worked_example> child.tag = "example" newSubChildren = [] newSubChildren.append(utils.create_node("label", text="Worked example")) pos = 1 for subChild in child: if subChild.tag == "title": newSubChildren.append(subChild) elif subChild.tag == "question": newSubChildren.append(subChild) subChild.tag = "section" subChild.append(utils.create_node("title", text="Question")) elif subChild.tag == "answer": newSubChildren.append(subChild) subChild.tag = "section" subChild.append(utils.create_node("title", text="Answer")) for x in subChild: if x.tag == "workstep": x.tag = "section" childIndex += 1 elif child.tag == "note": child.insert( 0, utils.create_node( "label", text={"warning": "Warning", "tip": "Tip", "note": "Note", "aside": "Interesting Fact"}.get( child.attrib["type"], child.attrib["type"] ), ), ) childIndex += 1 elif child.tag == "math_identity": del element[childIndex] # Remove math_identity from DOM, still available as child ruleNode = utils.create_node("rule") ruleNode.attrib["type"] = "Identity" child.tag = "statement" ruleNode.append(child) element.insert(childIndex, ruleNode) childIndex += 1 elif child.tag == "nuclear_notation": namespace = "http://www.w3.org/1998/Math/MathML" mathNode = utils.create_node("math", namespace=namespace) mathNode.append(utils.create_node("msubsup", namespace=namespace)) mathNode[-1].append(utils.create_node("mo", namespace=namespace, text=u"\u200b")) mathNode[-1].append(utils.create_node("mn", namespace=namespace, text=child.find("atomic_number").text)) if child.find("mass_number") is not None: massNumber = child.find("mass_number").text else: massNumber = u"\u200b" mathNode[-1].append(utils.create_node("mn", namespace=namespace, text=massNumber)) mathNode.append(utils.create_node("mtext", namespace=namespace, text=child.find("symbol").text)) mathNode.tail = child.tail element[childIndex] = mathNode childIndex += 1 elif child.tag == "math_extension": child.tag = "note" titleNode = child.find("title") if titleNode is not None: titleNode.tag = "label" titleNode.text = u"Extension \u2014 " + titleNode.text.strip() else: child.insert(0, utils.create_node("label", text="Extension")) bodyNode = child.find("body") utils.etree_replace_with_node_list(child, bodyNode, bodyNode) childIndex += 1 elif child.tag == "section": # Check that it is not an activity section if child.getparent().tag != "activity": shortCodeNode = child.find("shortcode") if shortCodeNode is None: if (child.attrib.get("type") not in ["subsubsection", "subsubsubsection"]) and ( child.find("title").text.strip() != "Chapter summary" ): print 'WARNING: no shortcode for section "%s"' % child.find("title").text.strip() shortcode = "SHORTCODE" else: shortcode = None else: if (child.attrib.get("type") in ["subsubsection", "subsubsubsection"]) or ( child.find("title").text.strip() == "Chapter summary" ): print 'WARNING: section "%s" should not have a shortcode' % child.find("title").text.strip() shortcode = shortCodeNode.text.strip() child.remove(shortCodeNode) """ # Commented out so that shortcodes do not get displayed if shortcode is not None: titleNode = child.find('title') if len(titleNode) == 0: if titleNode.text is None: titleNode.text = '' titleNode.text += ' [' + shortcode + ']' else: if titleNode[-1].tail is None: titleNode[-1].tail = '' titleNode[-1].tail += ' [' + shortcode + ']' """ childIndex += 1 elif child.tag == "latex": if child.attrib.get("display", "inline") == "block": delimiters = "[]" else: delimiters = "()" if child.text is None: child.text = "" child.text = "\\" + delimiters[0] + child.text if len(child) > 0: if child[-1].text is None: child[-1].tail = "" child[-1].tail += "\\" + delimiters[1] else: child.text += "\\" + delimiters[1] utils.etree_replace_with_node_list(element, child, child) childIndex += len(child) elif child.tag in ["chem_compound", "spec_note"]: assert len(child) == 0, "<chem_compound> element not expected to have sub-elements." if child.text is None: child.text = "" child.text = child.text.strip() assert child.text != "", "<chem_compound> element must contain text." compoundText = child.text pos = 0 textOpen = False while pos < len(compoundText): if "a" <= compoundText[pos].lower() <= "z": if not textOpen: compoundText = compoundText[:pos] + r"\text{" + compoundText[pos:] textOpen = True pos += len(r"\text{") + 1 else: pos += 1 else: if textOpen: compoundText = compoundText[:pos] + "}" + compoundText[pos:] textOpen = False pos += 2 else: pos += 1 if textOpen: compoundText += "}" compoundXml = utils.xmlify(r"\(" + compoundText + r"\)") compoundDom = etree.fromstring(compoundXml[compoundXml.find("<formula ") : compoundXml.rfind("\n</p>")]) utils.etree_replace_with_node_list(element, child, compoundDom) childIndex += len(child) else: path = [child.tag] node = child while True: node = node.getparent() if node is None: break path.append(node.tag) path.reverse() namespaces = {"m": "http://www.w3.org/1998/Math/MathML"} valid = [ "emphasis", "para", "figure/type", "exercise/problem", "exercise/title", "exercise/shortcodes/entry/number", "exercise/shortcodes/entry/shortcode", "exercise/shortcodes/entry/url", "exercise/shortcodes/entry/todo-content", "list/item/label", "table/tgroup/tbody/row/entry", "table/tgroup/colspec", "definition/term", "definition/meaning", "sup", "sub", "m:mn", "m:mo", "m:mi", "m:msup", "m:mrow", "m:math", "m:mtable", "m:mtr", "m:mtd", "m:msub", "m:mfrac", "m:msqrt", "m:mspace", "m:mstyle", "m:mfenced", "m:mtext", "m:mroot", "m:mref", "m:msubsup", "m:munderover", "m:munder", "m:mover", "m:mphantom", "equation", "link", "quote", "rule/title", "rule/statement", "rule/proof", "section/title", "section/shortcode", "image/arguments", "image/src", "number/coeff", "number/exp", "number/base", "nuclear_notation/mass_number", "nuclear_notation/atomic_number", "nuclear_notation/symbol", "pspicture/code", "pspicture/usepackage", "tikzpicture/code", "video/title", "video/shortcode", "video/url", "video/width", "video/height", "worked_example/answer/workstep/title", "worked_example/question", "worked_example/title", "activity/title", "math_extension/title", "math_extension/body", "math_identity", "document/content/title", "document/content/content", "simulation/title", "simulation/shortcode", "simulation/url", "simulation/width", "simulation/height", "simulation/embed", "presentation/title", "presentation/url", "presentation/shortcode", "presentation/embed", "box", ] validSet = set([]) for entry in valid: entry = entry.split("/") for i in range(len(entry)): if ":" in entry[i]: entry[i] = entry[i].split(":") assert len(entry[i]) == 2 entry[i] = "{%s}%s" % (namespaces[entry[i][0]], entry[i][1]) validSet.add(tuple(entry[: i + 1])) valid = validSet passed = False for entry in valid: if tuple(path[-len(entry) :]) == entry: passed = True break if not passed: path = "/".join(path) for key, url in namespaces.iteritems(): path = path.replace("{%s}" % url, key + ":") LOGGER.info("Unhandled element: " + path) childIndex += 1
def process(self, markup): # Strip comments pos = 0 while True: start = markup.find("<!--", pos) if start == -1: break stop = markup.find("-->", start + 4) assert stop != -1 stop += 3 markup = markup[:start] + markup[stop:] pos = start # Convert XML to DOM dom = etree.fromstring(markup) # Get CNXML+ version number versionNodeList = dom.xpath("/document/metadata/cnxml-version") if len(versionNodeList) == 0: # Insert version number into DOM version = "0.0" else: if len(versionNodeList) != 1: raise ValueError, "More than one cnxml-version node found in metadata section." version = versionNodeList[0].text.strip() # Convert v0.1 down to v0.0, if necessary if version == "0.1": for oldExercisesNode in dom.xpath("//exercises"): newExerciseNode = etree.Element("exercise") titleNode = oldExercisesNode.find("title") if titleNode is None: titleNode = etree.Element("title") newExerciseNode.append(titleNode) for oldEntryNode in oldExercisesNode.xpath("./entry"): shortcodeNode = oldEntryNode.find("shortcode") if shortcodeNode is None: shortcodeNode = etree.Element("shortcode") problemNode = oldEntryNode.find("problem") assert problemNode is not None solutionNode = oldEntryNode.find("solution") assert solutionNode is not None newExerciseNode.append(problemNode) newExerciseNode.append(etree.Element("shortcodes")) newExerciseNode[-1].append(etree.Element("entry")) newExerciseNode[-1][-1].append(shortcodeNode) if not ((solutionNode.text is None) and (len(solutionNode) == 0)): newExerciseNode[-1][-1].append(solutionNode) solutionNode.tag = "content" if solutionNode.attrib.get("url") is not None: newExerciseNode[-1][-1].append(etree.Element("url")) newExerciseNode[-1][-1][-1].text = solutionNode.attrib["url"] del solutionNode.attrib["url"] newExerciseNode.tail = oldExercisesNode.tail oldExercisesNode.getparent().replace(oldExercisesNode, newExerciseNode) contentNode = dom.find("content") # Check if it's an end of chapter exercise block if (len(contentNode) == 1) and (contentNode[0].tag == "exercise"): contentNode[0].tag = "section" contentNode[0].attrib["type"] = "chapter" elif version != "0.0": raise ValueError, "Don't know how to handle CNXML+ version " + version # Check for a pspicture generator version tag metadataNode = dom.find("metadata") self.pspictureGeneratorVersion = "1.0" if metadataNode is not None: generatorNode = metadataNode.find("pspicture-generator-version") if generatorNode is not None: self.pspictureGeneratorVersion = generatorNode.text.strip() if self.pspictureGeneratorVersion == "1.0": LOGGER.info("Deprecation warning: pspicture-generator-version 1.0 is deprecated, please upgrade to 1.1") # Convert down to CNXML # Strip out <section type="chapter"> dom = dom.find("content") assert len(dom) == 1 # only a single chapter section assert (dom[0].tag == "section") and (dom[0].attrib["type"] == "chapter") chapterNode = dom[0] titleNode = chapterNode[0] assert titleNode.tag == "title" contentsNodes = chapterNode[1:] del dom[0] dom.append(titleNode) dom.append(utils.create_node("content")) for node in contentsNodes: dom[-1].append(node) # Build chapter hash from title: for pspictures directory if titleNode.text is None: chapterTitle = "" else: chapterTitle = titleNode.text if self.pspictureGeneratorVersion == "1.0": self.chapterHash = hashlib.md5(chapterTitle.encode("utf-8")).hexdigest() # Hack to replace shortcode content with todo-content. # traverse_dom_for_cnxml() needs to change eventually to use # xpath rather than a recursive function. for contentNode in dom.xpath("//shortcodes/entry/content"): contentNode.tag = "todo-content" # Transform using new-style (xpath-based) transform self.transform(dom) # TOFIX: Remaining elements using old-style transform # Transform all elements in document, except pspictures self.traverse_dom_for_cnxml(dom) # Transform pspictures if self.pspictureGeneratorVersion == "1.0": self.psPictureCount = 0 self.tikzPictureCount = 0 self.traverse_dom_for_pspictures(dom) markup = utils.declutter_latex_tags(etree.tostring(dom)).strip() assert markup[:8] == "<content" assert markup[-10:] == "</content>" markup = '<?xml version="1.0"?>\n<document xmlns="http://cnx.rice.edu/cnxml"' + markup[8:-10] + "</document>\n" return markup
def traverse_dom_for_cnxml(self, element): # traverse every element in tree, find matching environments, transform for child in element: self.traverse_dom_for_cnxml(child) childIndex = 0 while childIndex < len(element): child = element[childIndex] if child.tag in ['video', 'simulation', 'presentation', 'box']: child.tag = 'todo-' + child.tag childIndex += 1 elif child.tag == 'image': # <image> <arguments/> <src/> </image> mediaNode = utils.create_node('media') mediaNode.append(utils.create_node('image')) mediaNode.attrib['alt'] = 'Image' urlNode = child.find('src') if urlNode is not None: mediaNode[0].attrib['src'] = urlNode.text.strip() else: mediaNode[0].attrib['src'] = '' mediaNode.tail = child.tail element[childIndex] = mediaNode childIndex += 1 elif child.tag == 'figure': typeNode = child.find('type') if typeNode is not None: typ = typeNode.text.strip() child.attrib['type'] = typ typeNode.tag = 'label' typeNode.text = {'figure': 'Figure', 'table': 'Table'}[typ] childIndex += 1 elif child.tag == 'caption': if (len(child) == 1) and (child[0].tag == 'para'): utils.etree_replace_with_node_list(child, child[0], child[0]) childIndex += 1 elif child.tag == 'activity': # <activity type="activity"><title/> <section><title/>...</section> </activity> child.tag = 'example' child.append(utils.create_node('label', text={ 'g_experiment': 'General experiment', 'f_experiment': 'Formal experiment', 'i_experiment': 'Informal experiment', 'activity': 'Activity', 'Investigation': 'Investigation', 'groupdiscussion': 'Group discussion', 'casestudy': 'Case study', 'project': 'Project'}[child.attrib['type']])) pos = 1 while pos < len(child): if child[pos].tag == 'section': sectionNode = child[pos] assert sectionNode[0].tag == 'title' del child[pos] child.insert(pos, utils.create_node('para')) child[pos].append(utils.create_node('emphasis', text=sectionNode[0].text.strip())) child[pos][-1].attrib['effect'] = 'bold' pos += 1 sectionChildren = sectionNode.getchildren() for i in range(1, len(sectionChildren)): child.insert(pos, sectionChildren[i]) pos += 1 else: pos += 1 childIndex += 1 elif child.tag == 'worked_example': # <worked_example> <title/> <question/> <answer> ... <workstep> <title/> ... </workstep> </answer> </worked_example> child.tag = 'example' newSubChildren = [] newSubChildren.append(utils.create_node('label', text="Worked example")) pos = 1 for subChild in child: if subChild.tag == 'title': newSubChildren.append(subChild) elif subChild.tag == 'question': newSubChildren.append(subChild) subChild.tag = 'section' subChild.append(utils.create_node('title', text='Question')) elif subChild.tag == 'answer': newSubChildren.append(subChild) subChild.tag = 'section' subChild.append(utils.create_node('title', text='Answer')) for x in subChild: if x.tag == 'workstep': x.tag = 'section' childIndex += 1 elif child.tag == 'note': child.insert(0, utils.create_node('label', text={ 'warning': 'Warning', 'tip': 'Tip', 'note': 'Note', 'aside': 'Interesting Fact'}.get(child.attrib['type'], child.attrib['type']))) childIndex += 1 elif child.tag == 'math_identity': del element[childIndex] # Remove math_identity from DOM, still available as child ruleNode = utils.create_node('rule') ruleNode.attrib['type'] = 'Identity' child.tag = 'statement' ruleNode.append(child) element.insert(childIndex, ruleNode) childIndex += 1 elif child.tag == 'nuclear_notation': namespace = 'http://www.w3.org/1998/Math/MathML' mathNode = utils.create_node('math', namespace=namespace) mathNode.append(utils.create_node('msubsup', namespace=namespace)) mathNode[-1].append(utils.create_node('mo', namespace=namespace, text=u'\u200b')) mathNode[-1].append(utils.create_node('mn', namespace=namespace, text=child.find('atomic_number').text)) if child.find('mass_number') is not None: massNumber = child.find('mass_number').text else: massNumber = u'\u200b' mathNode[-1].append(utils.create_node('mn', namespace=namespace, text=massNumber)) mathNode.append(utils.create_node('mtext', namespace=namespace, text=child.find('symbol').text)) mathNode.tail = child.tail element[childIndex] = mathNode childIndex += 1 elif child.tag == 'math_extension': child.tag = 'note' titleNode = child.find('title') if titleNode is not None: titleNode.tag = 'label' titleNode.text = u'Extension \u2014 ' + titleNode.text.strip() else: child.insert(0, utils.create_node('label', text='Extension')) bodyNode = child.find('body') utils.etree_replace_with_node_list(child, bodyNode, bodyNode) childIndex += 1 elif child.tag == 'section': # Check that it is not an activity section if child.getparent().tag != 'activity': shortCodeNode = child.find('shortcode') if shortCodeNode is None: if (child.attrib.get('type') not in ['subsubsection', 'subsubsubsection']) and (child.find('title').text.strip() != 'Chapter summary'): print 'WARNING: no shortcode for section "%s"'%child.find('title').text.strip() shortcode = 'SHORTCODE' else: shortcode = None else: if (child.attrib.get('type') in ['subsubsection', 'subsubsubsection']) or (child.find('title').text.strip() == 'Chapter summary'): print 'WARNING: section "%s" should not have a shortcode'%child.find('title').text.strip() shortcode = shortCodeNode.text.strip() child.remove(shortCodeNode) """ # Commented out so that shortcodes do not get displayed if shortcode is not None: titleNode = child.find('title') if len(titleNode) == 0: if titleNode.text is None: titleNode.text = '' titleNode.text += ' [' + shortcode + ']' else: if titleNode[-1].tail is None: titleNode[-1].tail = '' titleNode[-1].tail += ' [' + shortcode + ']' """ childIndex += 1 elif child.tag == 'latex': if child.attrib.get('display', 'inline') == 'block': delimiters = '[]' else: delimiters = '()' if child.text is None: child.text = '' child.text = '\\' + delimiters[0] + child.text if len(child) > 0: if child[-1].text is None: child[-1].tail = '' child[-1].tail += '\\' + delimiters[1] else: child.text += '\\' + delimiters[1] utils.etree_replace_with_node_list(element, child, child) childIndex += len(child) elif child.tag in ['chem_compound', 'spec_note']: assert len(child) == 0, "<chem_compound> element not expected to have sub-elements." if child.text is None: child.text = '' child.text = child.text.strip() assert child.text != '', "<chem_compound> element must contain text." compoundText = child.text pos = 0 textOpen = False while pos < len(compoundText): if 'a' <= compoundText[pos].lower() <= 'z': if not textOpen: compoundText = compoundText[:pos] + r'\text{' + compoundText[pos:] textOpen = True pos += len(r'\text{') + 1 else: pos += 1 else: if textOpen: compoundText = compoundText[:pos] + '}' + compoundText[pos:] textOpen = False pos += 2 else: pos += 1 if textOpen: compoundText += '}' compoundXml = utils.xmlify(r'\(' + compoundText + r'\)') compoundDom = etree.fromstring(compoundXml[compoundXml.find('<formula '):compoundXml.rfind('\n</p>')]) utils.etree_replace_with_node_list(element, child, compoundDom) childIndex += len(child) else: path = [child.tag] node = child while True: node = node.getparent() if node is None: break path.append(node.tag) path.reverse() namespaces = {'m': 'http://www.w3.org/1998/Math/MathML'} valid = [ 'emphasis', 'para', 'figure/type', 'exercise/problem', 'exercise/title', 'exercise/shortcodes/entry/number', 'exercise/shortcodes/entry/shortcode', 'exercise/shortcodes/entry/url', 'exercise/shortcodes/entry/todo-content', 'list/item/label', 'table/tgroup/tbody/row/entry', 'table/tgroup/colspec', 'definition/term', 'definition/meaning', 'sup', 'sub', 'm:mn', 'm:mo', 'm:mi', 'm:msup', 'm:mrow', 'm:math', 'm:mtable', 'm:mtr', 'm:mtd', 'm:msub', 'm:mfrac', 'm:msqrt', 'm:mspace', 'm:mstyle', 'm:mfenced', 'm:mtext', 'm:mroot', 'm:mref', 'm:msubsup', 'm:munderover', 'm:munder', 'm:mover', 'm:mphantom', 'equation', 'link', 'quote', 'rule/title', 'rule/statement', 'rule/proof', 'section/title', 'section/shortcode', 'image/arguments', 'image/src', 'number/coeff', 'number/exp', 'number/base', 'nuclear_notation/mass_number', 'nuclear_notation/atomic_number', 'nuclear_notation/symbol', 'pspicture/code', 'pspicture/usepackage', 'tikzpicture/code', 'video/title', 'video/shortcode', 'video/url', 'video/width', 'video/height', 'worked_example/answer/workstep/title', 'worked_example/question', 'worked_example/title', 'activity/title', 'math_extension/title', 'math_extension/body', 'math_identity', 'document/content/title', 'document/content/content', 'simulation/title', 'simulation/shortcode', 'simulation/url', 'simulation/width', 'simulation/height', 'simulation/embed', 'presentation/title', 'presentation/url', 'presentation/shortcode', 'presentation/embed', 'box', ] validSet = set([]) for entry in valid: entry = entry.split('/') for i in range(len(entry)): if ':' in entry[i]: entry[i] = entry[i].split(':') assert len(entry[i]) == 2 entry[i] = '{%s}%s'%(namespaces[entry[i][0]], entry[i][1]) validSet.add(tuple(entry[:i+1])) valid = validSet passed = False for entry in valid: if tuple(path[-len(entry):]) == entry: passed = True break if not passed: path = '/'.join(path) for key, url in namespaces.iteritems(): path = path.replace('{%s}'%url, key+':') LOGGER.info('Unhandled element: ' + path) childIndex += 1