Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optional file option v2 #171

Merged
merged 6 commits into from
Jul 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 23 additions & 13 deletions doc/directives.rst
Original file line number Diff line number Diff line change
Expand Up @@ -61,15 +61,20 @@ and :rst:dir:`cpp:autodoc`, adding the ``file`` option.
.. rst:directive:: .. c:autovar:: name
.. rst:directive:: .. cpp:autovar:: name
Incorporate the documentation comment for the variable ``name`` in the file
``file``.
Incorporate the documentation comment for the variable ``name``.

If ``file`` is specified, look up ``name`` there, otherwise look up ``name``
in all previously parsed files in the current document.

.. rst:directive:option:: file
:type: text
The ``file`` option specifies to file to parse. The filename is
interpreted relative to the :data:`hawkmoth_root` configuration
option. (For the time being, this option is mandatory.)
The ``file`` option specifies the file to look up ``name`` in. This is
required if the file has not been parsed yet, and to disambiguate if
``name`` is found in multiple files.
The filename is interpreted relative to the :data:`hawkmoth_root`
configuration option.
For example:

Expand All @@ -78,6 +83,8 @@ and :rst:dir:`cpp:autodoc`, adding the ``file`` option.
.. c:autovar:: example_variable
:file: example_file.c
.. c:autovar:: another_variable
.. rst:directive:: .. c:autotype:: name
.. rst:directive:: .. cpp:autotype:: name
Expand Down Expand Up @@ -132,9 +139,12 @@ The directives support all the same directive options as :rst:dir:`c:autodoc`,
.. rst:directive:: .. c:autostruct:: name
.. rst:directive:: .. cpp:autostruct:: name
Incorporate the documentation comment for the structure ``name`` in the file
``file``, optionally including member documentation as specified by
``members``.
Incorporate the documentation comment for the structure ``name``, optionally
including member documentation as specified by ``members``.

The ``file`` option is as in :rst:dir:`c:autovar`. If ``file`` is specified,
look up ``name`` there, otherwise look up ``name`` in all previously parsed
files in the current document.

.. rst:directive:option:: members
:type: text
Expand All @@ -158,11 +168,9 @@ The directives support all the same directive options as :rst:dir:`c:autodoc`,
:file: example_file.c
.. c:autostruct:: example_struct
:file: example_file.c
:members:
.. c:autostruct:: example_struct
:file: example_file.c
:members: member_one, member_two
.. rst:directive:: .. cpp:autoclass:: name
Expand Down Expand Up @@ -201,7 +209,6 @@ The directives support all the same directive options as :rst:dir:`c:autodoc`,
:members:
.. c:autoenum:: example_enum
:file: example_file.c
:members: CONSTANT_ONE, CONSTANT_TWO
Generic Documentation Sections
Expand All @@ -214,13 +221,16 @@ specified file.
.. rst:directive:: .. c:autosection:: name
.. rst:directive:: .. cpp:autosection:: name
Incorporate the generic documentation comment identified by ``name`` in the
file ``file``. The ``file`` option is as in :rst:dir:`c:autovar`.
Incorporate the generic documentation comment identified by ``name``.

The ``name`` is derived from the first sentence of the comment, and may
contain whitespace. It starts from the first alphanumeric character,
inclusive, and extends to the next ``:``, ``.``, or newline, non-inclusive.

The ``file`` option is as in :rst:dir:`c:autovar`. If ``file`` is specified,
look up ``name`` there, otherwise look up ``name`` in all previously parsed
files in the current document.

For example:

.. code-block:: c
Expand Down
18 changes: 9 additions & 9 deletions src/hawkmoth/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ def __get_docstrings_for_root(self, viewlist, root):

def __get_docstrings(self, viewlist):
num_matches = 0
for root in self.__parsed_files(filter_filenames=list(self._get_filenames()),
for root in self.__parsed_files(filter_filenames=self._get_filenames(),
filter_clang_args=[self.__get_clang_args()]):
num_matches += self.__get_docstrings_for_root(viewlist, root)

Expand Down Expand Up @@ -147,8 +147,9 @@ def _get_filenames(self):
raise NotImplementedError(self.__class__.__name__ + '._get_filenames')

def run(self):
for filename in self._get_filenames():
self.__parse(filename)
if self._get_filenames():
for filename in self._get_filenames():
self.__parse(filename)

result = ViewList()

Expand All @@ -169,6 +170,7 @@ class _AutoDocDirective(_AutoBaseDirective):
optional_arguments = 100 # arbitrary limit

def _get_filenames(self):
ret = []
for pattern in self.arguments:
filenames = glob.glob(os.path.join(self.env.config.hawkmoth_root, pattern))
if len(filenames) == 0:
Expand All @@ -178,11 +180,13 @@ def _get_filenames(self):

for filename in filenames:
if os.path.isfile(filename):
yield os.path.abspath(filename)
ret.append(os.path.abspath(filename))
else:
self.logger.warning(f'Path "{filename}" matching pattern "{pattern}" is not a file.', # noqa: E501
location=(self.env.docname, self.lineno))

return ret

# Base class for named stuff
class _AutoSymbolDirective(_AutoBaseDirective):
"""Extract specified documentation comments from the specified file"""
Expand All @@ -197,12 +201,8 @@ class _AutoSymbolDirective(_AutoBaseDirective):

def _get_filenames(self):
filename = self.options.get('file')

# Note: For the time being the file option is mandatory (sic).
if not filename:
self.logger.warning(':file: option missing.',
location=(self.env.docname, self.lineno))
return []
return None

return [os.path.abspath(os.path.join(self.env.config.hawkmoth_root, filename))]

Expand Down
1 change: 0 additions & 1 deletion test/c/autostruct.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,5 @@ directives:
arguments:
- foo_struct
options:
file: struct.c
members:
expected: autostruct.rst
2 changes: 2 additions & 0 deletions test/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ def get_output(self):
if directive.directive != 'autodoc':
pytest.skip(f'{directive} directive test')

assert args[0] is not None

if directive.domain is not None:
args += [f'--domain={directive.domain}']

Expand Down
49 changes: 35 additions & 14 deletions test/test_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,33 +66,54 @@ def _filter_members(directive):

class ParserTestcase(testenv.Testcase):
def get_output(self):
roots = {}
docs_str = ''
errors_str = ''

for directive in self.directives:
input_filename = directive.get_input_filename()
filename = directive.get_input_filename()
if not filename:
continue

clang_args = directive.get_clang_args()

root, errors = parse(input_filename, domain=directive.domain, clang_args=clang_args)
key = (filename, tuple(clang_args))
if key in roots:
continue

tropt = directive.options.get('transform')
if tropt is not None:
transform = parser_transformations[tropt]
else:
transform = None
root, errors = parse(filename, domain=directive.domain, clang_args=clang_args)

process_docstring = lambda lines: _process_docstring(transform, lines)

for docstrings in root.walk(recurse=False, filter_types=_filter_types(directive),
filter_names=_filter_names(directive)):
for docstr in docstrings.walk(filter_names=_filter_members(directive)): # noqa: E501
lines = docstr.get_docstring(process_docstring=process_docstring)
docs_str += '\n'.join(lines) + '\n'
roots[key] = root

for error in errors:
errors_str += f'{error.level.name}: {os.path.basename(error.filename)}:{error.line}: {error.message}\n' # noqa: E501

for directive in self.directives:
filename = directive.get_input_filename()
filter_filenames = [filename] if filename is not None else None
filter_clang_args = [directive.get_clang_args()]

for root in roots.values():
if filter_filenames is not None and root.get_filename() not in filter_filenames:
continue

if filter_clang_args is not None and root.get_clang_args() not in filter_clang_args:
continue

tropt = directive.options.get('transform')
if tropt is not None:
transform = parser_transformations[tropt]
else:
transform = None

process_docstring = lambda lines: _process_docstring(transform, lines)

for docstrings in root.walk(recurse=False, filter_types=_filter_types(directive),
filter_names=_filter_names(directive)):
for docstr in docstrings.walk(filter_names=_filter_members(directive)):
lines = docstr.get_docstring(process_docstring=process_docstring)
docs_str += '\n'.join(lines) + '\n'

return docs_str, errors_str

def get_expected(self):
Expand Down
Loading