Skip to content

Plugin proposal : python-m - #778

Open
thomas-saigre wants to merge 1 commit into
ohmybash:masterfrom
thomas-saigre:master
Open

thomas-saigre wants to merge 1 commit into
ohmybash:masterfrom
thomas-saigre:master

Conversation

@thomas-saigre

Copy link
Copy Markdown
Contributor

The purpose of this plugin is to allow auto completion when running python module with python3 -m .... Cf the readme file for more details.

@thomas-saigre thomas-saigre changed the title Plugin proposam python-m Plugin proposal : python-m Sep 11, 2026
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

PR Summary by Qodo

Add python -m module path completion plugin

✨ Enhancement 📝 Documentation 🕐 10-20 Minutes

Grey Divider

AI Description

• Adds dotted local module completion after python or python3 -m.
• Preserves package traversal and excludes __pycache__ from suggestions.
• Documents plugin setup and completion examples.
Diagram

sequenceDiagram
    actor User
    participant OMB as Oh My Bash
    participant Bash
    participant Plugin as python-m plugin
    participant FS as Filesystem
    OMB->>Plugin: Source enabled plugin
    Plugin->>Bash: Register completer
    User->>Bash: Press Tab
    Bash->>Plugin: Send completion context
    Plugin->>FS: Find matching paths
    FS-->>Plugin: Return modules and directories
    Plugin-->>Bash: Return dotted candidates
    Bash-->>User: Display suggestions
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Python import discovery
  • ➕ Discovers installed modules and entries available through PYTHONPATH
  • ➕ Better matches Python import semantics, including namespace packages
  • ➖ Runs a Python subprocess during completion
  • ➖ May increase latency and complicate nested-package discovery
  • ➖ Import-based resolution can trigger package side effects
2. Delegate existing completion
  • ➕ Preserves richer pre-existing completion behavior outside the -m argument
  • ➕ Avoids replacing command completion installed by other packages
  • ➖ Requires capturing and safely invoking the previous completion specification
  • ➖ Behavior may vary across Bash and distribution-provided completion setups

Recommendation: The shell-only filesystem scan is appropriate for fast, dependency-free completion of local project modules. Consider delegating non--m requests to any existing Python completer; use Python import discovery only if installed and PYTHONPATH modules are explicitly in scope.

Files changed (2) +80 / -0

Enhancement (1) +45 / -0
python-m.plugin.shImplement dotted Python module completion +45/-0

Implement dotted Python module completion

• Registers Bash completers for 'python' and 'python3', translates dotted module input into filesystem paths, and returns matching Python files or directories. It suppresses '__pycache__', keeps package-only matches open for further traversal, and falls back to file completion outside '-m'.

plugins/python-m/python-m.plugin.sh

Documentation (1) +35 / -0
README.mdDocument python-m plugin setup and usage +35/-0

Document python-m plugin setup and usage

• Introduces installation instructions and examples showing dotted module completion within a local Python package tree.

plugins/python-m/README.md

@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (4) 📘 Rule violations (0) 📜 Skill insights (0)

Grey Divider


Action required

1. Installed modules never autocomplete 🐞 Bug ≡ Correctness
Description
_omb_python_m_complete derives one relative directory from the typed module name and enumerates
candidates exclusively with find "$dir". When an executable module comes from PYTHONPATH,
site-packages, or another interpreter search path rather than the current tree, it is absent from
the results.
Code

plugins/python-m/python-m.plugin.sh[29]

+        done < <(find "$dir" -mindepth 1 -maxdepth 1 \( -name "${base}*.py" -o -name "${base}*" -type d \) ! -name "__pycache__" -print0 2>/dev/null)
Evidence
The typed dotted name is converted directly to a relative path, and the sole candidate source is a
find against that path; there is no lookup of interpreter module search roots. The README
describes completion for Python module paths generally rather than limiting the feature to modules
under the current directory.

plugins/python-m/python-m.plugin.sh[8-29]
plugins/python-m/README.md[1-8]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The module completer searches only beneath the current working directory, so modules available through the interpreter's other search paths cannot be completed.

## Fix Focus Areas
- plugins/python-m/python-m.plugin.sh[8-32]

## Recommended Fix
Obtain the active interpreter's module search roots and enumerate matching modules or packages across all of them, preserving dotted nested-package completion and deduplicating candidates.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Spaces corrupt Python file completion 🐞 Bug ≡ Correctness
Description
The non-module branch assigns the unquoted output of compgen -f through command substitution,
which applies word splitting and pathname expansion before populating COMPREPLY. When a script or
directory name contains whitespace or glob characters, ordinary completion after python returns
split or expanded candidates instead of the actual path.
Code

plugins/python-m/python-m.plugin.sh[R40-42]

+    else
+        COMPREPLY=( $(compgen -f -- "$cur") )
+    fi
Evidence
Every invocation not immediately following -m reaches this branch, where COMPREPLY=( $(...) )
performs shell splitting on the generated filename candidates. The plugin installs this handler for
both supported Python commands, so it replaces their ordinary file completion path.

plugins/python-m/python-m.plugin.sh[40-45]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Ordinary Python file completion word-splits and expands the output from `compgen`, corrupting paths containing spaces or glob characters.

## Fix Focus Areas
- plugins/python-m/python-m.plugin.sh[40-42]

## Recommended Fix
Populate `COMPREPLY` without an unquoted command substitution, such as by reading `compgen` output line-by-line into the array, and enable filename-aware completion quoting where appropriate.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

3. Script arguments trigger module lookup 🐞 Bug ≡ Correctness
Description
_omb_python_m_complete enters module mode whenever the immediately preceding word equals -m,
without checking whether Python has already selected a script or command to execute. For `python
script.py -m <TAB>, where -m` belongs to the script's arguments, the plugin searches for Python
modules instead of completing the script's argument.
Code

plugins/python-m/python-m.plugin.sh[R6-9]

+    prev="${COMP_WORDS[COMP_CWORD-1]}"
+
+    if [[ "$prev" == "-m" ]]; then
+        path="${cur//.//}"
Evidence
The function records only the immediately previous word and uses equality with -m as its complete
mode decision. It performs no scan for an earlier script, -c, -m, or option terminator before
starting module-path discovery.

plugins/python-m/python-m.plugin.sh[5-12]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The completer treats every preceding `-m` as a Python interpreter option, including occurrences passed to an already selected script.

## Fix Focus Areas
- plugins/python-m/python-m.plugin.sh[5-12]

## Recommended Fix
Inspect the command words before the current position and enter module completion only when `-m` occurs in the interpreter option prefix, before any script, command, module, or option terminator selects what Python will execute.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


4. Django users lose module completion 🐞 Bug ≡ Correctness
Description
The plugin registers an exclusive completion function for python, while the existing Django
completion independently registers its own exclusive function for the same command. Oh My Bash loads
plugins before configured completions, so enabling both causes the later Django registration to
replace this plugin and makes its python -m behavior unavailable.
Code

plugins/python-m/python-m.plugin.sh[R44-45]

+complete -F _omb_python_m_complete python3
+complete -F _omb_python_m_complete python
Evidence
The new plugin registers _omb_python_m_complete directly for python; the Django completion later
registers _omb_completion_django_python for Python interpreters. The central loader sources
plugins on lines 130-131 and completions only afterward on lines 136-137, proving the Django
registration wins when both are configured.

plugins/python-m/python-m.plugin.sh[44-45]
oh-my-bash.sh[130-137]
completions/django.completion.sh[44-72]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The new exclusive Python completion registration is overwritten by configured completion modules such as Django, disabling module completion for users who enable both features.

## Fix Focus Areas
- plugins/python-m/python-m.plugin.sh[44-45]
- oh-my-bash.sh[130-137]
- completions/django.completion.sh[44-72]

## Recommended Fix
Integrate module-name completion without competing exclusive registrations, preserving or delegating to the existing Python completion handler for all other contexts and ensuring registration occurs after configured completion modules are loaded.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Context sources
Review mode: ⚖️ Balanced: This adds new shell completion runtime logic with filesystem traversal and Bash completion behavior, creating meaningful localized correctness risks beyond a trivial change.

Grey Divider

Tip of the day
💡 Did you know, you can switch off images and animations for a plain-text comment

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo


matches+=("$entry")
[[ "$is_dir" == 1 ]] && dir_matches+=("$entry")
done < <(find "$dir" -mindepth 1 -maxdepth 1 \( -name "${base}*.py" -o -name "${base}*" -type d \) ! -name "__pycache__" -print0 2>/dev/null)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

1. Installed modules never autocomplete 🐞 Bug ≡ Correctness

_omb_python_m_complete derives one relative directory from the typed module name and enumerates
candidates exclusively with find "$dir". When an executable module comes from PYTHONPATH,
site-packages, or another interpreter search path rather than the current tree, it is absent from
the results.
Agent Prompt
## Issue description
The module completer searches only beneath the current working directory, so modules available through the interpreter's other search paths cannot be completed.

## Fix Focus Areas
- plugins/python-m/python-m.plugin.sh[8-32]

## Recommended Fix
Obtain the active interpreter's module search roots and enumerate matching modules or packages across all of them, preserving dotted nested-package completion and deduplicating candidates.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +40 to +42
else
COMPREPLY=( $(compgen -f -- "$cur") )
fi

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

2. Spaces corrupt python file completion 🐞 Bug ≡ Correctness

The non-module branch assigns the unquoted output of compgen -f through command substitution,
which applies word splitting and pathname expansion before populating COMPREPLY. When a script or
directory name contains whitespace or glob characters, ordinary completion after python returns
split or expanded candidates instead of the actual path.
Agent Prompt
## Issue description
Ordinary Python file completion word-splits and expands the output from `compgen`, corrupting paths containing spaces or glob characters.

## Fix Focus Areas
- plugins/python-m/python-m.plugin.sh[40-42]

## Recommended Fix
Populate `COMPREPLY` without an unquoted command substitution, such as by reading `compgen` output line-by-line into the array, and enable filename-aware completion quoting where appropriate.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +6 to +9
prev="${COMP_WORDS[COMP_CWORD-1]}"

if [[ "$prev" == "-m" ]]; then
path="${cur//.//}"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Remediation recommended

3. Script arguments trigger module lookup 🐞 Bug ≡ Correctness

_omb_python_m_complete enters module mode whenever the immediately preceding word equals -m,
without checking whether Python has already selected a script or command to execute. For `python
script.py -m <TAB>, where -m` belongs to the script's arguments, the plugin searches for Python
modules instead of completing the script's argument.
Agent Prompt
## Issue description
The completer treats every preceding `-m` as a Python interpreter option, including occurrences passed to an already selected script.

## Fix Focus Areas
- plugins/python-m/python-m.plugin.sh[5-12]

## Recommended Fix
Inspect the command words before the current position and enter module completion only when `-m` occurs in the interpreter option prefix, before any script, command, module, or option terminator selects what Python will execute.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +44 to +45
complete -F _omb_python_m_complete python3
complete -F _omb_python_m_complete python

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Remediation recommended

4. Django users lose module completion 🐞 Bug ≡ Correctness

The plugin registers an exclusive completion function for python, while the existing Django
completion independently registers its own exclusive function for the same command. Oh My Bash loads
plugins before configured completions, so enabling both causes the later Django registration to
replace this plugin and makes its python -m behavior unavailable.
Agent Prompt
## Issue description
The new exclusive Python completion registration is overwritten by configured completion modules such as Django, disabling module completion for users who enable both features.

## Fix Focus Areas
- plugins/python-m/python-m.plugin.sh[44-45]
- oh-my-bash.sh[130-137]
- completions/django.completion.sh[44-72]

## Recommended Fix
Integrate module-name completion without competing exclusive registrations, preserving or delegating to the existing Python completion handler for all other contexts and ensuring registration occurs after configured completion modules are loaded.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

@akinomyoga

Copy link
Copy Markdown
Contributor

What is the difference from completions-core/python.bash:87-90@scop/bash-completion? We should probably include it in scop/bash-completion.

@thomas-saigre

Copy link
Copy Markdown
Contributor Author

What is the difference from completions-core/python.bash:87-90@scop/bash-completion? We should probably include it in scop/bash-completion.

I never heard of bash-completion, but my proposition seems indeed to do what it does, maybe in a less consistent way, as I manually check for sub-packages, and do not use pkgutil (cf source code)

@akinomyoga

Copy link
Copy Markdown
Contributor

I checked the behavior of bash-completion's package name generation, but it seems extremely slow particularly when . is included in the completion target. At least, there is room to improve.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants