# :coding: utf-8
from docutils.statemachine import StringList
[docs]def get_rst_class_elements(
environment, module_name, module_path_name, whitelist_names=None,
undocumented_members=False, private_members=False,
force_partial_import=False, skip_attribute_value=False, rst_elements=None
):
"""Return :term:`reStructuredText` from class elements within
*environment*.
*module_name* is the module alias that should be added to each
directive.
*module_path_name* is the module path alias that should be added to each
directive.
*whitelist_names* is an optional list of element names that
should be displayed exclusively.
*undocumented_members* indicate whether undocumented element should be
displayed.
*private_members* indicate whether elements starting with an underscore
should be displayed.
*force_partial_import* indicate whether the import statement should
force the partial import display if necessary.
*skip_attribute_value* indicate whether attribute value within the class
should not be displayed.
*rst_elements* can be an initial dictionary that will be updated and
returned.
"""
if rst_elements is None:
rst_elements = {}
for class_environment in environment["class"].values():
name = class_environment["name"]
description = class_environment["description"]
if description is None and not undocumented_members:
continue
if name.startswith("_") and not private_members:
continue
if whitelist_names is None or name in whitelist_names:
line_number = class_environment["line_number"]
extra_options = []
if force_partial_import:
extra_options = [":force-partial-import:"]
if skip_attribute_value:
extra_options.append(":skip-attribute-value:")
rst_element = rst_generate(
directive="autoclass",
element_id=class_environment["id"],
alias=class_environment["name"],
module_alias=module_name,
module_path_alias=module_path_name,
extra_options=extra_options
)
rst_elements[line_number] = [rst_element]
return rst_elements
[docs]def get_rst_attribute_elements(
class_environment, whitelist_names=None, blacklist_ids=None,
undocumented_members=False, private_members=False, skip_value=False,
rst_elements=None,
):
"""Return :term:`reStructuredText` from class attribute elements within
*class_environment*.
*whitelist_names* is an optional list of element names that
should be displayed exclusively.
*blacklist_ids* is an optional list of element identifiers that
should not be displayed.
*undocumented_members* indicate whether undocumented element should be
displayed.
*private_members* indicate whether elements starting with an underscore
should be displayed.
*skip_value* indicate whether the value should not be displayed.
*rst_elements* can be an initial dictionary that will be updated and
returned.
"""
if rst_elements is None:
rst_elements = {}
# As a method can also be a variable, use the method directive
# by default when available
if blacklist_ids is None:
blacklist_ids = []
for attr_environment in class_environment["attribute"].values():
if attr_environment["id"] in blacklist_ids:
continue
name = attr_environment["name"]
description = attr_environment["description"]
if description is None and not undocumented_members:
continue
if name.startswith("_") and not private_members:
continue
extra_options = []
if skip_value:
extra_options.append(":skip-value:")
if whitelist_names is None or name in whitelist_names:
line_number = attr_environment["line_number"]
rst_element = rst_generate(
directive="autoattribute",
element_id=attr_environment["id"],
extra_options=extra_options
)
rst_elements[line_number] = [rst_element]
return rst_elements
[docs]def get_rst_method_elements(
class_environment, whitelist_names=None, skip_constructor=False,
undocumented_members=False, private_members=False, rst_elements=None
):
"""Return :term:`reStructuredText` from class method elements within
*class_environment*.
*whitelist_names* is an optional list of element names that
should be displayed exclusively.
*skip_constructor* indicate whether the class constructor should be
displayed.
*undocumented_members* indicate whether undocumented element should be
displayed.
*private_members* indicate whether elements starting with an underscore
should be displayed.
*rst_elements* can be an initial dictionary that will be updated and
returned.
"""
if rst_elements is None:
rst_elements = {}
for method_environment in class_environment["method"].values():
name = method_environment["name"]
if name == "constructor" and skip_constructor:
continue
description = method_environment["description"]
if description is None and not undocumented_members:
continue
if name.startswith("_") and not private_members:
continue
if whitelist_names is None or name in whitelist_names:
line_number = method_environment["line_number"]
rst_element = rst_generate(
directive="automethod",
element_id=method_environment["id"],
)
rst_elements[line_number] = [rst_element]
return rst_elements
[docs]def get_rst_function_elements(
environment, module_name, module_path_name, whitelist_names=None,
undocumented_members=False, private_members=False,
force_partial_import=False, rst_elements=None
):
"""Return :term:`reStructuredText` from function elements within
*environment*.
*module_name* is the module alias that should be added to each
directive.
*module_path_name* is the module path alias that should be added to each
directive.
*whitelist_names* is an optional list of element names that
should be displayed exclusively.
*undocumented_members* indicate whether undocumented element should be
displayed.
*private_members* indicate whether elements starting with an underscore
should be displayed.
*force_partial_import* indicate whether the import statement should
force the partial import display if necessary.
*rst_elements* can be an initial dictionary that will be updated and
returned.
"""
if rst_elements is None:
rst_elements = {}
for function_environment in environment["function"].values():
name = function_environment["name"]
description = function_environment["description"]
if description is None and not undocumented_members:
continue
if name.startswith("_") and not private_members:
continue
if whitelist_names is None or name in whitelist_names:
line_number = function_environment["line_number"]
extra_options = []
if force_partial_import:
extra_options = [":force-partial-import:"]
rst_element = rst_generate(
directive="autofunction",
element_id=function_environment["id"],
alias=function_environment["name"],
module_alias=module_name,
module_path_alias=module_path_name,
extra_options=extra_options
)
rst_elements[line_number] = [rst_element]
return rst_elements
[docs]def get_rst_data_elements(
environment, module_name, module_path_name, whitelist_names=None,
blacklist_ids=None, undocumented_members=False, private_members=False,
force_partial_import=False, skip_value=False, rst_elements=None,
):
"""Return :term:`reStructuredText` from data elements within
*environment*.
*module_name* is the module alias that should be added to each
directive.
*module_path_name* is the module path alias that should be added to each
directive.
*whitelist_names* is an optional list of element names that
should be displayed exclusively.
*blacklist_ids* is an optional list of element identifiers that
should not be displayed.
*undocumented_members* indicate whether undocumented element should be
displayed.
*private_members* indicate whether elements starting with an underscore
should be displayed.
*force_partial_import* indicate whether the import statement should
force the partial import display if necessary.
*skip_value* indicate whether the value should not be displayed.
*rst_elements* can be an initial dictionary that will be updated and
returned.
"""
if rst_elements is None:
rst_elements = {}
# As a function can also be a variable, use the function directive
# by default when available
if blacklist_ids is None:
blacklist_ids = []
for data_environment in environment["data"].values():
if data_environment["id"] in blacklist_ids:
continue
name = data_environment["name"]
description = data_environment["description"]
if description is None and not undocumented_members:
continue
if name.startswith("_") and not private_members:
continue
if whitelist_names is None or name in whitelist_names:
line_number = data_environment["line_number"]
extra_options = []
if force_partial_import:
extra_options.append(":force-partial-import:")
if skip_value:
extra_options.append(":skip-value:")
rst_element = rst_generate(
directive="autodata",
element_id=data_environment["id"],
alias=data_environment["name"],
module_alias=module_name,
module_path_alias=module_path_name,
extra_options=extra_options
)
rst_elements[line_number] = [rst_element]
return rst_elements
[docs]def get_rst_export_elements(
file_environment, environment, module_name, module_path_name,
skip_data_value=False, skip_attribute_value=False, rst_elements=None
):
"""Return :term:`reStructuredText` from exported elements within
*file_environment*.
*environment* is the full :term:`Javascript` environment processed
in :mod:`~champollion.parser`.
*module_name* is the module alias that should be added to each
directive.
*module_path_name* is the module path alias that should be added to each
directive.
*skip_data_value* indicate whether data value should not be displayed.
*skip_attribute_value* indicate whether attribute value should not be
displayed.
*rst_elements* can be an initial dictionary that will be updated and
returned.
"""
export_environment = file_environment["export"]
import_environment = file_environment["import"]
if rst_elements is None:
rst_elements = {}
for _exported_env_id, _exported_env in export_environment.items():
from_module_id = _exported_env["module"]
line_number = _exported_env["line_number"]
if line_number not in rst_elements.keys():
rst_elements[line_number] = []
name = _exported_env["name"]
alias = _exported_env["alias"]
if alias is None:
alias = name
# Update module origin and name from import if necessary
if (from_module_id is None and
_exported_env_id in import_environment.keys()):
name = import_environment[_exported_env_id]["name"]
from_module_id = import_environment[_exported_env_id]["module"]
# Ignore element if the origin module can not be found
if from_module_id not in environment["module"].keys():
continue
from_module_environment = environment["module"][from_module_id]
from_file_id = from_module_environment["file_id"]
from_file_env = environment["file"][from_file_id]
if name == "default":
rst_element = get_rst_default_from_file_environment(
from_file_env, alias, module_name, module_path_name,
skip_data_value=skip_data_value,
skip_attribute_value=skip_attribute_value,
)
if rst_element is None:
continue
rst_elements[line_number].append(rst_element)
elif name == "*":
extra_options = [
":force-partial-import:",
":members:",
":skip-description:"
]
if skip_data_value:
extra_options.append(":skip-data-value:")
if skip_attribute_value:
extra_options.append(":skip-attribute-value:")
rst_element = rst_generate(
directive="automodule",
element_id=from_module_id,
module_alias=module_name,
module_path_alias=module_path_name,
extra_options=extra_options
)
rst_elements[line_number].append(rst_element)
else:
rst_element = get_rst_name_from_file_environment(
name, from_file_env, alias, module_name, module_path_name,
skip_data_value=skip_data_value,
skip_attribute_value=skip_attribute_value,
)
if rst_element is None:
continue
rst_elements[line_number].append(rst_element)
return rst_elements
[docs]def get_rst_default_from_file_environment(
file_environment, alias, module_name, module_path_name,
skip_data_value=False, skip_attribute_value=False
):
"""Return :term:`reStructuredText` from default element in
*file_environment*.
*alias* is the name that should replace the element name.
*module_name* is the module alias that should replace the element
module name.
*module_path_name* is the module path alias that should be added to each
directive.
*skip_data_value* indicate whether data value should not be displayed.
*skip_attribute_value* indicate whether attribute value should not be
displayed.
.. warning::
Return None if no default is found in the file.
"""
for class_env in file_environment["class"].values():
if class_env["default"]:
extra_options = [":force-partial-import:"]
if skip_data_value:
extra_options.append(":skip-data-value:")
if skip_attribute_value:
extra_options.append(":skip-attribute-value:")
return rst_generate(
directive="autoclass",
element_id=class_env["id"],
alias=alias,
module_alias=module_name,
module_path_alias=module_path_name,
extra_options=extra_options
)
for function_env in file_environment["function"].values():
if function_env["default"]:
return rst_generate(
directive="autofunction",
element_id=function_env["id"],
alias=alias,
module_alias=module_name,
module_path_alias=module_path_name,
extra_options=[":force-partial-import:"]
)
for data_env in file_environment["data"].values():
if data_env["default"]:
extra_options = [":force-partial-import:"]
if skip_data_value:
extra_options.append(":skip-value:")
return rst_generate(
directive="autodata",
element_id=data_env["id"],
alias=alias,
module_alias=module_name,
module_path_alias=module_path_name,
extra_options=extra_options
)
[docs]def get_rst_name_from_file_environment(
name, file_environment, alias, module_name, module_path_name,
skip_data_value=False, skip_attribute_value=False
):
"""Return :term:`reStructuredText` element in *file_environment* from
*name*.
*alias* is the name that should replace the element name.
*module_name* is the module name that should replace the element
module name.
*module_path_name* is the module path alias that should be added to each
directive.
*skip_data_value* indicate whether data value should not be displayed.
*skip_attribute_value* indicate whether attribute value should not be
displayed.
.. warning::
Return None if the element is not found in the file.
"""
for class_env in file_environment["class"].values():
if class_env["name"] == name and class_env["exported"]:
extra_options = [":force-partial-import:"]
if skip_data_value:
extra_options.append(":skip-data-value:")
if skip_attribute_value:
extra_options.append(":skip-attribute-value:")
return rst_generate(
directive="autoclass",
element_id=class_env["id"],
alias=alias,
module_alias=module_name,
module_path_alias=module_path_name,
extra_options=extra_options
)
for function_env in file_environment["function"].values():
if function_env["name"] == name and function_env["exported"]:
return rst_generate(
directive="autofunction",
element_id=function_env["id"],
alias=alias,
module_alias=module_name,
module_path_alias=module_path_name,
extra_options=[":force-partial-import:"]
)
for data_env in file_environment["data"].values():
if data_env["name"] == name and data_env["exported"]:
extra_options = [":force-partial-import:"]
if skip_data_value:
extra_options.append(":skip-value:")
return rst_generate(
directive="autodata",
element_id=data_env["id"],
alias=alias,
module_alias=module_name,
module_path_alias=module_path_name,
extra_options=extra_options
)
[docs]def rst_generate(
directive, element_id, alias=None, module_alias=None,
module_path_alias=None, extra_options=None
):
"""Generate `StringList` from *directive* and *element_id*.
*directive* is one of the directive added to the :term:`Javascript`
domain by this sphinx extension.
*element_id* is an element ID returned by the
:mod:`~champollion.parser`.
*alias* is the name that should replace the element name.
*module_alias* is the module name that should replace the element
module name.
*module_path_alias* is the module path that should replace the element
module path.
*extra_options* can be a list of extra options to add to the directive.
"""
if extra_options is None:
extra_options = []
element_rst = "\n.. js:{directive}:: {id}\n".format(
directive=directive, id=element_id
)
if alias is not None:
element_rst += " :alias: {alias}\n".format(
alias=alias
)
if module_alias is not None:
element_rst += " :module-alias: {module}\n".format(
module=module_alias
)
if module_path_alias is not None:
element_rst += " :module-path-alias: {module}\n".format(
module=module_path_alias
)
for option in extra_options:
element_rst += " {option}\n".format(
option=option
)
element_rst += "\n"
return StringList(element_rst.split("\n"))
[docs]def rst_string(expression=""):
"""Return `StringList` from *expression*.
"""
return StringList(expression.split("\n"))