allow displaying entities from multiple scopes

This commit is contained in:
Dmitry Arkhipov
2025-05-01 11:25:41 +03:00
parent a658a96deb
commit 9cddedd1e3
5 changed files with 96 additions and 32 deletions
+7
View File
@@ -1258,6 +1258,13 @@ def load_configs(args):
for file_name in args.config: for file_name in args.config:
with open(file_name, 'r', encoding='utf-8') as file: with open(file_name, 'r', encoding='utf-8') as file:
result.update( json.load(file) ) result.update( json.load(file) )
if 'allowed_prefixes' not in result:
allowed_prefixes = ['']
default_ns = result.get('default_namespace')
if default_ns:
allowed_prefixes[0] = default_ns + '::'
result['allowed_prefixes'] = allowed_prefixes
return result return result
def collect_compound_refs(file): def collect_compound_refs(file):
+16 -13
View File
@@ -18,11 +18,19 @@ The template also expects a Config global dictionary that contains
configuration parameters from the merged JSON config files passed to the docca configuration parameters from the merged JSON config files passed to the docca
program. By default the dictionary looks like this: program. By default the dictionary looks like this:
{ {
"include_private": False "include_private": False,
"legacy_behavior": True,
"allowed_prefixes": [""],
} }
In adition: In adition:
* It uses "default_namespace" Config key to only output entities in a specific * It uses "default_namespace" Config key to strip fully qualifed names of
namespace. entities in that namespace from the prefix {default_namespace}::.
* It uses "allowed_prefixes" Config key to only output entities in a specific
scope. This is done by checking if the FQN of the entity is prefixed with
an allowed prefix, or if it is itself a prefix of an allowed prefix. By
default this setting is [""] (allow any entity) unless "default_namespace"
is set, in which case it looks like ["{default_namespace}::"] (allow
everything in the default namespace).
* It uses "link_prefix" Config key as prefix for every generated cross-link. * It uses "link_prefix" Config key as prefix for every generated cross-link.
* It uses "convenience_header" Config key for "Convenience Header" subsections. * It uses "convenience_header" Config key for "Convenience Header" subsections.
* It uses "show_defaulted" Config key to determine whether to display if a * It uses "show_defaulted" Config key to determine whether to display if a
@@ -317,16 +325,11 @@ are enabled.
#} #}
{% import "docca/quickbook/components.jinja2" as comps -%} {%- import "docca/quickbook/components.jinja2" as comps -%}
{% for entity in entities.values() -%} {%- for entity in entities.values() -%}
{% if entity is not Namespace -%} {%- if entity is not Namespace -%}
{% continue %} {%- continue -%}
{%- endif -%} {%- endif -%}
{% if Config.get('default_namespace') {{ comps.write_entity(entity) }}
and entity.fully_qualified_name != Config.default_namespace -%}
{% continue %}
{%- endif -%}
{{ comps.write_namespace(entity) }}
{%- endfor %} {%- endfor %}
+38 -18
View File
@@ -8,33 +8,39 @@ Official repository: https://github.com/boostorg/json
#} #}
{% macro write_entity(entity) -%} {% macro write_entity(entity) -%}
{% if entity.access != Access.private or Config.include_private -%} {% if (entity.access != Access.private or Config.include_private)
{%- if entity is Namespace -%} and not is_external(entity) -%}
{{ write_namespace(entity) }} {%- for prefix in Config.allowed_prefixes %}
{%- elif entity is Type -%} {%- set fqn = entity.fully_qualified_name -%}
{{ write_type(entity) }} {%- if fqn.startswith(prefix) or prefix.startswith(fqn) -%}
{%- elif entity is OverloadSet -%} {%- if entity is Namespace -%}
{{ write_overload_set(entity) }} {{ write_namespace(entity) }}
{%- elif entity is Variable -%} {%- elif entity is Type -%}
{{ write_variable(entity) }} {{ write_type(entity) }}
{%- elif entity is Function -%} {%- elif entity is OverloadSet -%}
{{ write_function(entity) }} {{ write_overload_set(entity) }}
{%- endif -%} {%- elif entity is Variable -%}
{{ write_variable(entity) }}
{%- elif entity is Function -%}
{{ write_function(entity) }}
{%- endif -%}
{%- endif -%}
{%- endfor -%}
{%- endif -%} {%- endif -%}
{%- endmacro %} {%- endmacro %}
{% macro write_namespace(entity) -%} {% macro write_namespace(entity) -%}
{%- for m in entity.members.values() | select("Type") | sort -%} {%- for m in entity.members.values() | select("Type") | sort -%}
{{ write_type(m) }} {{ write_entity(m) }}
{%- endfor -%} {%- endfor -%}
{%- for m in entity.members.values() | select("OverloadSet") | sort -%} {%- for m in entity.members.values() | select("OverloadSet") | sort -%}
{{ write_overload_set(m) }} {{ write_entity(m) }}
{%- endfor -%} {%- endfor -%}
{%- for m in entity.members.values() | select("Variable") | sort -%} {%- for m in entity.members.values() | select("Variable") | sort -%}
{{ write_variable(m) }} {{ write_entity(m) }}
{%- endfor -%} {%- endfor -%}
{%- endmacro %} {%- endmacro %}
@@ -685,9 +691,7 @@ Convenience header {{ source_header(Config.convenience_header) }}
[*{{ phrase(part, in_code=in_code) }}] [*{{ phrase(part, in_code=in_code) }}]
{%- elif part is EntityRef -%} {%- elif part is EntityRef -%}
{%- if in_code %}``{% endif -%} {%- if in_code %}``{% endif -%}
{%- if Config.get('external_marker') {%- if is_external(part.entity) -%}
and (part.entity.brief | map(attribute="text") | join | trim)
== Config.get('external_marker') -%}
[@ [@
{%- for part in part.entity.description -%} {%- for part in part.entity.description -%}
{%- if part is Section and part.kind == Section.See -%} {%- if part is Section and part.kind == Section.See -%}
@@ -837,3 +841,19 @@ Convenience header {{ source_header(Config.convenience_header) }}
{% macro escape(s) -%} {% macro escape(s) -%}
{{ s.replace("[", "\\[").replace("]", "\\]") }} {{ s.replace("[", "\\[").replace("]", "\\]") }}
{%- endmacro %} {%- endmacro %}
{%- macro is_external(entity) -%}
{%- if not Config.get('external_marker') -%}
{%- else -%}
{%- set ns = namespace(brief=entity.brief) -%}
{%- if entity is OverloadSet -%}
{%- set ns.brief = ns.brief[0] -%}
{%- endif -%}
{%- if (ns.brief | map(attribute="text") | join | trim)
== Config.get('external_marker') -%}
1
{%- else -%}
{%- endif -%}
{%- endif -%}
{%- endmacro -%}
+1 -1
View File
@@ -19,7 +19,7 @@ from docca_test_helpers import make_elem
@pytest.fixture @pytest.fixture
def cfg(): def cfg():
return dict(legacy_behavior=False) return dict(legacy_behavior=False, allowed_prefixes=[''])
@pytest.fixture @pytest.fixture
def entities(): def entities():
+34
View File
@@ -2282,6 +2282,7 @@ def test_load_configs(tmpdir):
assert conf == { assert conf == {
'include_private': False, 'include_private': False,
'legacy_behavior': True, 'legacy_behavior': True,
'allowed_prefixes': [''],
} }
c = os.path.join(tmpdir, 'c1') c = os.path.join(tmpdir, 'c1')
@@ -2293,6 +2294,7 @@ def test_load_configs(tmpdir):
'include_private': False, 'include_private': False,
'legacy_behavior': True, 'legacy_behavior': True,
'A': 1, 'A': 1,
'allowed_prefixes': [''],
} }
c = os.path.join(tmpdir, 'c2') c = os.path.join(tmpdir, 'c2')
@@ -2305,6 +2307,7 @@ def test_load_configs(tmpdir):
'legacy_behavior': True, 'legacy_behavior': True,
'A': 1, 'A': 1,
'B': 2, 'B': 2,
'allowed_prefixes': [''],
} }
c = os.path.join(tmpdir, 'c3') c = os.path.join(tmpdir, 'c3')
@@ -2318,6 +2321,37 @@ def test_load_configs(tmpdir):
'A': 3, 'A': 3,
'B': 2, 'B': 2,
'C': True, 'C': True,
'allowed_prefixes': [''],
}
c = os.path.join(tmpdir, 'c4')
with open(c, 'w', encoding='utf-8') as f:
f.write('{ "default_namespace": "qwerty::uiop12" }')
args.config.append(c)
conf = docca.load_configs(args)
assert conf == {
'include_private': False,
'legacy_behavior': True,
'A': 3,
'B': 2,
'C': True,
'default_namespace': 'qwerty::uiop12',
'allowed_prefixes': ['qwerty::uiop12::'],
}
c = os.path.join(tmpdir, 'c5')
with open(c, 'w', encoding='utf-8') as f:
f.write('{ "allowed_prefixes": ["a::", "b::c::"] }')
args.config.append(c)
conf = docca.load_configs(args)
assert conf == {
'include_private': False,
'legacy_behavior': True,
'A': 3,
'B': 2,
'C': True,
'default_namespace': 'qwerty::uiop12',
'allowed_prefixes': ['a::', 'b::c::'],
} }
def test_docca_include_dir(): def test_docca_include_dir():