in python/scripts/generate_type_stubs_and_docs.py [0:0]
def patch_pybind11_stubgen():
"""
Patch ``pybind11_stubgen`` to generate more ergonomic code for Enum-like classes.
This generates a subclass of :class:``Enum`` for each Pybind11-generated Enum,
which is not strictly correct, but produces much nicer documentation and allows
for a much more Pythonic API.
"""
original_class_stubs_generator_new = ClassStubsGenerator.__new__
class EnumClassStubsGenerator(StubsGenerator):
def __init__(self, klass):
self.klass = klass
assert inspect.isclass(klass)
assert klass.__name__.isidentifier()
assert hasattr(klass, "__entries")
self.doc_string = None
self.enum_names = []
self.enum_values = []
self.enum_docstrings = []
def get_involved_modules_names(self):
return set()
def parse(self):
self.doc_string = self.klass.__doc__ or ""
self.doc_string = self.doc_string.split("Members:")[0]
for name, (value_object, docstring) in getattr(self.klass, "__entries").items():
self.enum_names.append(name)
self.enum_values.append(value_object.value)
self.enum_docstrings.append(docstring)
def to_lines(self):
result = [
"class {class_name}(Enum):{doc_string}".format(
class_name=self.klass.__name__,
doc_string="\n" + self.format_docstring(self.doc_string)
if self.doc_string
else "",
),
]
for name, value, docstring in sorted(
list(zip(self.enum_names, self.enum_values, self.enum_docstrings)),
key=lambda x: x[1],
):
result.append(f" {name} = {value} # fmt: skip")
result.append(f"{self.format_docstring(docstring or '')}")
if not self.enum_names:
result.append(self.indent("pass"))
return result
def patched_class_stubs_generator_new(cls, klass, *args, **kwargs):
if hasattr(klass, "__entries"):
return EnumClassStubsGenerator(klass, *args, **kwargs)
else:
return original_class_stubs_generator_new(cls)
ClassStubsGenerator.__new__ = patched_class_stubs_generator_new