Skip to content
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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ Lazydocs makes it easy to generate beautiful markdown documentation for your Pyt

### Installation

> _Requirements: Python 3.6+._
> _Requirements: Python 3.9+._
```bash
pip install lazydocs
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
EMAIL = "[email protected]"
AUTHOR = "ML Tooling Team"
LICENSE = "MIT"
REQUIRES_PYTHON = ">=3.6"
REQUIRES_PYTHON = ">=3.9"
VERSION = None # Only set version if you like to overwrite the version in _about.py

PWD = os.path.abspath(os.path.dirname(__file__))
Expand Down
14 changes: 10 additions & 4 deletions src/lazydocs/generation.py
Original file line number Diff line number Diff line change
Expand Up @@ -624,6 +624,14 @@ def _lines_isvalid(lines: list, start_index: int, blockindent: int,
prev_blank_line_count += 1
return "".join(out)


def get_module(loader, module_name: str) -> Optional[Any]:
spec = loader.find_spec(module_name)
if spec is None:
raise ImportError(f"Cannot find module {module_name}")
Comment on lines +628 to +631
Copy link

Copilot AI Aug 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function may raise an AttributeError if spec.loader is None. Consider adding a null check for spec.loader before calling load_module.

Suggested change
def get_module(loader, module_name: str) -> Optional[Any]:
spec = loader.find_spec(module_name)
if spec is None:
raise ImportError(f"Cannot find module {module_name}")
raise ImportError(f"Cannot find module {module_name}")
if spec.loader is None:
raise ImportError(f"Cannot load module {module_name}: spec.loader is None")

Copilot uses AI. Check for mistakes.
return spec.loader.load_module(spec.name)
Copy link

Copilot AI Aug 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The load_module method is deprecated. Consider using importlib.util.module_from_spec and spec.loader.exec_module pattern that's already used in the main code paths.

Suggested change
return spec.loader.load_module(spec.name)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
return module

Copilot uses AI. Check for mistakes.


class MarkdownGenerator(object):
"""Markdown generator class."""

Expand Down Expand Up @@ -1250,8 +1258,7 @@ def generate_docs(
mod = importlib.util.module_from_spec(mod_spec)
mod_spec.loader.exec_module(mod)
except AttributeError:
# For older python version compatibility
mod = loader.find_module(module_name).load_module(module_name) # type: ignore
mod = get_module(loader, module_name)
module_md = generator.module2md(mod, is_mdx=is_mdx, include_toc=include_toc)
if not module_md:
# Module md is empty -> ignore module and all submodules
Expand Down Expand Up @@ -1334,8 +1341,7 @@ def generate_docs(
mod = importlib.util.module_from_spec(mod_spec)
mod_spec.loader.exec_module(mod)
except AttributeError:
# For older python version compatibility
mod = loader.find_module(module_name).load_module(module_name) # type: ignore
mod = get_module(loader, module_name)
module_md = generator.module2md(mod, is_mdx=is_mdx, include_toc=include_toc)

if not module_md:
Expand Down
31 changes: 30 additions & 1 deletion tests/test_generation.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import hashlib

from lazydocs import MarkdownGenerator
from lazydocs import MarkdownGenerator, generate_docs
from tempfile import TemporaryDirectory


def test_import2md() -> None:
Expand Down Expand Up @@ -35,3 +36,31 @@ def test_func2md() -> None:
# Remove whitespaces: fix changes between py version 3.6 3.7 in signature method
md_hash = hashlib.md5(markdown.replace(" ", "").encode("utf-8")).hexdigest()
assert md_hash == "797bad8c00ee6f189cb6f578eaec02c4"


def test_integration_generate_docs(capsys) -> None:
test_class = """
class TestClass:
\"\"\"just a test class\"\"\"
"""
with TemporaryDirectory() as d:
test_module_name = "test_module"
with open(f"{d}/{test_module_name}.py", "w") as f:
f.write(test_class)

overview_file_name = "DOCS.md"
overview_file = f"{d}/output/{overview_file_name}"
generate_docs(
paths=[d],
output_path=f"{d}/output/",
overview_file=overview_file_name
)

captured = capsys.readouterr()

with open(overview_file) as f:
result = f.read()

assert test_module_name in result
assert f"{test_module_name}.TestClass" in result
assert "Failed to generate docs for module" not in captured.out
Loading