From 4d775a7baea29587b436f89af3a1386c6c862d57 Mon Sep 17 00:00:00 2001 From: Simon Cozens Date: Thu, 22 Feb 2024 11:31:55 +0000 Subject: [PATCH] Fix up automatic profile documentation --- Lib/fontbakery/sphinx_extensions/profile.py | 718 ++---------------- .../source/fontbakery/profiles/adobefonts.rst | 12 +- docs/source/fontbakery/profiles/cff.rst | 7 - docs/source/fontbakery/profiles/cmap.rst | 7 - docs/source/fontbakery/profiles/dsig.rst | 7 - .../source/fontbakery/profiles/fontbureau.rst | 12 +- docs/source/fontbakery/profiles/fontval.rst | 10 +- docs/source/fontbakery/profiles/fontwerk.rst | 11 +- docs/source/fontbakery/profiles/fvar.rst | 7 - docs/source/fontbakery/profiles/gdef.rst | 7 - docs/source/fontbakery/profiles/glyf.rst | 7 - .../fontbakery/profiles/googlefonts.rst | 12 +- .../profiles/googlefonts_conditions.rst | 7 - docs/source/fontbakery/profiles/gpos.rst | 7 - docs/source/fontbakery/profiles/head.rst | 7 - docs/source/fontbakery/profiles/hhea.rst | 7 - docs/source/fontbakery/profiles/index.rst | 8 - docs/source/fontbakery/profiles/iso15008.rst | 6 +- docs/source/fontbakery/profiles/kern.rst | 7 - docs/source/fontbakery/profiles/layout.rst | 7 - docs/source/fontbakery/profiles/loca.rst | 7 - docs/source/fontbakery/profiles/name.rst | 7 - docs/source/fontbakery/profiles/notofonts.rst | 12 +- docs/source/fontbakery/profiles/opentype.rst | 30 +- docs/source/fontbakery/profiles/os2.rst | 7 - docs/source/fontbakery/profiles/outline.rst | 6 +- docs/source/fontbakery/profiles/post.rst | 7 - docs/source/fontbakery/profiles/shaping.rst | 6 +- .../fontbakery/profiles/shared_conditions.rst | 7 - .../fontbakery/profiles/ufo_sources.rst | 6 +- 30 files changed, 100 insertions(+), 868 deletions(-) delete mode 100644 docs/source/fontbakery/profiles/cff.rst delete mode 100644 docs/source/fontbakery/profiles/cmap.rst delete mode 100644 docs/source/fontbakery/profiles/dsig.rst delete mode 100644 docs/source/fontbakery/profiles/fvar.rst delete mode 100644 docs/source/fontbakery/profiles/gdef.rst delete mode 100644 docs/source/fontbakery/profiles/glyf.rst delete mode 100644 docs/source/fontbakery/profiles/googlefonts_conditions.rst delete mode 100644 docs/source/fontbakery/profiles/gpos.rst delete mode 100644 docs/source/fontbakery/profiles/head.rst delete mode 100644 docs/source/fontbakery/profiles/hhea.rst delete mode 100644 docs/source/fontbakery/profiles/kern.rst delete mode 100644 docs/source/fontbakery/profiles/layout.rst delete mode 100644 docs/source/fontbakery/profiles/loca.rst delete mode 100644 docs/source/fontbakery/profiles/name.rst delete mode 100644 docs/source/fontbakery/profiles/os2.rst delete mode 100644 docs/source/fontbakery/profiles/post.rst delete mode 100644 docs/source/fontbakery/profiles/shared_conditions.rst diff --git a/Lib/fontbakery/sphinx_extensions/profile.py b/Lib/fontbakery/sphinx_extensions/profile.py index 47d6391c3d..a335d19164 100644 --- a/Lib/fontbakery/sphinx_extensions/profile.py +++ b/Lib/fontbakery/sphinx_extensions/profile.py @@ -1,662 +1,78 @@ -# from typing import Any, List, Tuple, Dict # cast -import re -import logging - -# we can get source code first line numbers with this module for object -import inspect +from typing import Any +from sphinx.ext.autodoc import ModuleDocumenter from sphinx.application import Sphinx -# from sphinx.ext.autodoc import Documenter -from sphinx.ext.autodoc import ModuleLevelDocumenter -from sphinx.pycode import ModuleAnalyzer, PycodeError - -# from sphinx.domains.python import PythonDomain -from sphinx.domains.python import _pseudo_parse_arglist -from sphinx.locale import __ -from sphinx.domains.python import PyObject -from sphinx import addnodes -from sphinx.util.inspect import signature as Signature -from sphinx.util.inspect import stringify_signature - - -from fontbakery.callable import ( - FontbakeryCallable, - FontBakeryCheck, - Disabled, -) - - -logger = logging.getLogger(__name__) +from fontbakery.fonts_profile import load_all_checks, checks_by_id -# mute the style checks for unused names -# will be removed eventually -if False: # pylint: disable=using-constant-test - FontbakeryCallable # pylint: disable=pointless-statement - FontBakeryCondition # pylint: disable=pointless-statement - FontBakeryCheck # pylint: disable=pointless-statement - Disabled # pylint: disable=pointless-statement +def setup(app: Sphinx) -> None: + app.setup_extension("sphinx.ext.autodoc") # Require autodoc extension + app.add_autodocumenter(FontbakeryProfileDocumenter) + load_all_checks() -__version__ = "0.0.1" - -# ModuleLevelDocumenter(Documenter): Specialized Documenter subclass for objects on -# module level (functions, classes, data/constants). Implements: resolve_name -# https://github.com/sphinx-doc/sphinx/blob/master/sphinx/ext/autodoc/__init__.py#L850 -# Documenter -class FontBakeryCallableDocumenter(ModuleLevelDocumenter): - """ - Specialized Documenter subclass for instances of FontBakeryCheck. - """ - - objtype = "fontbakerycallable" - can_doc_cls = FontbakeryCallable - member_order = 30 +class FontbakeryProfileDocumenter(ModuleDocumenter): + objtype = "profile" + directivetype = ModuleDocumenter.objtype + priority = 10 + ModuleDocumenter.priority @classmethod - def can_document_member(cls, member, membername, isattr, parent): - # type: (Any, str, bool, Any) -> bool - return isinstance(member, cls.can_doc_cls) + def can_document_member( + cls, member: Any, membername: str, isattr: bool, parent: Any + ) -> bool: + return hasattr(member, "PROFILE") - def format_args( + def add_content( self, - ): # pylint: disable=arguments-differ - # I am really not sure what went wrong here... - # - # type: () -> str - # We use the original signature from the wrapped _function - has_retval = isinstance(self.object, FontBakeryCondition) - - if not hasattr(self.object, "_func"): - # FIXME! I don't know what's this. - return None - - # FIXME: Unexpected keyword argument 'has_retval' - sig = Signature( # pylint: disable=unexpected-keyword-arg - self.object._func, - bound_method=False, - has_retval=has_retval, - ) - args = stringify_signature(sig) - # escape backslashes for reST - args = args.replace("\\", "\\\\") - return args - - def format_name(self): - # I'm using this to inject some new info into the check - # search for the separator ":::" in this document to see where - # the info is received. This is not a clean solution! - # - # in https://github.com/sphinx-doc/sphinx/ - # blob/master/sphinx/ext/autodoc/__init__.py#L374 - # - # it says: - # > This normally should be something that can be parsed by the generated - # > directive, but doesn't need to be (Sphinx will display it unparsed - # > then). - # See below in `handle_signature` where that ipdb debugger is started, usually - # that exception would be dropped and we drop out of signature building. - # (RAISED here in `_handle_signature` the ValueError when the regex - # doesn't match...) seems like the slash (/) is killing most of the header! - # Otherwise the ids display fine, the dots are fine. - # Also, in any case of name change, the [source] view is killed (removed!) - # the document and also genindex.html anchor works so far (with 7 instead of /) - # - res = super().format_name() - if self.objtype == "fontbakerycheck": - # A bit hackish, splitting somwhere else by ::: to retrieve the checkid - # we can get the source file first line number of self.object: - lineno = inspect.getsourcelines(self.object)[1] - res = ( - self.object.id + ":::" + f"{lineno}" + ":::" + res - ) # .replace('/', '7') - # else: - # res = super().format_name() - # print('formatted name:', res) - # > formatted name: com.google.fonts/check/ - # xavgcharwidth:::59:::com_google_fonts_check_xavgcharwidth - # > formatted name: bold_wght_coord - - return res - - # handle_signature: com_google_fonts_check_post_table_version(ttFont, is_ttf) - # - # sig signature: com_google_fonts_check_post_table_version(ttFont, is_ttf) - # result: ('com_google_fonts_check_post_table_version', None) - # signode: - # FontBakeryCheck - # - # fontbakery.profiles.post. - # - # com_google_fonts_check_post_table_version - # - # ttFont - # is_ttf - # - # - - def generate( - self, - more_content=None, - real_modname=None, - check_module=False, - all_members=False, - ): - # type: (Any, str, bool, bool) -> None - """Generate reST for the object given by *self.name*, and possibly for - its members. - - If *more_content* is given, include that content. If *real_modname* is - given, use that module name to find attribute docs. If *check_module* is - True, only generate if the object is defined in the module name it is - imported from. If *all_members* is True, document all members. - """ - # print('generate', more_content, real_modname, check_module, all_members) - # print(self.name) - # print('---------------------') - # > generate None fontbakery.profiles.post True True - # > fontbakery.profiles.post::com_google_fonts_check_post_table_version - # > --------------------- - # - # > generate None fontbakery.profiles.shared_conditions True True - # > fontbakery.profiles.shared_conditions::glyph_metrics_stats - # > --------------------- - if not self.parse_name(): - # need a module to import - logger.warning( - __( - "don't know which module to import for autodocumenting" - ' %r (try placing a "module" or "currentmodule" directive' - " in the document, or giving an explicit module name)" - ), - self.name, - type="autodoc", - ) - return - - # now, import the module and get object to document - if not self.import_object(): - return - - # doesn't do anything! - # if self.objtype == 'fontbakerycheck': - # self.name = self.object.id - - # If there is no real module defined, figure out which to use. - # The real module is used in the module analyzer to look up the module - # where the attribute documentation would actually be found in. - # This is used for situations where you have a module that collects the - # functions and classes of internal submodules. - self.real_modname = real_modname or self.get_real_modname() # type: str - - # try to also get a source code analyzer for attribute docs - try: - self.analyzer = ModuleAnalyzer.for_module(self.real_modname) - # parse right now, to get PycodeErrors on parsing (results will - # be cached anyway) - self.analyzer.find_attr_docs() - except PycodeError as err: - # FIXME: Too many arguments for logging format string - logger.debug( # pylint: disable=logging-too-many-args - "[autodoc] module analyzer failed: %s", - err, - ) - # no source file -- e.g. for builtin and C modules - self.analyzer = None - # at least add the module.__file__ as a dependency - if hasattr(self.module, "__file__") and self.module.__file__: - self.directive.record_dependencies.add(self.module.__file__) - else: - self.directive.record_dependencies.add(self.analyzer.srcname) - - # check __module__ of object (for members not given explicitly) - if check_module: - if not self.check_module(): - return - - sourcename = self.get_sourcename() - - # make sure that the result starts with an empty line. This is - # necessary for some situations where another directive preprocesses - # reST and no starting newline is present - self.add_line("", sourcename) - - # format the object's signature, if any - sig = self.format_signature() - - # generate the directive header and options, if applicable - self.add_directive_header(sig) - self.add_line("", sourcename) - - # e.g. the module directive doesn't have content - self.indent += self.content_indent - - # add all content (from docstrings, attribute docs etc.) - self.add_content(more_content) - - # document members, if possible - self.document_members(all_members) - - -class FontBakeryCheckDocumenter(FontBakeryCallableDocumenter): - objtype = "fontbakerycheck" - can_doc_cls = FontBakeryCheck - - def get_object_members(self, want_all: bool): - return False, [] - - -class FontBakeryConditionDocumenter(FontBakeryCallableDocumenter): - objtype = "fontbakerycondition" - can_doc_cls = object # XXX - - def get_object_members(self, want_all: bool): - return False, [] - -# REs for Python signatures -py_sig_re = re.compile( - r"""^ ([\w.]*\.)? # class name(s) - (\w+) \s* # thing name - (?: \(\s*(.*)\s*\) # optional: arguments - (?:\s* -> \s* (.*))? # return annotation - )? $ # and nothing more - """, - re.VERBOSE, -) - - -# PyObject: -# https://github.com/sphinx-doc/sphinx/blob/master/sphinx/domains/python.py#L189 -# PyObject is a subclass of sphinx.directives.ObjectDescription -# ObjectDescription is a sphinx.util.docutils.SphinxDirective -# SphinxDirective is a docutils.parsers.rst.Directive -class PyFontBakeryObject(PyObject): - """ - Description of a class-like object (classes, interfaces, exceptions). - """ - - allow_nesting = True - - @property - def pretty_objtype(self): - if self.objtype.startswith("fontbakery"): - suffix = self.objtype[len("fontbakery") :] # noqa: E203 - return "FontBakery" + suffix[0].upper() + suffix[1:] - return self.objtype - - # this is bullshit, returns two values but manipulates - # signode massively, which is undocumented. - # signode is an instance of from - # https://github.com/sphinx-doc/sphinx/blob/master/sphinx/domains/python.py#L237 - def _handle_signature(self, cid, lineno, sig, signode): - # type: (str, addnodes.desc_signature) -> Tuple[str, str] - """Transform a Python signature into RST nodes. - - Return (fully qualified name of the thing, classname if any). - - If inside a class, the current class name is handled intelligently: - * it is stripped from the displayed name if present - * it is added to the full name (return value) if not present - - This is the xml string result of signode, whitespace is not - equivalent for readability. - - FontBakeryCheck - fontbakery.profiles.cmap. - com_google_fonts_check_all_glyphs_have_codepoints - - - ttFont - - - - """ - m = py_sig_re.match(sig) - if m is None: - # this is the immediate fail!!! - raise ValueError - prefix, name, arglist, retann = m.groups() - # print('prefix, name, arglist, retann =', prefix, name, arglist, retann) - # > prefix, name, arglist, retann = - # None com_google_fonts_check_all_glyphs_have_codepoints ttFont None - - # determine module and class name (if applicable), as well as full name - modname = self.options.get("module", self.env.ref_context.get("py:module")) - classname = self.env.ref_context.get("py:class") - if classname: - add_module = False - if prefix and (prefix == classname or prefix.startswith(classname + ".")): - fullname = prefix + name - # class name is given again in the signature - prefix = prefix[len(classname) :].lstrip(".") # noqa: E203 - elif prefix: - # class name is given in the signature, but different - # (shouldn't happen) - fullname = classname + "." + prefix + name - else: - # class name is not given in the signature - fullname = classname + "." + name - else: - add_module = True - if prefix: - classname = prefix.rstrip(".") - fullname = prefix + name - else: - classname = "" - fullname = name - - signode["module"] = modname - signode["class"] = classname - signode["fullname"] = fullname - signode.attributes["lineno"] = lineno - - # sig_prefix = self.get_signature_prefix(sig) - # if sig_prefix: - # signode += addnodes.desc_annotation(sig_prefix, sig_prefix) - - if prefix: - signode += addnodes.desc_addname(prefix, prefix) - elif add_module and self.env.config.add_module_names: - if modname and modname != "exceptions": - # exceptions are a special case, since they are documented in the - # 'exceptions' module. - # nodetext = modname + ' ID: ' - # signode += addnodes.desc_addname(nodetext, nodetext) - pass - - signode += addnodes.desc_name(name, cid) - if arglist: - _pseudo_parse_arglist(signode, arglist) - else: - if self.needs_arglist(): - # for callables, add an empty parameter list - signode += addnodes.desc_parameterlist() - - if retann: - signode += addnodes.desc_returns(retann, retann) - - anno = self.options.get("annotation") - if anno: - signode += addnodes.desc_annotation(" " + anno, " " + anno) - - return cid, prefix - - def handle_signature(self, sig, signode): - # print('>>>>>>>>>>>>>>>>>handle_signature:', sig, signode) - # > >>>>>>>>>>>>>>>>>handle_signature: - # com.google.fonts/check/ - # all_glyphs_have_codepoints:::36::: - # com_google_fonts_check_all_glyphs_have_codepoints(ttFont) - # - - cid = None - if ":::" in sig: - cid, lineno, sig = sig.split(":::") - # print('GOT id:', cid, lineno, 'for:', sig) - # > GOT id: com.google.fonts/check/all_glyphs_have_codepoints 36 - # for: com_google_fonts_check_all_glyphs_have_codepoints(ttFont) - - res = "(NONE!)" - try: - res = ( - self._handle_signature(cid, lineno, sig, signode) - if cid is not None - else super().handle_signature(sig, signode) - ) - except Exception as e: - print("!!!", e) - raise e - - return res - - # This ends in: path-to-docs/html/genindex.html - def get_index_text(self, modname, name): - # type: (str, Tuple[str, str]) -> str - - return f"{name[0]} ({self.pretty_objtype} in {modname})" - # fontbakerycheck - # modname: fontbakery.profiles.cmap - # name_cls:('com_google_fonts_check_all_glyphs_have_codepoints', None) - # return f' {self.objtype} modname: {modname} name_cls:{name_cls}' - - def add_target_and_index(self, name_cls, sig, signode): - # type: (Tuple[str, str], str, addnodes.desc_signature) -> None - modname = self.options.get("module", self.env.ref_context.get("py:module")) - # fullname = (modname and modname + '.' or '') + name_cls[0] - fullname = name_cls[0] - # note target - if fullname not in self.state.document.ids: - signode["names"].append(fullname) - signode["ids"].append(fullname) - signode["first"] = not self.names - self.state.document.note_explicit_target(signode) - - # note, there will be a change to this in a future release - # https://github.com/sphinx-doc/sphinx/ - # commit/259be8716ad4b2332aa4d7693d73400eb06fa7d7 - # in the past (now) - objects = self.env.domaindata["py"]["objects"] - if fullname in objects: - self.state_machine.reporter.warning( - "duplicate object description of %s, " % fullname - + "other instance in " - + self.env.doc2path(objects[fullname][0]) - + ", use :noindex: for one of them", - line=self.lineno, - ) - objects[fullname] = (self.env.docname, self.objtype) - # in the future - # domain = cast(PythonDomain, self.env.get_domain('py')) - # domain.note_object(fullname, self.objtype) - - indextext = self.get_index_text(modname, name_cls) - if indextext: - self.indexnode["entries"].append(("single", indextext, fullname, "", None)) - - -# Copied a lot from napoleon extension: -# https://github.com/sphinx-doc/sphinx/blob/master/sphinx/ext/napoleon/__init__.py -# To get started, hooking into autodoc seems the way to go, hence that was -# a good fit. - - -def setup(app): - # type: (Sphinx) -> Dict[str, Any] - """Sphinx extension setup function. - When the extension is loaded, Sphinx imports this module and executes - the ``setup()`` function, which in turn notifies Sphinx of everything - the extension offers. - Parameters - ---------- - app : sphinx.application.Sphinx - Application object representing the Sphinx process - See Also - -------- - `The Sphinx documentation on Extensions - `_ - `The Extension Tutorial `_ - `The Extension API `_ - """ - if not isinstance(app, Sphinx): - # probably called by tests - return {"version": __version__, "parallel_read_safe": True} - - # _patch_python_domain() - - # => this: - app.add_autodocumenter(FontBakeryCallableDocumenter) - app.add_autodocumenter(FontBakeryCheckDocumenter) - app.add_autodocumenter(FontBakeryConditionDocumenter) - - # https://github.com/sphinx-doc/sphinx/blob/master/sphinx/domains/python.py - app.add_directive_to_domain( - "py", "fontbakerycallable", PyFontBakeryObject, override=False - ) - app.add_directive_to_domain( - "py", "fontbakerycheck", PyFontBakeryObject, override=False - ) - app.add_directive_to_domain( - "py", "fontbakerycondition", PyFontBakeryObject, override=False - ) - - # => see e.g.: https://github.com/sphinx-doc/sphinx/ - # blob/master/sphinx/ext/autodoc/__init__.py#L984 - - app.setup_extension("sphinx.ext.autodoc") - app.connect("autodoc-process-docstring", _process_docstring) - app.connect("autodoc-skip-member", _skip_member) - - # for name, (default, rebuild) in Config._config_values.items(): - # app.add_config_value(name, default, rebuild) - return {"version": __version__, "parallel_read_safe": True} - - -def _skip_member(app, what, name, obj, skip, options): - # type: (Sphinx, str, str, Any, bool, Any) -> bool - """Determine if private and special class members are included in docs. - The following settings in conf.py determine if private and special class - members or init methods are included in the generated documentation: - * ``napoleon_include_init_with_doc`` -- - include init methods if they have docstrings - * ``napoleon_include_private_with_doc`` -- - include private members if they have docstrings - * ``napoleon_include_special_with_doc`` -- - include special members if they have docstrings - Parameters - ---------- - app : sphinx.application.Sphinx - Application object representing the Sphinx process - what : str - A string specifying the type of the object to which the member - belongs. Valid values: "module", "class", "exception", "function", - "method", "attribute". - name : str - The name of the member. - obj : module, class, exception, function, method, or attribute. - For example, if the member is the __init__ method of class A, then - `obj` will be `A.__init__`. - skip : bool - A boolean indicating if autodoc will skip this member if `_skip_member` - does not override the decision - options : sphinx.ext.autodoc.Options - The options given to the directive: an object with attributes - inherited_members, undoc_members, show_inheritance and noindex that - are True if the flag option of same name was given to the auto - directive. - Returns - ------- - bool - True if the member should be skipped during creation of the docs, - False if it should be included in the docs. - """ - if name in [ - "check_skip_filter", - "conditions", - "configs", - "description", - "documentation", - "experimental", - "force", - "id", - "is_librebarcode", - "name", - "proponent", - "proposal", - "rationale", - "severity", - "suggested_profile", - ]: - return True - else: - return None - - -def _process_docstring(app, what, name, obj, options, lines): - # type: (Sphinx, str, str, Any, Any, List[str]) -> None - """Process the docstring for a given python object. - Called when autodoc has read and processed a docstring. `lines` is a list - of docstring lines that `_process_docstring` modifies in place to change - what Sphinx outputs. - The following settings in conf.py control what styles of docstrings will - be parsed: - * ``napoleon_google_docstring`` -- parse Google style docstrings - * ``napoleon_numpy_docstring`` -- parse NumPy style docstrings - Parameters - ---------- - app : sphinx.application.Sphinx - Application object representing the Sphinx process. - what : str - A string specifying the type of the object to which the docstring - belongs. Valid values: "module", "class", "exception", "function", - "method", "attribute". - name : str - The fully qualified name of the object. - obj : module, class, exception, function, method, or attribute - The object to which the docstring belongs. - options : sphinx.ext.autodoc.Options - The options given to the directive: an object with attributes - inherited_members, undoc_members, show_inheritance and noindex that - are True if the flag option of same name was given to the auto - directive. - lines : list of str - The lines of the docstring, see above. - .. note:: `lines` is modified *in place* - """ - - if hasattr(obj, "rationale") and obj.rationale: - lines.append("**Rationale:**") - for line in obj.rationale.split("\n"): - lines.append(line) - - if hasattr(obj, "proposal") and obj.proposal: - proposal = obj.proposal - if not isinstance(obj.proposal, list): - proposal = [obj.proposal] - - proposals = [p for p in proposal if "legacy:" not in p] - legacy_name = [p.split("legacy:")[1] for p in proposal if "legacy:" in p] - - if legacy_name: - lines.append( - f"**Legacy check** originally simply called '{legacy_name[0]}'." - f" We used to lack richer metadata back in 2015. We're open to" - f" further improvements to this description." - ) - else: - if proposals: - lines.append(f"- **Originally proposed at** {proposals.pop(0)}") - - if proposals: - proposals = " / ".join(proposals) - lines.append(f"- **Some additional changes** were proposed at {proposals}") - - if hasattr(obj, "proponent") and obj.proponent: - proponent = obj.proponent - if "(@" in obj.proponent and ")" in obj.proponent: - fullname, username = obj.proponent.split("(@") - fullname = fullname.strip() - username = username.split(")")[0].strip() - proponent = f"`{fullname} `_" - lines.append(f"- **Proposed by**: {proponent}") - - if hasattr(obj, "suggested_profile") and obj.suggested_profile: - lines.append(f"- **Suggested profile:** {obj.suggested_profile}") - - if hasattr(obj, "experimental") and obj.experimental: - lines.append( - f"- **EXPERIMENTAL:** {obj.experimental}. Please provide feedback!" - ) + more_content: Any | None, + # no_docstring: bool = False, + ) -> None: + super().add_content(more_content) + source_name = self.get_sourcename() + profile = self.object + overrides = profile.PROFILE.get("overrides", {}) + defaults = profile.PROFILE.get("configuration_defaults", {}) + if "include_profiles" in profile.PROFILE: + # This could be a link + included = [ + f":doc:`{profile}`" for profile in profile.PROFILE["include_profiles"] + ] + self.add_line("Included profiles: " + ", ".join(included), source_name) + self.add_line("", source_name) + for section, checks in profile.PROFILE["sections"].items(): + self.add_line(f"{section}", source_name) + for check in checks: + if check in checks_by_id: + self.add_line( + f" - *{check}*: {checks_by_id[check].description}", source_name + ) + else: + self.add_line(f" - *{check}*", source_name) + if check in overrides: + self.add_line("", source_name) + for override in overrides[check]: + code, status, reason = ( + override["code"], + override["status"], + override.get("reason"), + ) + self.add_line( + f" - The **{code}** result is reported as a" + " **{status}** in this profile", + source_name, + ) + if reason: + self.add_line("", source_name) + self.add_line(f" {reason}", source_name) + self.add_line("", source_name) + if check in defaults: + self.add_line("", source_name) + self.add_line( + " - For this check, the following parameters are configured:", + source_name, + ) + self.add_line("", source_name) + for param, value in defaults[check].items(): + self.add_line(f" - ``{param}``: ``{value}``", source_name) + self.add_line("", source_name) diff --git a/docs/source/fontbakery/profiles/adobefonts.rst b/docs/source/fontbakery/profiles/adobefonts.rst index 51da6a5d02..00ac46c1a1 100644 --- a/docs/source/fontbakery/profiles/adobefonts.rst +++ b/docs/source/fontbakery/profiles/adobefonts.rst @@ -1,9 +1,5 @@ -########## -adobefonts -########## +########### +Adobe Fonts +########### -All vendor-specific profiles such as the `adobefonts` one also include the checks from the :doc:`universal` profile. - -.. automodule:: fontbakery.profiles.adobefonts - :members: - :undoc-members: +.. autoprofile:: fontbakery.profiles.adobefonts diff --git a/docs/source/fontbakery/profiles/cff.rst b/docs/source/fontbakery/profiles/cff.rst deleted file mode 100644 index ca874f8d66..0000000000 --- a/docs/source/fontbakery/profiles/cff.rst +++ /dev/null @@ -1,7 +0,0 @@ -### -cff -### - -.. automodule:: fontbakery.profiles.cff - :members: - :undoc-members: diff --git a/docs/source/fontbakery/profiles/cmap.rst b/docs/source/fontbakery/profiles/cmap.rst deleted file mode 100644 index 7601f317fd..0000000000 --- a/docs/source/fontbakery/profiles/cmap.rst +++ /dev/null @@ -1,7 +0,0 @@ -#### -cmap -#### - -.. automodule:: fontbakery.profiles.cmap - :members: - :undoc-members: diff --git a/docs/source/fontbakery/profiles/dsig.rst b/docs/source/fontbakery/profiles/dsig.rst deleted file mode 100644 index 836a00518b..0000000000 --- a/docs/source/fontbakery/profiles/dsig.rst +++ /dev/null @@ -1,7 +0,0 @@ -#### -dsig -#### - -.. automodule:: fontbakery.profiles.dsig - :members: - :undoc-members: diff --git a/docs/source/fontbakery/profiles/fontbureau.rst b/docs/source/fontbakery/profiles/fontbureau.rst index 2f2acf0620..7d23cedc05 100644 --- a/docs/source/fontbakery/profiles/fontbureau.rst +++ b/docs/source/fontbakery/profiles/fontbureau.rst @@ -1,9 +1,5 @@ -########## -fontbureau -########## +########### +Font Bureau +########### -All vendor-specific profiles such as the `fontbureau` one also include the checks from the :doc:`universal` profile. - -.. automodule:: fontbakery.profiles.fontbureau - :members: - :undoc-members: +.. autoprofile:: fontbakery.profiles.fontbureau diff --git a/docs/source/fontbakery/profiles/fontval.rst b/docs/source/fontbakery/profiles/fontval.rst index c7c7ba1e05..2597fdc0df 100644 --- a/docs/source/fontbakery/profiles/fontval.rst +++ b/docs/source/fontbakery/profiles/fontval.rst @@ -1,7 +1,5 @@ -####### -fontval -####### +######################## +Microsoft Font Validator +######################## -.. automodule:: fontbakery.profiles.fontval - :members: - :undoc-members: +.. autoprofile:: fontbakery.profiles.fontval diff --git a/docs/source/fontbakery/profiles/fontwerk.rst b/docs/source/fontbakery/profiles/fontwerk.rst index f542e07e86..bc57ca1adb 100644 --- a/docs/source/fontbakery/profiles/fontwerk.rst +++ b/docs/source/fontbakery/profiles/fontwerk.rst @@ -1,12 +1,5 @@ ######## -fontwerk +Fontwerk ######## -All vendor-specific profiles such as the `fontwerk` one also include the checks from the :doc:`universal` profile. Fontwerk also includes most checks from the :doc:`googlefonts` profile, except these: - -.. literalinclude:: ../../../../Lib/fontbakery/profiles/fontwerk.py - :pyobject: leave_this_one_out - -.. automodule:: fontbakery.profiles.fontwerk - :members: - :undoc-members: +.. autoprofile:: fontbakery.profiles.fontwerk \ No newline at end of file diff --git a/docs/source/fontbakery/profiles/fvar.rst b/docs/source/fontbakery/profiles/fvar.rst deleted file mode 100644 index b4836fee8a..0000000000 --- a/docs/source/fontbakery/profiles/fvar.rst +++ /dev/null @@ -1,7 +0,0 @@ -#### -fvar -#### - -.. automodule:: fontbakery.profiles.fvar - :members: - :undoc-members: diff --git a/docs/source/fontbakery/profiles/gdef.rst b/docs/source/fontbakery/profiles/gdef.rst deleted file mode 100644 index 10d5f28e5d..0000000000 --- a/docs/source/fontbakery/profiles/gdef.rst +++ /dev/null @@ -1,7 +0,0 @@ -#### -gdef -#### - -.. automodule:: fontbakery.profiles.gdef - :members: - :undoc-members: diff --git a/docs/source/fontbakery/profiles/glyf.rst b/docs/source/fontbakery/profiles/glyf.rst deleted file mode 100644 index 1f931ba19d..0000000000 --- a/docs/source/fontbakery/profiles/glyf.rst +++ /dev/null @@ -1,7 +0,0 @@ -#### -glyf -#### - -.. automodule:: fontbakery.profiles.glyf - :members: - :undoc-members: diff --git a/docs/source/fontbakery/profiles/googlefonts.rst b/docs/source/fontbakery/profiles/googlefonts.rst index 9f202f5c4d..9e25c2d903 100644 --- a/docs/source/fontbakery/profiles/googlefonts.rst +++ b/docs/source/fontbakery/profiles/googlefonts.rst @@ -1,9 +1,5 @@ -########### -googlefonts -########### +############ +Google Fonts +############ -All vendor-specific profiles such as the `googlefonts` one also include the checks from the :doc:`universal` profile. - -.. automodule:: fontbakery.profiles.googlefonts - :members: - :undoc-members: +.. autoprofile:: fontbakery.profiles.googlefonts diff --git a/docs/source/fontbakery/profiles/googlefonts_conditions.rst b/docs/source/fontbakery/profiles/googlefonts_conditions.rst deleted file mode 100644 index 6c24821a77..0000000000 --- a/docs/source/fontbakery/profiles/googlefonts_conditions.rst +++ /dev/null @@ -1,7 +0,0 @@ -###################### -googlefonts_conditions -###################### - -.. automodule:: fontbakery.profiles.googlefonts_conditions - :members: - :undoc-members: diff --git a/docs/source/fontbakery/profiles/gpos.rst b/docs/source/fontbakery/profiles/gpos.rst deleted file mode 100644 index 1935c73ba4..0000000000 --- a/docs/source/fontbakery/profiles/gpos.rst +++ /dev/null @@ -1,7 +0,0 @@ -#### -gpos -#### - -.. automodule:: fontbakery.profiles.gpos - :members: - :undoc-members: diff --git a/docs/source/fontbakery/profiles/head.rst b/docs/source/fontbakery/profiles/head.rst deleted file mode 100644 index 5ff7410081..0000000000 --- a/docs/source/fontbakery/profiles/head.rst +++ /dev/null @@ -1,7 +0,0 @@ -#### -head -#### - -.. automodule:: fontbakery.profiles.head - :members: - :undoc-members: diff --git a/docs/source/fontbakery/profiles/hhea.rst b/docs/source/fontbakery/profiles/hhea.rst deleted file mode 100644 index 6c50a14486..0000000000 --- a/docs/source/fontbakery/profiles/hhea.rst +++ /dev/null @@ -1,7 +0,0 @@ -#### -hhea -#### - -.. automodule:: fontbakery.profiles.hhea - :members: - :undoc-members: diff --git a/docs/source/fontbakery/profiles/index.rst b/docs/source/fontbakery/profiles/index.rst index eabfd2b0ae..b49bfc1866 100644 --- a/docs/source/fontbakery/profiles/index.rst +++ b/docs/source/fontbakery/profiles/index.rst @@ -15,13 +15,5 @@ profiles fontval ufo_sources iso15008 - layout outline shaping - shared_conditions - googlefonts_conditions - - -.. automodule:: fontbakery.profiles - :members: - :undoc-members: diff --git a/docs/source/fontbakery/profiles/iso15008.rst b/docs/source/fontbakery/profiles/iso15008.rst index 3b3f135225..25ae966414 100644 --- a/docs/source/fontbakery/profiles/iso15008.rst +++ b/docs/source/fontbakery/profiles/iso15008.rst @@ -1,7 +1,5 @@ ######## -iso15008 +ISO15008 ######## -.. automodule:: fontbakery.profiles.iso15008 - :members: - :undoc-members: +.. autoprofile:: fontbakery.profiles.iso15008 diff --git a/docs/source/fontbakery/profiles/kern.rst b/docs/source/fontbakery/profiles/kern.rst deleted file mode 100644 index 287ebaed2b..0000000000 --- a/docs/source/fontbakery/profiles/kern.rst +++ /dev/null @@ -1,7 +0,0 @@ -#### -kern -#### - -.. automodule:: fontbakery.profiles.kern - :members: - :undoc-members: diff --git a/docs/source/fontbakery/profiles/layout.rst b/docs/source/fontbakery/profiles/layout.rst deleted file mode 100644 index 8ab6605efd..0000000000 --- a/docs/source/fontbakery/profiles/layout.rst +++ /dev/null @@ -1,7 +0,0 @@ -###### -layout -###### - -.. automodule:: fontbakery.profiles.layout - :members: - :undoc-members: diff --git a/docs/source/fontbakery/profiles/loca.rst b/docs/source/fontbakery/profiles/loca.rst deleted file mode 100644 index f671e989ab..0000000000 --- a/docs/source/fontbakery/profiles/loca.rst +++ /dev/null @@ -1,7 +0,0 @@ -#### -loca -#### - -.. automodule:: fontbakery.profiles.loca - :members: - :undoc-members: diff --git a/docs/source/fontbakery/profiles/name.rst b/docs/source/fontbakery/profiles/name.rst deleted file mode 100644 index 5d328d8ba1..0000000000 --- a/docs/source/fontbakery/profiles/name.rst +++ /dev/null @@ -1,7 +0,0 @@ -#### -name -#### - -.. automodule:: fontbakery.profiles.name - :members: - :undoc-members: diff --git a/docs/source/fontbakery/profiles/notofonts.rst b/docs/source/fontbakery/profiles/notofonts.rst index 45563c5774..98be01a645 100644 --- a/docs/source/fontbakery/profiles/notofonts.rst +++ b/docs/source/fontbakery/profiles/notofonts.rst @@ -1,9 +1,5 @@ -######### -notofonts -######### +########## +Noto Fonts +########## -All vendor-specific profiles such as the `notofonts` one also include the checks from the :doc:`universal` profile. - -.. automodule:: fontbakery.profiles.notofonts - :members: - :undoc-members: +.. autoprofile:: fontbakery.profiles.notofonts diff --git a/docs/source/fontbakery/profiles/opentype.rst b/docs/source/fontbakery/profiles/opentype.rst index 70dd06fcd0..8a597b1205 100644 --- a/docs/source/fontbakery/profiles/opentype.rst +++ b/docs/source/fontbakery/profiles/opentype.rst @@ -1,30 +1,6 @@ ######## -opentype +Opentype ######## -The checks of the `opentype` profile are separated in one sub-profile for each of the Open Type tables as listed below: - -.. toctree:: - :maxdepth: 1 - - cff - cmap - dsig - fvar - gdef - glyf - gpos - head - hhea - kern - loca - name - os2 - post - layout - -.. automodule:: fontbakery.profiles.opentype - :members: - :undoc-members: - - .. automodule:: fontbakery.profiles +.. autoprofile:: fontbakery.profiles.opentype + \ No newline at end of file diff --git a/docs/source/fontbakery/profiles/os2.rst b/docs/source/fontbakery/profiles/os2.rst deleted file mode 100644 index 73ac520814..0000000000 --- a/docs/source/fontbakery/profiles/os2.rst +++ /dev/null @@ -1,7 +0,0 @@ -### -os2 -### - -.. automodule:: fontbakery.profiles.os2 - :members: - :undoc-members: diff --git a/docs/source/fontbakery/profiles/outline.rst b/docs/source/fontbakery/profiles/outline.rst index a3d10390b6..54ed358958 100644 --- a/docs/source/fontbakery/profiles/outline.rst +++ b/docs/source/fontbakery/profiles/outline.rst @@ -1,7 +1,5 @@ ####### -outline +Outline ####### -.. automodule:: fontbakery.profiles.outline - :members: - :undoc-members: +.. autoprofile:: fontbakery.profiles.outline diff --git a/docs/source/fontbakery/profiles/post.rst b/docs/source/fontbakery/profiles/post.rst deleted file mode 100644 index c549b68b55..0000000000 --- a/docs/source/fontbakery/profiles/post.rst +++ /dev/null @@ -1,7 +0,0 @@ -#### -post -#### - -.. automodule:: fontbakery.profiles.post - :members: - :undoc-members: diff --git a/docs/source/fontbakery/profiles/shaping.rst b/docs/source/fontbakery/profiles/shaping.rst index 58d898ad2f..ef67e63c4c 100644 --- a/docs/source/fontbakery/profiles/shaping.rst +++ b/docs/source/fontbakery/profiles/shaping.rst @@ -1,7 +1,5 @@ ####### -shaping +Shaping ####### -.. automodule:: fontbakery.profiles.shaping - :members: - :undoc-members: +.. autoprofile:: fontbakery.profiles.shaping diff --git a/docs/source/fontbakery/profiles/shared_conditions.rst b/docs/source/fontbakery/profiles/shared_conditions.rst deleted file mode 100644 index 7b72f78900..0000000000 --- a/docs/source/fontbakery/profiles/shared_conditions.rst +++ /dev/null @@ -1,7 +0,0 @@ -################# -shared_conditions -################# - -.. automodule:: fontbakery.profiles.shared_conditions - :members: - :undoc-members: diff --git a/docs/source/fontbakery/profiles/ufo_sources.rst b/docs/source/fontbakery/profiles/ufo_sources.rst index 0ac9fa4578..ac7ab33da7 100644 --- a/docs/source/fontbakery/profiles/ufo_sources.rst +++ b/docs/source/fontbakery/profiles/ufo_sources.rst @@ -1,7 +1,5 @@ ########### -ufo_sources +UFO Sources ########### -.. automodule:: fontbakery.profiles.ufo_sources - :members: - :undoc-members: +.. autoprofile:: fontbakery.profiles.ufo_sources