-
Notifications
You must be signed in to change notification settings - Fork 224
feat:! Adds pointer tag parsing implementation in parse_xml
#830
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 5 commits
709326a
781023d
dec49e8
e42f36d
d8f02a9
fa76371
12e8032
ea7eddd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,10 @@ | ||
| """ | ||
| Useful helper methods | ||
| """ | ||
| from lxml import etree | ||
|
|
||
|
|
||
| XML_PARSER = etree.XMLParser(dtd_validation=False, load_dtd=False, remove_blank_text=True, encoding='utf-8') | ||
|
|
||
|
|
||
| def child_isinstance(block, child_id, block_class_or_mixin): | ||
|
|
@@ -23,3 +27,87 @@ | |
| type_name = block.runtime.id_reader.get_block_type(def_id) | ||
| child_class = block.runtime.load_block_type(type_name) | ||
| return issubclass(child_class, block_class_or_mixin) | ||
|
|
||
|
|
||
| def name_to_pathname(name): | ||
| """ | ||
| Convert a location name for use in a path: replace ':' with '/'. | ||
| This allows users of the xml format to organize content into directories | ||
| """ | ||
| return name.replace(':', '/') | ||
|
|
||
|
|
||
| def is_pointer_tag(xml_obj): | ||
| """ | ||
| Check if xml_obj is a pointer tag: <blah url_name="something" />. | ||
| No children, one attribute named url_name, no text. | ||
|
|
||
| Special case for course roots: the pointer is | ||
| <course url_name="something" org="myorg" course="course"> | ||
|
|
||
| xml_obj: an etree Element | ||
|
|
||
| Returns a bool. | ||
| """ | ||
| if xml_obj.tag != "course": | ||
| expected_attr = {'url_name'} | ||
| else: | ||
| expected_attr = {'url_name', 'course', 'org'} | ||
|
|
||
| actual_attr = set(xml_obj.attrib.keys()) | ||
|
|
||
| has_text = xml_obj.text is not None and len(xml_obj.text.strip()) > 0 | ||
|
|
||
| return len(xml_obj) == 0 and actual_attr == expected_attr and not has_text | ||
|
|
||
|
|
||
| def load_definition_xml(node, runtime, def_id): | ||
| """ | ||
| Parses and loads an XML definition file based on a given node, runtime | ||
| environment, and definition ID. | ||
|
|
||
| Arguments: | ||
| node: XML element containing attributes for definition loading. | ||
| runtime: The runtime environment that provides resource access. | ||
| def_id: Unique identifier for the definition being loaded. | ||
|
|
||
| Returns: | ||
| tuple: A tuple containing the loaded XML definition and the | ||
| corresponding file path. | ||
| """ | ||
| url_name = node.get('url_name') | ||
| filepath = format_filepath(node.tag, name_to_pathname(url_name)) | ||
| definition_xml = load_file(filepath, runtime.resources_fs, def_id) | ||
| return definition_xml, filepath | ||
|
||
|
|
||
|
|
||
| def format_filepath(category, name): | ||
| """ | ||
| Construct a formatted filepath string based on the given category and name. | ||
| """ | ||
| return f'{category}/{name}.xml' | ||
ttqureshi marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
|
|
||
| def load_file(filepath, fs, def_id): # pylint: disable=invalid-name | ||
| """ | ||
| Open the specified file in fs, and call cls.file_to_xml on it, | ||
| returning the lxml object. | ||
|
|
||
| Add details and reraise on error. | ||
| """ | ||
| try: | ||
| with fs.open(filepath) as xml_file: | ||
| return file_to_xml(xml_file) | ||
| except Exception as err: # lint-amnesty | ||
ttqureshi marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| # Add info about where we are, but keep the traceback | ||
| raise Exception(f'Unable to load file contents at path {filepath} for item {def_id}: {err}') from err | ||
|
|
||
|
|
||
| def file_to_xml(file_object): | ||
| """ | ||
| Used when this module wants to parse a file object to xml | ||
| that will be converted to the definition. | ||
|
|
||
| Returns an lxml Element | ||
| """ | ||
| return etree.parse(file_object, parser=XML_PARSER).getroot() | ||
Uh oh!
There was an error while loading. Please reload this page.