From 6ceeb3241e8e4a35cf047038963002da4455b7b3 Mon Sep 17 00:00:00 2001 From: "Michael.Makukha" Date: Fri, 9 May 2025 11:28:09 +0300 Subject: [PATCH 1/4] Add tests, docs, and implementation for #133307 --- Doc/library/pdb.rst | 24 +++++++++++++++----- Lib/pdb.py | 52 +++++++++++++++++++++++++++----------------- Lib/test/test_pdb.py | 35 +++++++++++++++++++++++++++++ 3 files changed, 85 insertions(+), 26 deletions(-) diff --git a/Doc/library/pdb.rst b/Doc/library/pdb.rst index a0304edddf6478..3c1370119cc97e 100644 --- a/Doc/library/pdb.rst +++ b/Doc/library/pdb.rst @@ -378,12 +378,20 @@ There are four preset *convenience variables*: pair: .pdbrc; file triple: debugger; configuration; file -If a file :file:`.pdbrc` exists in the user's home directory or in the current -directory, it is read with ``'utf-8'`` encoding and executed as if it had been -typed at the debugger prompt, with the exception that empty lines and lines -starting with ``#`` are ignored. This is particularly useful for aliases. If both -files exist, the one in the home directory is read first and aliases defined there -can be overridden by the local file. +If a file :file:`.pdbrc` exists in any of the supported locations, it is read +with ``'utf-8'`` encoding and executed as if it had been typed at the debugger +prompt, with the exception that empty lines and lines starting with ``#`` are +ignored. This is particularly useful for aliases. Supported locations for +:file:`.pdbrc` file are + +1. ``$XDG_CONFIG_HOME/pdb`` (defaults to ``~/.config/pdb``, if environment + variable :envvar:`XDG_CONFIG_HOME` is not set) +2. User's home directory +3. Current working directory + +If :file:`.pdbrc` files exist in multiple locations, they are processed in +order, so that ``$XDG_CONFIG_HOME/pdb/.pdbrc`` is loaded first, and extended +by :file:`.pdbrc` files in user's home and current directory. .. versionchanged:: 3.2 :file:`.pdbrc` can now contain commands that continue debugging, such as @@ -394,6 +402,10 @@ can be overridden by the local file. :file:`.pdbrc` is now read with ``'utf-8'`` encoding. Previously, it was read with the system locale encoding. +.. versionadded:: 3.15 + :file:`.pdbrc` is now searched in ``$XDG_CONFIG_HOME/pdb`` directory first. + Previously, this location was ignored. + .. pdbcommand:: h(elp) [command] diff --git a/Lib/pdb.py b/Lib/pdb.py index f89d104fcddb9a..d85ed6bad7f0a2 100644 --- a/Lib/pdb.py +++ b/Lib/pdb.py @@ -46,12 +46,24 @@ input is split at the first ';;', even if it is in the middle of a quoted string. -If a file ".pdbrc" exists in your home directory or in the current -directory, it is read in and executed as if it had been typed at the -debugger prompt. This is particularly useful for aliases. If both -files exist, the one in the home directory is read first and aliases -defined there can be overridden by the local file. This behavior can be -disabled by passing the "readrc=False" argument to the Pdb constructor. +If a '.pdbrc' exists in any of the supported locations, it is read with 'utf-8' +encoding and executed as if it had been typed at the debugger prompt, with the +exception that empty lines and lines starting with '#' are ignored. This is +particularly useful for aliases. + +This behavior can be disabled by passing the 'readrc=False' argument to the Pdb +constructor. + +Supported locations for '.pdbrc' file are + +1. '$XDG_CONFIG_HOME/pdb' (defaults to '~/.config/pdb', if environment variable + $XDG_CONFIG_HOME is not set) +2. User's home directory +3. Current working directory + +If '.pdbrc' files exist in multiple locations, they are processed in order, so +that '$XDG_CONFIG_HOME/pdb/.pdbrc' is loaded first, and extended by '.pdbrc' +files in user's home and current directory. Aside from aliases, the debugger is not directly programmable; but it is implemented as a class from which you can derive your own debugger @@ -98,7 +110,7 @@ import _colorize import _pyrepl.utils -from contextlib import ExitStack, closing, contextmanager +from contextlib import ExitStack, closing, contextmanager, suppress from rlcompleter import Completer from types import CodeType from warnings import deprecated @@ -369,19 +381,19 @@ def __init__(self, completekey='tab', stdin=None, stdout=None, skip=None, # c.a or c['a'], it won't be recognized as a c(ontinue) command self.identchars = cmd.Cmd.identchars + '=.[](),"\'+-*/%@&|<>~^' - # Read ~/.pdbrc and ./.pdbrc + # Read $XDG_CONFIG_HOME/pdb/.pdbrc, ~/.pdbrc, and ./.pdbrc self.rcLines = [] if readrc: - try: - with open(os.path.expanduser('~/.pdbrc'), encoding='utf-8') as rcFile: - self.rcLines.extend(rcFile) - except OSError: - pass - try: - with open(".pdbrc", encoding='utf-8') as rcFile: - self.rcLines.extend(rcFile) - except OSError: - pass + # $XDG_CONFIG_HOME defaults to $HOME/.config + config_home = os.environ.get('XDG_CONFIG_HOME', '~/.config') + for rc_path in ( + os.path.expanduser(os.path.join(config_home, 'pdb', '.pdbrc')), + os.path.expanduser('~/.pdbrc'), + '.pdbrc', + ): + with suppress(OSError): + with open(rc_path, encoding='utf-8') as rcFile: + self.rcLines.extend(rcFile) self.commands = {} # associates a command list to breakpoint numbers self.commands_defining = False # True while in the process of defining @@ -3492,8 +3504,8 @@ def help(): an executable module or package to debug can be specified using the -m switch. -Initial commands are read from .pdbrc files in your home directory -and in the current directory, if they exist. Commands supplied with +Initial commands are read from .pdbrc files in "$XDG_CONFIG_HOME/pdb", your home +directory, and in the current directory, if they exist. Commands supplied with -c are executed after commands from .pdbrc files. To let the script run until an exception occurs, use "-c continue". diff --git a/Lib/test/test_pdb.py b/Lib/test/test_pdb.py index 68c2b508fa64dc..404ab4abf28598 100644 --- a/Lib/test/test_pdb.py +++ b/Lib/test/test_pdb.py @@ -3935,6 +3935,41 @@ def test_readrc_homedir(self): f.write("invalid") self.assertEqual(pdb.Pdb().rcLines[0], "invalid") + def test_pdbrc_xdg_config_home(self): + with ( + os_helper.temp_dir() as temp_dir, + os_helper.change_cwd(temp_dir), + os_helper.EnvironmentVarGuard() as env, + patch( + 'os.path.expanduser', + lambda p: p.replace('~', os.environ.get('HOME', '~')), + ), + ): + for rc_dir, rcLines in ( + (os.path.join(temp_dir, 'xdg', '.config', 'pdb'), '#xdgconf'), + (os.path.join(temp_dir, 'home', '.config', 'pdb'), '#homeconf'), + (os.path.join(temp_dir, 'home'), '#home'), + (temp_dir, '#cwd'), + ): + if not os.path.exists(rc_dir): + os.makedirs(rc_dir) + with open(os.path.join(rc_dir, '.pdbrc'), 'w') as f: + f.write(rcLines) + + env.unset('HOME') + env.unset('XDG_CONFIG_HOME') + + # when both XDG_CONFIG_HOME and $HOME are unset, ./.pdbrc is still loaded + self.assertListEqual(pdb.Pdb().rcLines, ['#cwd']) + # # when XDG_CONFIG_HOME is unset, it defaults to $HOME/.config + env.set('HOME', os.path.join(temp_dir, 'home')) + self.assertListEqual(pdb.Pdb().rcLines, ['#homeconf', '#home', '#cwd']) + # when XDG_CONFIG_HOME is set, .pdbrc is loaded from there + env.set('XDG_CONFIG_HOME', os.path.join(temp_dir, 'xdg', '.config')) + self.assertListEqual(pdb.Pdb().rcLines, ['#xdgconf', '#home', '#cwd']) + # when readrc=False, .pdbrc is not loaded from any location + self.assertListEqual(pdb.Pdb(readrc=False).rcLines, []) + def test_header(self): stdout = StringIO() header = 'Nobody expects... blah, blah, blah' From c7838f5ef5191a2b1c8e8105a4128b2cc893cdb9 Mon Sep 17 00:00:00 2001 From: "Michael.Makukha" Date: Fri, 9 May 2025 11:32:32 +0300 Subject: [PATCH 2/4] Fix docs bug --- Doc/library/pdb.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/pdb.rst b/Doc/library/pdb.rst index 3c1370119cc97e..81f39a11feec67 100644 --- a/Doc/library/pdb.rst +++ b/Doc/library/pdb.rst @@ -402,7 +402,7 @@ by :file:`.pdbrc` files in user's home and current directory. :file:`.pdbrc` is now read with ``'utf-8'`` encoding. Previously, it was read with the system locale encoding. -.. versionadded:: 3.15 +.. versionadded:: next :file:`.pdbrc` is now searched in ``$XDG_CONFIG_HOME/pdb`` directory first. Previously, this location was ignored. From 27b0aab62b34f006a840cf5b33aa4b089d086848 Mon Sep 17 00:00:00 2001 From: "Michael.Makukha" Date: Fri, 9 May 2025 11:51:20 +0300 Subject: [PATCH 3/4] Add NEWS entry --- .../next/Library/2025-05-09-11-50-53.gh-issue-133307.YBSk6r.rst | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2025-05-09-11-50-53.gh-issue-133307.YBSk6r.rst diff --git a/Misc/NEWS.d/next/Library/2025-05-09-11-50-53.gh-issue-133307.YBSk6r.rst b/Misc/NEWS.d/next/Library/2025-05-09-11-50-53.gh-issue-133307.YBSk6r.rst new file mode 100644 index 00000000000000..560985a561fdd5 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-05-09-11-50-53.gh-issue-133307.YBSk6r.rst @@ -0,0 +1,2 @@ +Python Debugger now supports additional location +``$XDG_CONFIG_HOME/pdb/.pdbrc`` for :file:`.pdbrc` file. From ca9b95fa3be9d9f30436fd2c2dcb4fd13c582e2d Mon Sep 17 00:00:00 2001 From: "Michael.Makukha" Date: Fri, 9 May 2025 12:06:52 +0300 Subject: [PATCH 4/4] Fix docs bug --- Doc/library/pdb.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Doc/library/pdb.rst b/Doc/library/pdb.rst index 81f39a11feec67..86bef68c86d7bf 100644 --- a/Doc/library/pdb.rst +++ b/Doc/library/pdb.rst @@ -385,7 +385,7 @@ ignored. This is particularly useful for aliases. Supported locations for :file:`.pdbrc` file are 1. ``$XDG_CONFIG_HOME/pdb`` (defaults to ``~/.config/pdb``, if environment - variable :envvar:`XDG_CONFIG_HOME` is not set) + variable ``XDG_CONFIG_HOME`` is not set) 2. User's home directory 3. Current working directory