arxify's picture
Upload folder using huggingface_hub
ba2f5d6
raw
history blame
5.43 kB
import importlib
import warnings
import re
from docutils.parsers.rst import Directive
from docutils import nodes, utils
from sphinx import addnodes
from recommonmark.parser import CommonMarkParser
def type_description(schema):
"""Return a concise type description for the given schema"""
if not schema or not isinstance(schema, dict) or schema.keys() == {"description"}:
return "any"
elif "$ref" in schema:
return ":class:`{}`".format(schema["$ref"].split("/")[-1])
elif "enum" in schema:
return "[{}]".format(", ".join(repr(s) for s in schema["enum"]))
elif "type" in schema:
if isinstance(schema["type"], list):
return "[{}]".format(", ".join(schema["type"]))
elif schema["type"] == "array":
return "array({})".format(type_description(schema.get("items", {})))
elif schema["type"] == "object":
return "dict"
else:
return "`{}`".format(schema["type"])
elif "anyOf" in schema:
return "anyOf({})".format(
", ".join(type_description(s) for s in schema["anyOf"])
)
else:
warnings.warn(
"cannot infer type for schema with keys {}" "".format(schema.keys())
)
return "--"
def prepare_table_header(titles, widths):
"""Build docutil empty table"""
ncols = len(titles)
assert len(widths) == ncols
tgroup = nodes.tgroup(cols=ncols)
for width in widths:
tgroup += nodes.colspec(colwidth=width)
header = nodes.row()
for title in titles:
header += nodes.entry("", nodes.paragraph(text=title))
tgroup += nodes.thead("", header)
tbody = nodes.tbody()
tgroup += tbody
return nodes.table("", tgroup), tbody
reClassDef = re.compile(r":class:`([^`]+)`")
reCode = re.compile(r"`([^`]+)`")
def add_class_def(node, classDef):
"""Add reference on classDef to node"""
ref = addnodes.pending_xref(
reftarget=classDef,
reftype="class",
refdomain="py", # py:class="None" py:module="altair" refdoc="user_guide/marks"
refexplicit=False,
# refdoc="",
refwarn=False,
)
ref["py:class"] = "None"
ref["py:module"] = "altair"
ref += nodes.literal(text=classDef, classes=["xref", "py", "py-class"])
node += ref
return node
def add_text(node, text):
"""Add text with inline code to node"""
is_text = True
for part in reCode.split(text):
if part:
if is_text:
node += nodes.Text(part, part)
else:
node += nodes.literal(part, part)
is_text = not is_text
return node
def build_row(item):
"""Return nodes.row with property description"""
prop, propschema, required = item
row = nodes.row()
# Property
row += nodes.entry("", nodes.paragraph(text=prop), classes=["vl-prop"])
# Type
str_type = type_description(propschema)
par_type = nodes.paragraph()
is_text = True
for part in reClassDef.split(str_type):
if part:
if is_text:
add_text(par_type, part)
else:
add_class_def(par_type, part)
is_text = not is_text
# row += nodes.entry('')
row += nodes.entry("", par_type) # , classes=["vl-type-def"]
# Description
md_parser = CommonMarkParser()
# str_descr = "***Required.*** " if required else ""
str_descr = ""
str_descr += propschema.get("description", " ")
doc_descr = utils.new_document("schema_description")
md_parser.parse(str_descr, doc_descr)
# row += nodes.entry('', *doc_descr.children, classes="vl-decsr")
row += nodes.entry("", *doc_descr.children, classes=["vl-decsr"])
return row
def build_schema_tabel(items):
"""Return schema table of items (iterator of prop, schema.item, requred)"""
table, tbody = prepare_table_header(
["Property", "Type", "Description"], [10, 20, 50]
)
for item in items:
tbody += build_row(item)
return table
def select_items_from_schema(schema, props=None):
"""Return iterator (prop, schema.item, requred) on prop, return all in None"""
properties = schema.get("properties", {})
required = schema.get("required", [])
if not props:
for prop, item in properties.items():
yield prop, item, prop in required
else:
for prop in props:
try:
yield prop, properties[prop], prop in required
except KeyError:
warnings.warn("Can't find property:", prop)
def prepare_schema_tabel(schema, props=None):
items = select_items_from_schema(schema, props)
return build_schema_tabel(items)
class AltairObjectTableDirective(Directive):
"""
Directive for building a table of attribute descriptions.
Usage:
.. altair-object-table:: altair.MarkConfig
"""
has_content = False
required_arguments = 1
def run(self):
objectname = self.arguments[0]
modname, classname = objectname.rsplit(".", 1)
module = importlib.import_module(modname)
cls = getattr(module, classname)
schema = cls.resolve_references(cls._schema)
# create the table from the object
table = prepare_schema_tabel(schema)
return [table]
def setup(app):
app.add_directive("altair-object-table", AltairObjectTableDirective)