1""" 2cloud_sptheme.ext.docfield_markup -- monkeypatches sphinx to allow ``~`` in docfields. 3""" 4#============================================================================= 5# imports 6#============================================================================= 7# core 8import logging; log = logging.getLogger(__name__) 9# site 10# pkg 11from cloud_sptheme import __version__ 12from cloud_sptheme.utils import patchapplier, monkeypatch 13# local 14__all__ = [ 15 "setup", 16] 17 18#============================================================================= 19# patch 20#============================================================================= 21@patchapplier 22def _patch_docfield(): 23 from sphinx.util.docfields import Field, nodes, addnodes 24 25 # NOTE: would like to just wrap make_xref(), but have to override first arg (rawsource) of 26 # pending_xref() call, so have to replicate the code. 27 28 @monkeypatch(Field) 29 def make_xref(_wrapped, self, rolename, domain, target, innernode=addnodes.literal_emphasis, 30 contnode=None, env=None): 31 #------------------------------------------------------------------------ 32 # custom prep work before real sphinx code. 33 #------------------------------------------------------------------------ 34 35 # given raw text in 'target', parse into 'title' and effective 'target' 36 # NOTE: this tries to replicate the markup convention used in PyXRefRole.process_link() 37 rawtext = title = target 38 if rawtext.startswith("~"): 39 # if the first character is a tilde, don't display the module/class 40 # parts of the content 41 target = target.lstrip("~") 42 title = target.rpartition(".")[2] 43 44 # create wrapper for innernode(title,title) calls, which honors custom title. 45 # NOTE: doing as wrapper so code below will match sphinx as closely as possible. 46 # could instead just plug this in as contnode (if not already set) 47 node_type = innernode 48 49 def innernode(*ignored): 50 if issubclass(node_type, nodes.Text): 51 # Text classes want rawtext second 52 return node_type(title, rawtext) 53 else: 54 # Element classes want rawtext first 55 return node_type(rawtext, title) 56 57 #------------------------------------------------------------------------ 58 # remainder of this should match sphinx code exactly, except where noted. 59 #------------------------------------------------------------------------ 60 if not rolename: 61 return contnode or innernode(target, target) 62 # NOTE: passing <title> as first arg, sphinx passes '' 63 refnode = addnodes.pending_xref(title, refdomain=domain, refexplicit=False, 64 reftype=rolename, reftarget=target) 65 refnode += contnode or innernode(target, target) 66 if env: 67 env.domains[domain].process_field_xref(refnode) 68 return refnode 69 70#============================================================================= 71# sphinx entrypoint 72#============================================================================= 73def setup(app): 74 # don't apply our patch unless actually loaded by sphinx 75 _patch_docfield() 76 77 # identifies the version of our extension 78 return {'version': __version__} 79 80#============================================================================= 81# eoc 82#============================================================================= 83