2025-05-22 12:28:49 +00:00
|
|
|
import importlib
|
|
|
|
import inspect
|
|
|
|
import fnmatch
|
|
|
|
from io import TextIOWrapper
|
2025-06-06 14:34:39 +00:00
|
|
|
import os
|
2025-05-22 12:28:49 +00:00
|
|
|
|
|
|
|
|
|
|
|
def write_classes(f: TextIOWrapper, patterns: list[str], module_name: str, title: str, description: str = '', exclude: list[str] = []) -> None:
|
2025-06-06 14:34:39 +00:00
|
|
|
"""Write the classes to the file."""
|
2025-05-22 12:28:49 +00:00
|
|
|
module = importlib.import_module(module_name)
|
|
|
|
|
|
|
|
classes = [
|
|
|
|
name for name, obj in inspect.getmembers(module, inspect.isclass)
|
|
|
|
if (obj.__module__ == module_name and
|
2025-06-06 14:34:39 +00:00
|
|
|
any(fnmatch.fnmatch(name, pat) for pat in patterns if pat not in exclude) and
|
|
|
|
(obj.__doc__ and ('(Automatic generated stub)' not in obj.__doc__ or ' digital ' in obj.__doc__)) and
|
|
|
|
obj.__doc__ and '(no I/O function)' not in obj.__doc__
|
|
|
|
)
|
2025-05-22 12:28:49 +00:00
|
|
|
]
|
|
|
|
|
|
|
|
if description:
|
|
|
|
f.write(f'{description}\n\n')
|
|
|
|
|
2025-06-06 14:34:39 +00:00
|
|
|
write_dochtree(f, title, classes)
|
|
|
|
|
2025-05-22 12:28:49 +00:00
|
|
|
for cls in classes:
|
2025-06-06 14:34:39 +00:00
|
|
|
with open(f'docs/source/_autogenerated/{cls}.md', 'w') as f2:
|
|
|
|
f2.write(f'# {module_name}.{cls}\n')
|
|
|
|
f2.write('```{eval-rst}\n')
|
|
|
|
f2.write(f'.. autoclass:: {module_name}.{cls}\n')
|
|
|
|
f2.write(' :members:\n')
|
|
|
|
f2.write(' :show-inheritance:\n')
|
|
|
|
f2.write(' :inherited-members:\n')
|
2025-05-26 16:00:24 +00:00
|
|
|
if title not in ['Base classes', 'Bus coupler']:
|
2025-06-06 14:34:39 +00:00
|
|
|
f2.write(' :exclude-members: select, parameters\n')
|
|
|
|
f2.write('```\n\n')
|
|
|
|
|
|
|
|
|
|
|
|
def write_dochtree(f: TextIOWrapper, title: str, items: list[str]):
|
|
|
|
f.write('```{toctree}\n')
|
|
|
|
f.write(':maxdepth: 1\n')
|
|
|
|
f.write(f':caption: {title}:\n')
|
2025-06-06 14:36:55 +00:00
|
|
|
# f.write(':hidden:\n')
|
2025-06-06 14:34:39 +00:00
|
|
|
for text in items:
|
|
|
|
if not text.startswith('_'):
|
|
|
|
f.write(f"{text}\n")
|
|
|
|
f.write('```\n\n')
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
# Ensure the output directory exists
|
|
|
|
os.makedirs('docs/source/_autogenerated', exist_ok=True)
|
|
|
|
|
|
|
|
with open('docs/source/_autogenerated/index.md', 'w') as f:
|
|
|
|
f.write('# Classes and Modules\n\n')
|
|
|
|
|
|
|
|
write_classes(f, ['BK*', 'WAGO_750_352'], 'pyhoff.devices', title='Bus coupler',
|
2025-06-06 14:36:55 +00:00
|
|
|
description='These classes are bus couplers and are used to connect the IO bus terminals to a Ethernet interface.')
|
2025-06-06 14:34:39 +00:00
|
|
|
write_classes(f, ['KL*'], 'pyhoff.devices', title='Beckhoff bus terminals')
|
|
|
|
write_classes(f, ['WAGO*'], 'pyhoff.devices', title='WAGO bus terminals', exclude=['WAGO_750_352'])
|
|
|
|
write_classes(f, ['*Terminal*'], 'pyhoff.devices', title='Generic bus terminals')
|
|
|
|
write_classes(f, ['*'], 'pyhoff', title='Base classes',
|
2025-06-06 14:36:55 +00:00
|
|
|
description='These classes are base classes for devices and are typically not used directly.')
|
2025-06-06 14:34:39 +00:00
|
|
|
write_classes(f, ['*'], 'pyhoff.modbus', title='Modbus',
|
2025-06-06 14:36:55 +00:00
|
|
|
description='This modbus implementation is used internally.')
|