Skip to content

add ipython-profile support#266

Open
woutervh wants to merge 4 commits intogotcha:masterfrom
woutervh:master
Open

add ipython-profile support#266
woutervh wants to merge 4 commits intogotcha:masterfrom
woutervh:master

Conversation

@woutervh
Copy link
Contributor

@woutervh woutervh commented Mar 13, 2023

  • add ipython-profile support

Summary by CodeRabbit

  • New Features

    • Users can now run ipdb with non-default IPython profiles by setting the IPDB_IPYTHON_PROFILE environment variable or configuring it via configuration file, with fallback to default profile if the profile directory doesn't exist.
  • Documentation

    • Added guidance on configuring custom IPython profiles for ipdb.
  • Tests

    • Added test coverage for profile configuration functionality.

Wouter Vanden Hove and others added 3 commits March 12, 2023 02:56
* add ipython-profile support

* add tests to fetch ipytohn_profiler from config

---------

Co-authored-by: Wouter Vanden Hove <wvandenhove@ekglobal.co>
@codecov-commenter
Copy link

codecov-commenter commented Mar 13, 2023

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

❌ Patch coverage is 89.28571% with 6 lines in your changes missing coverage. Please review.
✅ Project coverage is 81.02%. Comparing base (3326c07) to head (9726ed8).
⚠️ Report is 3 commits behind head on master.

Files with missing lines Patch % Lines
ipdb/__main__.py 70.00% 6 Missing ⚠️
❗ Your organization needs to install the Codecov GitHub app to enable full functionality.
Additional details and impacted files
@@            Coverage Diff             @@
##           master     #266      +/-   ##
==========================================
- Coverage   81.64%   81.02%   -0.62%     
==========================================
  Files           7        7              
  Lines         512      564      +52     
==========================================
+ Hits          418      457      +39     
- Misses         94      107      +13     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@gotcha
Copy link
Owner

gotcha commented Mar 22, 2023

Thanks for this PR.
I am sure it will be appreciated.
See my first comments. I'll dig deeper.

* add ipython-profile support

* add tests to fetch ipytohn_profiler from config

* cleanup profile-tests

---------

Co-authored-by: Wouter Vanden Hove <wvandenhove@ekglobal.co>
@gotcha
Copy link
Owner

gotcha commented Feb 27, 2026

@coderabbitai review

@coderabbitai
Copy link

coderabbitai bot commented Feb 27, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai
Copy link

coderabbitai bot commented Feb 27, 2026

📝 Walkthrough

Walkthrough

This pull request adds support for non-default IPython profiles in ipdb. Users can specify a profile via the IPDB_IPYTHON_PROFILE environment variable or configuration file. The implementation includes profile directory resolution logic, documentation, and comprehensive test coverage.

Changes

Cohort / File(s) Summary
Documentation & Changelog
HISTORY.txt, README.rst
Added changelog entry for version 0.13.14 and two documentation sections explaining how to configure non-default IPython profiles via environment variable and pyproject.toml.
Core Implementation
ipdb/__main__.py
Updated _get_debugger_cls() to accept ipython_profile parameter and resolve profile directory via ProfileDir.find_profile_dir_by_name(). Modified _init_pdb() to accept optional ipython_profile parameter and read profile from environment or config. Added new public function get_ipython_profile_from_config() to retrieve profile setting from config file.
Test Coverage
tests/test_config.py
Added comprehensive test suite for get_ipython_profile_from_config() covering scenarios with missing, default, and non-default profiles; includes tests for environment variable and configuration file handling.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant ipdb as ipdb/__main__.py
    participant Config as Config/Env
    participant ProfileDir as IPython ProfileDir
    participant IPythonApp as TerminalIPythonApp

    User->>ipdb: _init_pdb(ipython_profile=None)
    ipdb->>Config: get_ipython_profile_from_config()
    Config-->>ipdb: profile_name ("default" or configured)
    ipdb->>ipdb: _get_debugger_cls(ipython_profile)
    ipdb->>ProfileDir: find_profile_dir_by_name(profile_name)
    alt Profile found
        ProfileDir-->>ipdb: profile_dir
    else Profile not found
        ProfileDir-->>ipdb: ProfileDirError → fallback to "default"
    end
    ipdb->>IPythonApp: TerminalIPythonApp(profile_dir=resolved_dir)
    IPythonApp-->>ipdb: app instance
    ipdb-->>User: debugger initialized with selected profile
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 Hop, skip, and a bound of profile delight!
No more "default" constraints holding tight,
Configuration magic, environment flair,
IPython profiles everywhere!
The debugger hops forth, refined and bright!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'add ipython-profile support' directly describes the main change: introducing support for configuring and using non-default IPython profiles in ipdb through environment variables and config files.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Nitpick comments (1)
tests/test_config.py (1)

427-470: Use unittest assertions instead of bare assert.

Bare asserts can be skipped under optimized execution (python -O) and are inconsistent with the extensive use of self.assertEqual() and other unittest assertion methods throughout this test file.

Proposed fix
         with ModifiedEnvironment(IPDB_CONFIG=None, HOME=self.tmpd):
             profile_name = get_ipython_profile_from_config()
-            assert profile_name == "default"
+            self.assertEqual("default", profile_name)
@@
         with ModifiedEnvironment(IPDB_CONFIG=None, HOME=self.tmpd):
             profile_name = get_ipython_profile_from_config()
-            assert profile_name == "default"
+            self.assertEqual("default", profile_name)
@@
         with ModifiedEnvironment(IPDB_CONFIG=None, HOME=self.tmpd):
             profile_name = get_ipython_profile_from_config()
-            assert profile_name == "foo"
+            self.assertEqual("foo", profile_name)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/test_config.py` around lines 427 - 470, Replace bare Python asserts in
the tests with unittest assertion methods: in test_default_profile_setup and
test_non_default_profile_setup (and the nearby test that calls
get_ipython_profile_from_config inside ModifiedEnvironment), change lines like
assert profile_name == "default" and assert profile_name == "foo" to
self.assertEqual(profile_name, "default") and self.assertEqual(profile_name,
"foo") respectively so the tests use the TestCase assertions consistently
(functions referenced: get_ipython_profile_from_config, ModifiedEnvironment,
write_lines_to_file).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@ipdb/__main__.py`:
- Around line 65-72: The _init_pdb function currently uses a mutable default
commands=[] and eagerly evaluates get_ipython_profile_from_config() inside
os.getenv; change the signature to def _init_pdb(context=None,
ipython_profile=None, commands=None): set commands = [] inside the function if
commands is None, and avoid passing get_ipython_profile_from_config() directly
to os.getenv by first checking os.getenv("IPDB_IPYTHON_PROFILE", None) and only
calling get_ipython_profile_from_config() when that env var is not set (do the
same pattern for context: check os.getenv("IPDB_CONTEXT_SIZE", None) and call
get_context_from_config() only if env is None) so config parsing remains lazy
and the default list is not shared across calls, referencing _init_pdb,
commands, ipython_profile, get_ipython_profile_from_config,
get_context_from_config, and os.getenv.

In `@README.rst`:
- Around line 127-132: The README has a typo in the environment variable name:
replace the incorrect string "IPDB_IPYTON_PROFILE" with the correct
"IPDB_IPYTHON_PROFILE" in the code block and any related mentions so the docs
match runtime behavior (search for the literal IPDB_IPYTON_PROFILE in the
README.rst and update it accordingly).
- Line 140: Fix the malformed inline-literal in README.rst by removing the extra
backtick after ``profile_ipdb``` and inserting a space before "in your
``IPYTHON_HOME``", so the sentence reads with a single inline-literal
``profile_ipdb`` and a space: "This should correspond with a profile-directory
``profile_ipdb`` in your ``IPYTHON_HOME``." Reference the literal text
"profile_ipdb" and "IPYTHON_HOME" to locate the change.

In `@tests/test_config.py`:
- Around line 141-156: Remove the duplicated test method definition for
test_noenv_nodef_nosetup_pyproject so only a single test function remains;
locate both definitions of test_noenv_nodef_nosetup_pyproject in the
tests/test_config.py file, decide which body to keep (or merge assertions from
both if they differ), delete the redundant def, and ensure imports and
references such as get_config, ModifiedEnvironment, env_filename,
default_filename, and setup_filename remain correct and the test suite still
passes.

---

Nitpick comments:
In `@tests/test_config.py`:
- Around line 427-470: Replace bare Python asserts in the tests with unittest
assertion methods: in test_default_profile_setup and
test_non_default_profile_setup (and the nearby test that calls
get_ipython_profile_from_config inside ModifiedEnvironment), change lines like
assert profile_name == "default" and assert profile_name == "foo" to
self.assertEqual(profile_name, "default") and self.assertEqual(profile_name,
"foo") respectively so the tests use the TestCase assertions consistently
(functions referenced: get_ipython_profile_from_config, ModifiedEnvironment,
write_lines_to_file).

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3326c07 and 9726ed8.

📒 Files selected for processing (4)
  • HISTORY.txt
  • README.rst
  • ipdb/__main__.py
  • tests/test_config.py

Comment on lines +65 to +72
def _init_pdb(context=None, ipython_profile=None, commands=[]):
if context is None:
context = os.getenv("IPDB_CONTEXT_SIZE", get_context_from_config())
debugger_cls = _get_debugger_cls()

if ipython_profile is None:
ipython_profile = os.getenv(
"IPDB_IPYTHON_PROFILE", get_ipython_profile_from_config()
)
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# First, verify the patterns exist in the _init_pdb function
echo "=== Checking for mutable default argument pattern ==="
rg -n 'def _init_pdb\(context=None, ipython_profile=None, commands=\[\]\):' ipdb/__main__.py

echo "=== Checking for eager evaluation pattern ==="
rg -n 'IPDB_IPYTHON_PROFILE", get_ipython_profile_from_config\(\)' ipdb/__main__.py

echo "=== Reading the actual function to see context ==="
rg -n -A 20 'def _init_pdb' ipdb/__main__.py | head -40

Repository: gotcha/ipdb

Length of output: 1036


Fix mutable default argument and eager config evaluation in _init_pdb.

commands=[] as a default argument is a mutable default anti-pattern that causes the list to be shared across all function calls. Additionally, get_ipython_profile_from_config() is evaluated immediately on every call to os.getenv(), even when IPDB_IPYTHON_PROFILE is set, which defeats the lazy evaluation intent and can trigger unnecessary config parsing.

Proposed fix
-def _init_pdb(context=None, ipython_profile=None, commands=[]):
+def _init_pdb(context=None, ipython_profile=None, commands=None):
+    if commands is None:
+        commands = []
     if context is None:
         context = os.getenv("IPDB_CONTEXT_SIZE", get_context_from_config())

     if ipython_profile is None:
-        ipython_profile = os.getenv(
-            "IPDB_IPYTHON_PROFILE", get_ipython_profile_from_config()
-        )
+        ipython_profile = os.getenv("IPDB_IPYTHON_PROFILE")
+        if ipython_profile is None:
+            ipython_profile = get_ipython_profile_from_config()
🧰 Tools
🪛 Ruff (0.15.2)

[warning] 65-65: Do not use mutable data structures for argument defaults

Replace with None; initialize within function

(B006)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ipdb/__main__.py` around lines 65 - 72, The _init_pdb function currently uses
a mutable default commands=[] and eagerly evaluates
get_ipython_profile_from_config() inside os.getenv; change the signature to def
_init_pdb(context=None, ipython_profile=None, commands=None): set commands = []
inside the function if commands is None, and avoid passing
get_ipython_profile_from_config() directly to os.getenv by first checking
os.getenv("IPDB_IPYTHON_PROFILE", None) and only calling
get_ipython_profile_from_config() when that env var is not set (do the same
pattern for context: check os.getenv("IPDB_CONTEXT_SIZE", None) and call
get_context_from_config() only if env is None) so config parsing remains lazy
and the default list is not shared across calls, referencing _init_pdb,
commands, ipython_profile, get_ipython_profile_from_config,
get_context_from_config, and os.getenv.

Comment on lines +127 to +132
You can set a non-default profile by setting the environment variable ``IPDB_IPYTON_PROFILE``:

.. code-block:: bash

export IPDB_IPYTON_PROFILE="ipdb"

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Fix env-var name typo in docs (IPDB_IPYTHON_PROFILE).

IPDB_IPYTON_PROFILE (missing H) will not match runtime behavior, so users following docs won’t activate the feature.

Proposed fix
-You can set a non-default profile by setting the environment variable ``IPDB_IPYTON_PROFILE``:
+You can set a non-default profile by setting the environment variable ``IPDB_IPYTHON_PROFILE``:

-        export IPDB_IPYTON_PROFILE="ipdb"
+        export IPDB_IPYTHON_PROFILE="ipdb"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
You can set a non-default profile by setting the environment variable ``IPDB_IPYTON_PROFILE``:
.. code-block:: bash
export IPDB_IPYTON_PROFILE="ipdb"
You can set a non-default profile by setting the environment variable ``IPDB_IPYTHON_PROFILE``:
.. code-block:: bash
export IPDB_IPYTHON_PROFILE="ipdb"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@README.rst` around lines 127 - 132, The README has a typo in the environment
variable name: replace the incorrect string "IPDB_IPYTON_PROFILE" with the
correct "IPDB_IPYTHON_PROFILE" in the code block and any related mentions so the
docs match runtime behavior (search for the literal IPDB_IPYTON_PROFILE in the
README.rst and update it accordingly).

[tool.ipdb]
ipython_profile = "ipdb"

This should correspond with a profile-directory ``profile_ipdb```in your ``IPYTHON_HOME``.
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Fix malformed inline-literal markup.

The profile directory literal has an extra backtick and missing space.

Proposed fix
-This should correspond with a profile-directory ``profile_ipdb```in your ``IPYTHON_HOME``.
+This should correspond with a profile-directory ``profile_ipdb`` in your ``IPYTHON_HOME``.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@README.rst` at line 140, Fix the malformed inline-literal in README.rst by
removing the extra backtick after ``profile_ipdb``` and inserting a space before
"in your ``IPYTHON_HOME``", so the sentence reads with a single inline-literal
``profile_ipdb`` and a space: "This should correspond with a profile-directory
``profile_ipdb`` in your ``IPYTHON_HOME``." Reference the literal text
"profile_ipdb" and "IPYTHON_HOME" to locate the change.

Comment on lines +141 to +156
def test_noenv_nodef_nosetup_pyproject(self):
"""
Setup: $IPDB_CONFIG unset, $HOME/.ipdb does not exist,
setup.cfg does not exist, pyproject.toml exists
Result: load pyproject.toml
"""
os.unlink(self.env_filename)
os.unlink(self.default_filename)
os.remove(self.setup_filename)
with ModifiedEnvironment(IPDB_CONFIG=None, HOME=self.tmpd):
cfg = get_config()
# breakpoint()
self.assertEqual(["ipdb"], cfg.sections())
self.assertEqual(self.pyproject_context, cfg.getint("ipdb", "context"))
self.assertRaises(configparser.NoOptionError, cfg.get, "ipdb", "version")

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify duplicate method definitions.
rg -n 'def test_noenv_nodef_nosetup_pyproject\(' tests/test_config.py

Repository: gotcha/ipdb

Length of output: 162


Remove duplicated test method definition.

test_noenv_nodef_nosetup_pyproject is defined twice (Lines 126 and 141); the second definition overrides the first and silently drops one test body.

Proposed fix
-    def test_noenv_nodef_nosetup_pyproject(self):
-        """
-        Setup: $IPDB_CONFIG unset, $HOME/.ipdb does not exist,
-            setup.cfg does not exist, pyproject.toml exists
-        Result: load pyproject.toml
-        """
-        os.unlink(self.env_filename)
-        os.unlink(self.default_filename)
-        os.remove(self.setup_filename)
-        with ModifiedEnvironment(IPDB_CONFIG=None, HOME=self.tmpd):
-            cfg = get_config()
-            # breakpoint()
-            self.assertEqual(["ipdb"], cfg.sections())
-            self.assertEqual(self.pyproject_context, cfg.getint("ipdb", "context"))
-            self.assertRaises(configparser.NoOptionError, cfg.get, "ipdb", "version")
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
def test_noenv_nodef_nosetup_pyproject(self):
"""
Setup: $IPDB_CONFIG unset, $HOME/.ipdb does not exist,
setup.cfg does not exist, pyproject.toml exists
Result: load pyproject.toml
"""
os.unlink(self.env_filename)
os.unlink(self.default_filename)
os.remove(self.setup_filename)
with ModifiedEnvironment(IPDB_CONFIG=None, HOME=self.tmpd):
cfg = get_config()
# breakpoint()
self.assertEqual(["ipdb"], cfg.sections())
self.assertEqual(self.pyproject_context, cfg.getint("ipdb", "context"))
self.assertRaises(configparser.NoOptionError, cfg.get, "ipdb", "version")
🧰 Tools
🪛 Ruff (0.15.2)

[error] 141-141: Redefinition of unused test_noenv_nodef_nosetup_pyproject from line 126: test_noenv_nodef_nosetup_pyproject redefined here

(F811)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/test_config.py` around lines 141 - 156, Remove the duplicated test
method definition for test_noenv_nodef_nosetup_pyproject so only a single test
function remains; locate both definitions of test_noenv_nodef_nosetup_pyproject
in the tests/test_config.py file, decide which body to keep (or merge assertions
from both if they differ), delete the redundant def, and ensure imports and
references such as get_config, ModifiedEnvironment, env_filename,
default_filename, and setup_filename remain correct and the test suite still
passes.

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.

4 participants