Graceful Handling of Unimplemented Types¶
Overview¶
The Atlassian Document Format (ADF) is a rich specification with many node and mark types. As a library that evolves incrementally, atlas_doc_parser may not implement all ADF types at any given time. This document explains how the library gracefully handles unimplemented types during parsing.
Design Philosophy¶
The library follows a progressive implementation approach:
Parse what we can: When encountering an ADF document, the parser deserializes all implemented node and mark types into Python objects.
Skip what we can’t: Unimplemented types are silently skipped rather than causing the entire parsing operation to fail.
Inform the user: When an unimplemented type is encountered, a warning is logged to inform users which types are missing. This helps users identify gaps and submit feature requests.
Fail on real errors: Actual parsing errors (malformed data, type mismatches, etc.) are still raised as exceptions. Only missing type registrations are skipped.
This design ensures that:
Users can work with partial ADF documents even if the library doesn’t support all types yet
The library can evolve incrementally without breaking existing functionality
Users are informed about which types need implementation
Error Handling Behavior¶
When to Skip Errors¶
Errors are skipped only when:
A node type is not registered in
NODE_TYPE_TO_CLASS_MAPPINGA mark type is not registered in
MARK_TYPE_TO_CLASS_MAPPING
In these cases, the unimplemented element is simply omitted from the parsed result.
When to Raise Errors¶
Errors are raised normally when:
The
from_dict()method of a dataclass fails (malformed attributes, type errors, etc.)Any other exception occurs during parsing (network errors, JSON decode errors, etc.)
The ADF structure is invalid (missing required fields, wrong types, etc.)
This distinction ensures that genuine bugs and data issues are surfaced while allowing the library to handle incomplete implementations gracefully.
Implementation Details¶
Key Components¶
The graceful handling mechanism involves several components:
Exception Class:
atlas_doc_parser.exc.UnimplementedTypeErrorA custom exception raised when a type is not found in the registry. It carries the type name and category (node or mark) for informative error messages.
Parse Functions:
parse_node()andparse_mark()Located in
atlas_doc_parser.nodes.parse_nodeandatlas_doc_parser.marks.parse_markrespectively. These functions look up the type in their respective mapping dictionaries. If the type is not found, they raiseUnimplementedTypeErrorinstead of letting theKeyErrorpropagate.Base Class Handler:
BaseNode.from_dict()Located in
atlas_doc_parser.mark_or_node. This method catchesUnimplementedTypeErrorspecifically when parsingcontent(child nodes) andmarks. When caught, it skips the unimplemented element and continues parsing the remaining elements.Warning Control:
settings.WARN_UNIMPLEMENTED_TYPEA module-level boolean flag in
atlas_doc_parser.settingsthat controls whether warnings are logged for unimplemented types. Default isTrue.
Code Flow¶
When parsing a document:
NodeDoc.from_dict(data)
|
+-- For each item in content:
| |
| +-- parse_node(item_data)
| |
| +-- Type not in NODE_TYPE_TO_CLASS_MAPPING?
| | |
| | +-- Raise UnimplementedTypeError
| |
| +-- Type found?
| |
| +-- Call NodeClass.from_dict(item_data)
|
+-- Catch UnimplementedTypeError?
| |
| +-- Log warning (if WARN_UNIMPLEMENTED_TYPE is True)
| +-- Skip this item, continue with next
|
+-- Catch other exceptions?
|
+-- Re-raise (fail normally)
Usage Examples¶
Default Behavior (Warnings Enabled)¶
from atlas_doc_parser.nodes.node_doc import NodeDoc
# Parse a document that contains an unimplemented node type
data = {
"version": 1,
"type": "doc",
"content": [
{"type": "bodiedExtension", "attrs": {...}}, # Not implemented
{"type": "paragraph", "content": [{"type": "text", "text": "Hello"}]}
]
}
doc = NodeDoc.from_dict(data)
# WARNING logged: Node type 'bodiedExtension' is not yet implemented...
# doc.content contains only the paragraph (bodiedExtension was skipped)
Disabling Warnings¶
import atlas_doc_parser.settings as settings
# Disable warnings for unimplemented types
settings.WARN_UNIMPLEMENTED_TYPE = False
# Now parse silently
doc = NodeDoc.from_dict(data)
# No warning logged, unimplemented types still skipped
Testing¶
The graceful handling mechanism is tested in tests/nodes/test_nodes_node_doc.py with the test_node_doc_with_unimplemented_model test case. This test uses a Confluence page that intentionally contains an unimplemented node type (bodiedExtension) to verify that:
Parsing completes without raising an exception
The unimplemented node is skipped
Other nodes in the document are parsed correctly
Contributing New Types¶
When a user encounters an unimplemented type, the warning message directs them to submit an issue at: https://github.com/MacHu-GWU/atlas_doc_parser-project/issues
To implement a new type:
Create the dataclass in the appropriate module (
nodes/ormarks/)Register the type in the mapping dictionary (
NODE_TYPE_TO_CLASS_MAPPINGorMARK_TYPE_TO_CLASS_MAPPING)Add tests for the new type