To illustrate my point, I took the liberty and use your example from your 
post

==========================
On Thursday, November 20, 2025 at 4:24:37 AM UTC-6 Edward K. Ream wrote:

Leo issue #4472 <https://github.com/leo-editor/leo-editor/issues/4472>is a 
hobby project...This sentence [from gemini3] captures my initial vague idea 
exactly:


Your proposal essentially transforms Pylint from an *Inference Engine* 
(which is slow and guess-prone) into a *Logic Validator* (which is fast and 
deterministic).


All well and good,  but pylint's --prefer-stubs 
<https://pylint.pycqa.org/en/latest/user_guide/configuration/all-options.html#prefer-stubs>
 command-line 
option may be the best way to help pylint. gemini3 had no part in my 
thought process, and I have the feeling that gemini3 may have led me astray 
had I continued the original discussion. In a weird way, AIs seem to have 
blind spots.

My next step will be to adapt Leo's python importer so that it copies 
signatures for classes, methods and functions into a .pyi (stub) file. This 
will be a *much* easier project than my old make-stub-files 
<https://github.com/edreamleo/make-stub-files> script. It should take only 
a few days.
==============================
and put that into Windsurf (first my request, then the answer):
Take the file D:\WORKSPACE\leo-editor-devel\leo\core\leoImport.py and adapt 
it so that it copies signatures for classes, methods and functions into a 
.pyi (stub) file. This will be a much easier project than my old 
make-stub-files script.

ANSWER:

Good idea to integrate stub generation directly with Leo’s import 
machinery. I’ll first scan 
[leoImport.py](cci:7://file:///d:/WORKSPACE/leo-editor-devel/leo/core/leoImport.py:0:0-0:0)
 
to see its structure and existing import commands, then propose a concrete 
design (e.g. a new command that walks classes/functions and writes a `.pyi` 
alongside the source). After that, I can suggest or implement the code 
changes.

I’ll create a short TODO plan and read the file now.

Here’s a concrete plan and some design questions before I touch the code.

---

## High‑level idea

Add a **new command + helper(s)** in 
[leoImport.py](cci:7://file:///d:/WORKSPACE/leo-editor-devel/leo/core/leoImport.py:0:0-0:0)
 
that:

1. Takes a Python module path (or uses the current `@file` node’s file).
2. Uses `ast` to parse it.
3. Walks classes, methods, and functions.
4. Writes a corresponding `.pyi` file (next to the `.py` or into a chosen 
directory) containing only **signatures** and minimal bodies (`...`).

This stays strictly simpler than a general “make-stub-files” script: no 
cross‑module analysis, no type inference; just copy what’s already in 
annotations/defaults.

---

## Design questions for you

To avoid guessing, I’d like your preferences on these:

1. **Source of file to stub**
   - **Option A**: a command that uses the **current `@file` node**’s 
external file (`c.p`).
   - **Option B**: a command that prompts for one or more `.py` files 
(similar to other `import*` commands).
   - We can support both, but which should be the primary workflow?

2. **Where to write `.pyi`**
   - Same directory as the `.py` (`foo.py` → `foo.pyi`)?
   - Or some configurable “stubs directory” (setting) relative to the 
project?

3. **What to include**
   - Only top‑level `def` and `class` definitions?
   - For classes: include all methods, `@classmethod`, `@staticmethod`, 
properties?
   - Skip private names starting with `_` or include everything?

4. **Handling existing `.pyi` files**
   - Always **overwrite**?
   - Or refuse if exists (unless a config/argument says “force”)?

If you answer these, I can implement something that matches your intended 
workflow.

---

## Proposed concrete changes in 
[leoImport.py](cci:7://file:///d:/WORKSPACE/leo-editor-devel/leo/core/leoImport.py:0:0-0:0)

### 1. Add a small AST-based stub generator

Implement a pure helper (no Leo dependency) near 
[LeoImportCommands](cci:2://file:///d:/WORKSPACE/leo-editor-devel/leo/core/leoImport.py:137:0-1339:13)
 
or at the bottom:

- `generate_stub(source: str) -> str`  
  - Parse with `ast.parse`.
  - Collect:
    - `ast.FunctionDef` / `ast.AsyncFunctionDef` at module level.
    - `ast.ClassDef` and their methods.
  - Reconstruct signatures:
    - Use `ast.get_source_segment` if feasible, or format `args`, `returns` 
yourself.
    - Body is always `...` (ellipsis).
- `write_stub_for_file(path: str) -> str`  
  - Read file.
  - Call `generate_stub`.
  - Write to `path.replace('.py', '.pyi')` (or similar logic).
  - Return path of written stub.

This part will be straightforward and fully testable without GUI.

### 2. Add Leo-facing helpers in 
[LeoImportCommands](cci:2://file:///d:/WORKSPACE/leo-editor-devel/leo/core/leoImport.py:137:0-1339:13)

For example:

- `def makeStubForCurrentFile(self) -> None:`
  - Use `c.p` to find the underlying external `.py` (via `c.fullPath(p)` / 
`atFileCommands` if needed).
  - Call `write_stub_for_file`.
  - Report in the log (`g.es(f"created stub: {stub_path}")`).

- Optionally: `def makeStubsForFiles(self, paths: list[str]) -> None:`
  - Loop over a list of `.py` files (if you want a “batch” mode with a 
dialog).

### 3. Add commands (decorated functions) near the other `@g.command` 
definitions

Following the style you showed:

```python
@g.command('make-stub-for-current-file')
def make_stub_for_current_file(event: LeoKeyEvent) -> None:
    c = event.get('c')
    if c:
        c.importCommands.makeStubForCurrentFile()
```

Optionally another command taking multiple files via an open dialog, if you 
want parity with other import commands.

---

## Behavior details (default proposal)

Unless you say otherwise, I’d implement:

- **Source**:
  - Primary: current `@file` node’s underlying `.py`.
  - Fallback: if `c.p` is not an `@file` node with `.py`, show an error.

- **Destination**:
  - Same directory, same basename, `.pyi` extension.

- **Included items**:
  - All **top‑level** functions and classes.
  - For classes:
    - All methods (including async) and static/class methods.
    - Properties exposed via `@property`.
  - Don’t filter private names initially (keep it simple and predictable).
- **Docstrings**:
  - Omitted in `.pyi` (just signatures + `...`).
- **Existing stubs**:
  - **Overwrite** by default, with a log message.  
    We can add a config bool later, e.g. `@bool stub_generation_overwrite = 
True/False`.

---

## Next step

If you confirm your answers to the 4 design questions (or accept the 
defaults above), I’ll:

- Implement the stub generator helpers in 
[leoImport.py](cci:7://file:///d:/WORKSPACE/leo-editor-devel/leo/core/leoImport.py:0:0-0:0).
- Add a `LeoImportCommands.makeStubForCurrentFile` (and optional batch 
variant).
- Add a `@g.command` wrapper to invoke it from Leo.
- Keep comments/structure consistent with existing code and not touch 
unrelated parts.

Then I’ll summarize exactly what changed and how to use the new command.

END OF ANSWER

The technical details are over my head. But they will be meaningful to you. 
And I guess, with some additionl questions the days will shrink into 
hours...

Regards
Reinhard


On Tuesday, November 25, 2025 at 10:36:58 AM UTC+1 Edward K. Ream wrote:

> On Tuesday, November 25, 2025 at 3:10:02 AM UTC-6 rengel wrote:
>
> Thanks for sharing! Did you try to put the complete Leo codebase into an 
> AI-based IDE like Windsurf or Google Antigravity? Then you can get a 
> critique of the entire codebase or parts thereof or the complete 
> documentation within the IDE and get automatic improvements (if you wish 
> so) or suggestions for improvements. 
> I know that this isn't the Leonine way of programming, but it might be 
> worth a try. 
>
>
> No, I haven't tried that. Thanks for the suggestion.
>
> Edward
>

-- 
You received this message because you are subscribed to the Google Groups 
"leo-editor" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion visit 
https://groups.google.com/d/msgid/leo-editor/125440c4-dff2-497d-a748-a529e872244fn%40googlegroups.com.

Reply via email to