0

In my project, I have a class EnergyModel defined in energymodel.py. There is also generate_data class method imported from another source file:

#energy_model.py

from .energy_model_data_generation import generate_data
class EnergyModel(BaseEstimator):
    def __init__(...):
        EnergyModel.generate_data=generate_data

And there is another source file where the method is defined:

#energy_model_data_generation.py

def generate_data(self, ...):
     ...

I separated methods into different source files to keep the files sufficiently small - this is convenient for me. Now, I want to generate class documentation with Sphinx. My implementation.rst is the following:

Implementation
==============

.. _Energymodel_class:

Energymodel class
-----------------

.. autoclass:: neuralflow.EnergyModel
     :members:

Where neuralflow is the name of the package (imported in conf.py). This does not generate documentation for generate_data methods. I did not find how to include it, I only found how you can cross-refence methods, which is not what I want.

Edit: There is also __init__.py file in my directory with the source file, so it is a package. It looks like this:

from .energy_model import EnergyModel
# Also import other modules/packages that are not part of EnergyModel class

__all__ = ['EnergyModel', ...(other stuff that are not part of EnergyModel)]

Also I've added root directory to the path in conf.py file

Mikhail Genkin
  • 3,247
  • 4
  • 27
  • 47
  • Is your source code in a Python package? IOW, in a directory that contains a file named `__init__.py`? Also is your package in your PATH in your `conf.py`? – Steve Piercy Aug 29 '20 at 05:53
  • I don't see how this can work. The module with the `EnergyModel` class is imported, but the class is not instantiated. Sphinx is able to extract a docstring from `__init__()`, but `__init__()` is not actually executed. – mzjn Aug 29 '20 at 06:47
  • @StevePiercy, yes, and yes. I've made the edit to my post. – Mikhail Genkin Aug 29 '20 at 16:21
  • @mzjn So the only way to make it work would be to place all the methods into a single source file? Is it possible (like in cpp) to declare the members in the souce file, but to put the actual implementation in other files? – Mikhail Genkin Aug 29 '20 at 16:22

1 Answers1

1

The problem is that the generate_data() method is added dynamically to the class in the constructor. Because Sphinx nevers call the constructor (as @mzjn points out), this method is simply not part of the class when Sphinx is building the documentation. The solution is to define the method at the class level:

import energy_model_generation as emg

class EnergyModel(BaseEstimator):
    generate_data = emg.generate_data

As more of a code-review type comment, it doesn't really make sense to dynamically create methods in the constructor like this. Methods should only be defined once, but the constructor can be called many times—once for each instance of the class. It's easy to imagine this being the source of obscure bugs.

Kale Kundert
  • 1,144
  • 6
  • 18
  • thanks for the answer. I've just checked - it works, the autodoc does recognize methods introduced this way. Can you clarify on the code-review part? Are you saying that my way of introducing members is not good and I should use yours (even if I was not using autodoc at all)? So it is better to introduce methods at the class level rather than inside __init__? Thanks! – Mikhail Genkin Aug 30 '20 at 18:14